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
commit dbdf28d0a0
61 changed files with 3998 additions and 1344 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

After

Width:  |  Height:  |  Size: 238 KiB

View file

@ -1868,6 +1868,9 @@ stickersSettings: sprite(140px, 124px, 21px, 22px);
savedGifsOver: sprite(329px, 286px, 21px, 22px); savedGifsOver: sprite(329px, 286px, 21px, 22px);
savedGifsActive: sprite(350px, 286px, 21px, 22px); savedGifsActive: sprite(350px, 286px, 21px, 22px);
stickersSettingsUnreadSize: 17px;
stickersSettingsUnreadPosition: point(4px, 5px);
emojiPanCategories: #f7f7f7; emojiPanCategories: #f7f7f7;
rbEmoji: flatCheckbox { rbEmoji: flatCheckbox {
@ -2141,7 +2144,9 @@ mvCaptionRadius: 2px;
mvCaptionBg: #11111180; mvCaptionBg: #11111180;
mvCaptionFont: font(fsize); mvCaptionFont: font(fsize);
medviewSaveMsgCheck: sprite(311px, 309px, 22px, 18px); medviewSaveMsgCheck: icon {
{ "mediaview_save_check", #ffffff }
};
medviewSaveMsgFont: font(16px); medviewSaveMsgFont: font(16px);
medviewSaveMsgPadding: margins(55px, 19px, 29px, 20px); medviewSaveMsgPadding: margins(55px, 19px, 29px, 20px);
medviewSaveMsgCheckPos: point(23px, 21px); medviewSaveMsgCheckPos: point(23px, 21px);

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

View file

@ -602,6 +602,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_group_invite_want_join_channel" = "Do you want to join the channel «{title}»?"; "lng_group_invite_want_join_channel" = "Do you want to join the channel «{title}»?";
"lng_group_invite_join" = "Join"; "lng_group_invite_join" = "Join";
"lng_group_invite_members" = "{count:_not_used_|# member|# members}, among them:";
"lng_group_invite_link" = "Invite link:"; "lng_group_invite_link" = "Invite link:";
"lng_group_invite_create" = "Create an invite link"; "lng_group_invite_create" = "Create an invite link";
"lng_group_invite_about" = "Telegram users will be able to join\nyour group by following this link."; "lng_group_invite_about" = "Telegram users will be able to join\nyour group by following this link.";
@ -680,15 +682,20 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_stickers_add_pack" = "Add stickers"; "lng_stickers_add_pack" = "Add stickers";
"lng_stickers_share_pack" = "Share Stickers"; "lng_stickers_share_pack" = "Share Stickers";
"lng_stickers_not_found" = "Sticker pack not found."; "lng_stickers_not_found" = "Sticker pack not found.";
"lng_stickers_too_many_packs" = "You have too many sticker packs. Please remove some first."; "lng_stickers_packs_archived" = "Some of your unused stickers have been archived to make room for the sets you've activated.";
"lng_stickers_archived" = "Archived Stickers";
"lng_stickers_copied" = "Sticker pack link copied to clipboard."; "lng_stickers_copied" = "Sticker pack link copied to clipboard.";
"lng_stickers_default_set" = "Great Minds"; "lng_stickers_default_set" = "Great Minds";
"lng_stickers_you_have" = "Manage and reorder sticker packs"; "lng_stickers_you_have" = "Manage and reorder sticker packs";
"lng_stickers_packs" = "Sticker Packs"; "lng_stickers_packs" = "Sticker Packs";
"lng_stickers_reorder" = "Click and drag to reorder sticker packs"; "lng_stickers_reorder" = "Click and drag to reorder sticker packs";
"lng_stickers_featured" = "Featured Stickers";
"lng_stickers_clear_recent" = "Clear";
"lng_stickers_clear_recent_sure" = "Are you sure you want to clear your frequently used stickers list?";
"lng_stickers_remove" = "Delete"; "lng_stickers_remove" = "Delete";
"lng_stickers_return" = "Undo"; "lng_stickers_return" = "Undo";
"lng_stickers_restore" = "Restore"; "lng_stickers_restore" = "Restore";
"lng_stickers_add" = "Add";
"lng_stickers_count" = "{count:Loading...|# sticker|# stickers}"; "lng_stickers_count" = "{count:Loading...|# sticker|# stickers}";
"lng_in_dlg_photo" = "Photo"; "lng_in_dlg_photo" = "Photo";

View file

@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,60,0 FILEVERSION 0,9,61,0
PRODUCTVERSION 0,9,60,0 PRODUCTVERSION 0,9,61,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -51,10 +51,10 @@ BEGIN
BLOCK "040904b0" BLOCK "040904b0"
BEGIN BEGIN
VALUE "CompanyName", "Telegram Messenger LLP" VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileVersion", "0.9.60.0" VALUE "FileVersion", "0.9.61.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop" VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.9.60.0" VALUE "ProductVersion", "0.9.61.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,60,0 FILEVERSION 0,9,61,0
PRODUCTVERSION 0,9,60,0 PRODUCTVERSION 0,9,61,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -43,10 +43,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Telegram Messenger LLP" VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Updater" VALUE "FileDescription", "Telegram Updater"
VALUE "FileVersion", "0.9.60.0" VALUE "FileVersion", "0.9.61.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop" VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.9.60.0" VALUE "ProductVersion", "0.9.61.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -923,12 +923,12 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
_stickerSetRequests.remove(setId); _stickerSetRequests.remove(setId);
if (result.type() != mtpc_messages_stickerSet) return; if (result.type() != mtpc_messages_stickerSet) return;
const auto &d(result.c_messages_stickerSet()); auto &d(result.c_messages_stickerSet());
if (d.vset.type() != mtpc_stickerSet) return; if (d.vset.type() != mtpc_stickerSet) return;
const auto &s(d.vset.c_stickerSet()); auto &s(d.vset.c_stickerSet());
Stickers::Sets &sets(Global::RefStickerSets()); auto &sets = Global::RefStickerSets();
auto it = sets.find(setId); auto it = sets.find(setId);
if (it == sets.cend()) return; if (it == sets.cend()) return;
@ -936,7 +936,9 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
it->hash = s.vhash.v; it->hash = s.vhash.v;
it->shortName = qs(s.vshort_name); it->shortName = qs(s.vshort_name);
it->title = stickerSetTitle(s); it->title = stickerSetTitle(s);
it->flags = s.vflags.v; auto clientFlags = it->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_not_loaded | MTPDstickerSet_ClientFlag::f_special);
it->flags = s.vflags.v | clientFlags;
it->flags &= ~MTPDstickerSet_ClientFlag::f_not_loaded;
const auto &d_docs(d.vdocuments.c_vector().v); const auto &d_docs(d.vdocuments.c_vector().v);
auto custom = sets.find(Stickers::CustomSetId); auto custom = sets.find(Stickers::CustomSetId);
@ -1002,7 +1004,14 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
Local::writeUserSettings(); Local::writeUserSettings();
} }
Local::writeStickers(); if (it->flags & MTPDstickerSet::Flag::f_installed) {
if (!(it->flags & MTPDstickerSet::Flag::f_archived)) {
Local::writeInstalledStickers();
}
}
if (it->flags & MTPDstickerSet_ClientFlag::f_featured) {
Local::writeFeaturedStickers();
}
if (App::main()) emit App::main()->stickersUpdated(); if (App::main()) emit App::main()->stickersUpdated();
} }

View file

@ -30,6 +30,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "data/data_abstract_structure.h" #include "data/data_abstract_structure.h"
#include "history/history_service_layout.h" #include "history/history_service_layout.h"
#include "media/media_audio.h" #include "media/media_audio.h"
#include "inline_bots/inline_bot_layout_item.h"
#include "application.h" #include "application.h"
#include "fileuploader.h" #include "fileuploader.h"
#include "mainwidget.h" #include "mainwidget.h"
@ -382,397 +383,413 @@ namespace {
return (online > now); return (online > now);
} }
UserData *feedUsers(const MTPVector<MTPUser> &users) { UserData *feedUser(const MTPUser &user) {
UserData *result = nullptr; UserData *data = nullptr;
for_const (auto &user, users.c_vector().v) { bool wasContact = false, minimal = false;
UserData *data = nullptr; const MTPUserStatus *status = 0, emptyStatus = MTP_userStatusEmpty();
bool wasContact = false, minimal = false;
const MTPUserStatus *status = 0, emptyStatus = MTP_userStatusEmpty();
Notify::PeerUpdate update; Notify::PeerUpdate update;
using UpdateFlag = Notify::PeerUpdate::Flag; using UpdateFlag = Notify::PeerUpdate::Flag;
switch (user.type()) { switch (user.type()) {
case mtpc_userEmpty: { case mtpc_userEmpty: {
const auto &d(user.c_userEmpty()); auto &d(user.c_userEmpty());
PeerId peer(peerFromUser(d.vid.v)); PeerId peer(peerFromUser(d.vid.v));
data = App::user(peer); data = App::user(peer);
auto canShareThisContact = data->canShareThisContactFast(); auto canShareThisContact = data->canShareThisContactFast();
wasContact = data->isContact(); wasContact = data->isContact();
data->input = MTP_inputPeerUser(d.vid, MTP_long(0)); data->input = MTP_inputPeerUser(d.vid, MTP_long(0));
data->inputUser = MTP_inputUser(d.vid, MTP_long(0)); data->inputUser = MTP_inputUser(d.vid, MTP_long(0));
data->setName(lang(lng_deleted), QString(), QString(), QString());
data->setPhoto(MTP_userProfilePhotoEmpty());
data->access = UserNoAccess;
data->flags = 0;
data->setBotInfoVersion(-1);
status = &emptyStatus;
data->contact = -1;
if (canShareThisContact != data->canShareThisContactFast()) update.flags |= UpdateFlag::UserCanShareContact;
if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact;
} break;
case mtpc_user: {
auto &d(user.c_user());
minimal = d.is_min();
PeerId peer(peerFromUser(d.vid.v));
data = App::user(peer);
auto canShareThisContact = data->canShareThisContactFast();
wasContact = data->isContact();
if (!minimal) {
data->flags = d.vflags.v;
if (d.is_self()) {
data->input = MTP_inputPeerSelf();
data->inputUser = MTP_inputUserSelf();
} else if (!d.has_access_hash()) {
data->input = MTP_inputPeerUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access));
data->inputUser = MTP_inputUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access));
} else {
data->input = MTP_inputPeerUser(d.vid, d.vaccess_hash);
data->inputUser = MTP_inputUser(d.vid, d.vaccess_hash);
}
if (d.is_restricted()) {
data->setRestrictionReason(extractRestrictionReason(qs(d.vrestriction_reason)));
} else {
data->setRestrictionReason(QString());
}
}
if (d.is_deleted()) {
if (!data->phone().isEmpty()) {
data->setPhone(QString());
update.flags |= UpdateFlag::UserPhoneChanged;
}
data->setName(lang(lng_deleted), QString(), QString(), QString()); data->setName(lang(lng_deleted), QString(), QString(), QString());
data->setPhoto(MTP_userProfilePhotoEmpty()); data->setPhoto(MTP_userProfilePhotoEmpty());
data->access = UserNoAccess; data->access = UserNoAccess;
data->flags = 0;
data->setBotInfoVersion(-1);
status = &emptyStatus; status = &emptyStatus;
data->contact = -1; } else {
// apply first_name and last_name from minimal user only if we don't have
// local values for first name and last name already, otherwise skip
bool noLocalName = data->firstName.isEmpty() && data->lastName.isEmpty();
QString fname = (!minimal || noLocalName) ? (d.has_first_name() ? textOneLine(qs(d.vfirst_name)) : QString()) : data->firstName;
QString lname = (!minimal || noLocalName) ? (d.has_last_name() ? textOneLine(qs(d.vlast_name)) : QString()) : data->lastName;
if (canShareThisContact != data->canShareThisContactFast()) update.flags |= UpdateFlag::UserCanShareContact; QString phone = minimal ? data->phone() : (d.has_phone() ? qs(d.vphone) : QString());
if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact; QString uname = minimal ? data->username : (d.has_username() ? textOneLine(qs(d.vusername)) : QString());
} break;
case mtpc_user: {
const auto &d(user.c_user());
minimal = d.is_min();
PeerId peer(peerFromUser(d.vid.v)); bool phoneChanged = (data->phone() != phone);
data = App::user(peer); if (phoneChanged) {
auto canShareThisContact = data->canShareThisContactFast(); data->setPhone(phone);
wasContact = data->isContact(); update.flags |= UpdateFlag::UserPhoneChanged;
if (!minimal) {
data->flags = d.vflags.v;
if (d.is_self()) {
data->input = MTP_inputPeerSelf();
data->inputUser = MTP_inputUserSelf();
} else if (!d.has_access_hash()) {
data->input = MTP_inputPeerUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access));
data->inputUser = MTP_inputUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access));
} else {
data->input = MTP_inputPeerUser(d.vid, d.vaccess_hash);
data->inputUser = MTP_inputUser(d.vid, d.vaccess_hash);
}
if (d.is_restricted()) {
data->setRestrictionReason(extractRestrictionReason(qs(d.vrestriction_reason)));
} else {
data->setRestrictionReason(QString());
}
} }
if (d.is_deleted()) { bool nameChanged = (data->firstName != fname) || (data->lastName != lname);
if (!data->phone().isEmpty()) {
data->setPhone(QString()); bool showPhone = !isServiceUser(data->id) && !d.is_self() && !d.is_contact() && !d.is_mutual_contact();
update.flags |= UpdateFlag::UserPhoneChanged; bool showPhoneChanged = !isServiceUser(data->id) && !d.is_self() && ((showPhone && data->contact) || (!showPhone && !data->contact));
} if (minimal) {
data->setName(lang(lng_deleted), QString(), QString(), QString()); showPhoneChanged = false;
data->setPhoto(MTP_userProfilePhotoEmpty()); showPhone = !isServiceUser(data->id) && (data->id != peerFromUser(MTP::authedId())) && !data->contact;
data->access = UserNoAccess; }
status = &emptyStatus;
// see also Local::readPeer
QString pname = (showPhoneChanged || phoneChanged || nameChanged) ? ((showPhone && !phone.isEmpty()) ? formatPhone(phone) : QString()) : data->nameOrPhone;
if (!minimal && d.is_self() && uname != data->username) {
SignalHandlers::setCrashAnnotation("Username", uname);
}
data->setName(fname, lname, pname, uname);
if (d.has_photo()) {
data->setPhoto(d.vphoto);
} else { } else {
// apply first_name and last_name from minimal user only if we don't have data->setPhoto(MTP_userProfilePhotoEmpty());
// local values for first name and last name already, otherwise skip
bool noLocalName = data->firstName.isEmpty() && data->lastName.isEmpty();
QString fname = (!minimal || noLocalName) ? (d.has_first_name() ? textOneLine(qs(d.vfirst_name)) : QString()) : data->firstName;
QString lname = (!minimal || noLocalName) ? (d.has_last_name() ? textOneLine(qs(d.vlast_name)) : QString()) : data->lastName;
QString phone = minimal ? data->phone() : (d.has_phone() ? qs(d.vphone) : QString());
QString uname = minimal ? data->username : (d.has_username() ? textOneLine(qs(d.vusername)) : QString());
bool phoneChanged = (data->phone() != phone);
if (phoneChanged) {
data->setPhone(phone);
update.flags |= UpdateFlag::UserPhoneChanged;
}
bool nameChanged = (data->firstName != fname) || (data->lastName != lname);
bool showPhone = !isServiceUser(data->id) && !d.is_self() && !d.is_contact() && !d.is_mutual_contact();
bool showPhoneChanged = !isServiceUser(data->id) && !d.is_self() && ((showPhone && data->contact) || (!showPhone && !data->contact));
if (minimal) {
showPhoneChanged = false;
showPhone = !isServiceUser(data->id) && (data->id != peerFromUser(MTP::authedId())) && !data->contact;
}
// see also Local::readPeer
QString pname = (showPhoneChanged || phoneChanged || nameChanged) ? ((showPhone && !phone.isEmpty()) ? formatPhone(phone) : QString()) : data->nameOrPhone;
if (!minimal && d.is_self() && uname != data->username) {
SignalHandlers::setCrashAnnotation("Username", uname);
}
data->setName(fname, lname, pname, uname);
if (d.has_photo()) {
data->setPhoto(d.vphoto);
} else {
data->setPhoto(MTP_userProfilePhotoEmpty());
}
if (d.has_access_hash()) data->access = d.vaccess_hash.v;
status = d.has_status() ? &d.vstatus : &emptyStatus;
} }
if (!minimal) { if (d.has_access_hash()) data->access = d.vaccess_hash.v;
if (d.has_bot_info_version()) { status = d.has_status() ? &d.vstatus : &emptyStatus;
data->setBotInfoVersion(d.vbot_info_version.v); }
data->botInfo->readsAllHistory = d.is_bot_chat_history(); if (!minimal) {
if (data->botInfo->cantJoinGroups != d.is_bot_nochats()) { if (d.has_bot_info_version()) {
data->botInfo->cantJoinGroups = d.is_bot_nochats(); data->setBotInfoVersion(d.vbot_info_version.v);
update.flags |= UpdateFlag::BotCanAddToGroups; data->botInfo->readsAllHistory = d.is_bot_chat_history();
} if (data->botInfo->cantJoinGroups != d.is_bot_nochats()) {
data->botInfo->inlinePlaceholder = d.has_bot_inline_placeholder() ? '_' + qs(d.vbot_inline_placeholder) : QString(); data->botInfo->cantJoinGroups = d.is_bot_nochats();
} else { update.flags |= UpdateFlag::BotCanAddToGroups;
data->setBotInfoVersion(-1);
}
data->contact = (d.is_contact() || d.is_mutual_contact()) ? 1 : (data->phone().isEmpty() ? -1 : 0);
if (data->contact == 1 && cReportSpamStatuses().value(data->id, dbiprsHidden) != dbiprsHidden) {
cRefReportSpamStatuses().insert(data->id, dbiprsHidden);
Local::writeReportSpamStatuses();
}
if (d.is_self() && ::self != data) {
::self = data;
if (App::wnd()) App::wnd()->updateGlobalMenu();
} }
data->botInfo->inlinePlaceholder = d.has_bot_inline_placeholder() ? '_' + qs(d.vbot_inline_placeholder) : QString();
} else {
data->setBotInfoVersion(-1);
} }
data->contact = (d.is_contact() || d.is_mutual_contact()) ? 1 : (data->phone().isEmpty() ? -1 : 0);
if (canShareThisContact != data->canShareThisContactFast()) update.flags |= UpdateFlag::UserCanShareContact; if (data->contact == 1 && cReportSpamStatuses().value(data->id, dbiprsHidden) != dbiprsHidden) {
if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact; cRefReportSpamStatuses().insert(data->id, dbiprsHidden);
} break; Local::writeReportSpamStatuses();
}
if (!data) continue;
if (minimal) {
if (data->loadedStatus == PeerData::NotLoaded) {
data->loadedStatus = PeerData::MinimalLoaded;
} }
} else if (data->loadedStatus != PeerData::FullLoaded) { if (d.is_self() && ::self != data) {
data->loadedStatus = PeerData::FullLoaded; ::self = data;
} if (App::wnd()) App::wnd()->updateGlobalMenu();
auto oldOnlineTill = data->onlineTill;
if (status && !minimal) switch (status->type()) {
case mtpc_userStatusEmpty: data->onlineTill = 0; break;
case mtpc_userStatusRecently:
if (data->onlineTill > -10) { // don't modify pseudo-online
data->onlineTill = -2;
}
break;
case mtpc_userStatusLastWeek: data->onlineTill = -3; break;
case mtpc_userStatusLastMonth: data->onlineTill = -4; break;
case mtpc_userStatusOffline: data->onlineTill = status->c_userStatusOffline().vwas_online.v; break;
case mtpc_userStatusOnline: data->onlineTill = status->c_userStatusOnline().vexpires.v; break;
}
if (oldOnlineTill != data->onlineTill) {
update.flags |= UpdateFlag::UserOnlineChanged;
}
if (data->contact < 0 && !data->phone().isEmpty() && peerToUser(data->id) != MTP::authedId()) {
data->contact = 0;
}
if (App::main()) {
if ((data->contact > 0 && !wasContact) || (wasContact && data->contact < 1)) {
Notify::userIsContactChanged(data);
}
markPeerUpdated(data);
if (update.flags) {
update.peer = data;
Notify::peerUpdatedDelayed(update);
} }
} }
result = data;
if (canShareThisContact != data->canShareThisContactFast()) update.flags |= UpdateFlag::UserCanShareContact;
if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact;
} break;
}
if (!data) {
return nullptr;
}
if (minimal) {
if (data->loadedStatus == PeerData::NotLoaded) {
data->loadedStatus = PeerData::MinimalLoaded;
}
} else if (data->loadedStatus != PeerData::FullLoaded) {
data->loadedStatus = PeerData::FullLoaded;
}
auto oldOnlineTill = data->onlineTill;
if (status && !minimal) switch (status->type()) {
case mtpc_userStatusEmpty: data->onlineTill = 0; break;
case mtpc_userStatusRecently:
if (data->onlineTill > -10) { // don't modify pseudo-online
data->onlineTill = -2;
}
break;
case mtpc_userStatusLastWeek: data->onlineTill = -3; break;
case mtpc_userStatusLastMonth: data->onlineTill = -4; break;
case mtpc_userStatusOffline: data->onlineTill = status->c_userStatusOffline().vwas_online.v; break;
case mtpc_userStatusOnline: data->onlineTill = status->c_userStatusOnline().vexpires.v; break;
}
if (oldOnlineTill != data->onlineTill) {
update.flags |= UpdateFlag::UserOnlineChanged;
}
if (data->contact < 0 && !data->phone().isEmpty() && peerToUser(data->id) != MTP::authedId()) {
data->contact = 0;
}
if (App::main()) {
if ((data->contact > 0 && !wasContact) || (wasContact && data->contact < 1)) {
Notify::userIsContactChanged(data);
}
markPeerUpdated(data);
if (update.flags) {
update.peer = data;
Notify::peerUpdatedDelayed(update);
}
}
return data;
}
UserData *feedUsers(const MTPVector<MTPUser> &users) {
UserData *result = nullptr;
for_const (auto &user, users.c_vector().v) {
if (auto feededUser = feedUser(user)) {
result = feededUser;
}
} }
return result; return result;
} }
PeerData *feedChat(const MTPChat &chat) {
PeerData *data = nullptr;
bool minimal = false;
Notify::PeerUpdate update;
using UpdateFlag = Notify::PeerUpdate::Flag;
switch (chat.type()) {
case mtpc_chat: {
auto &d(chat.c_chat());
data = App::chat(peerFromChat(d.vid.v));
auto cdata = data->asChat();
auto canEdit = cdata->canEdit();
if (cdata->version < d.vversion.v) {
cdata->version = d.vversion.v;
cdata->invalidateParticipants();
}
data->input = MTP_inputPeerChat(d.vid);
cdata->setName(qs(d.vtitle));
cdata->setPhoto(d.vphoto);
cdata->date = d.vdate.v;
if (d.has_migrated_to() && d.vmigrated_to.type() == mtpc_inputChannel) {
const auto &c(d.vmigrated_to.c_inputChannel());
ChannelData *channel = App::channel(peerFromChannel(c.vchannel_id));
if (!channel->mgInfo) {
channel->flags |= MTPDchannel::Flag::f_megagroup;
channel->flagsUpdated();
}
if (!channel->access) {
channel->input = MTP_inputPeerChannel(c.vchannel_id, c.vaccess_hash);
channel->inputChannel = d.vmigrated_to;
channel->access = d.vmigrated_to.c_inputChannel().vaccess_hash.v;
}
bool updatedTo = (cdata->migrateToPtr != channel), updatedFrom = (channel->mgInfo->migrateFromPtr != cdata);
if (updatedTo) {
cdata->migrateToPtr = channel;
}
if (updatedFrom) {
channel->mgInfo->migrateFromPtr = cdata;
if (History *h = App::historyLoaded(cdata->id)) {
if (History *hto = App::historyLoaded(channel->id)) {
if (!h->isEmpty()) {
h->clear(true);
}
if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) {
App::removeDialog(h);
}
}
}
Notify::migrateUpdated(channel);
update.flags |= UpdateFlag::MigrationChanged;
}
if (updatedTo) {
Notify::migrateUpdated(cdata);
update.flags |= UpdateFlag::MigrationChanged;
}
}
if (!(cdata->flags & MTPDchat::Flag::f_admins_enabled) && (d.vflags.v & MTPDchat::Flag::f_admins_enabled)) {
cdata->invalidateParticipants();
}
cdata->flags = d.vflags.v;
cdata->count = d.vparticipants_count.v;
cdata->isForbidden = false;
if (canEdit != cdata->canEdit()) {
update.flags |= UpdateFlag::ChatCanEdit;
}
} break;
case mtpc_chatForbidden: {
auto &d(chat.c_chatForbidden());
data = App::chat(peerFromChat(d.vid.v));
auto cdata = data->asChat();
auto canEdit = cdata->canEdit();
data->input = MTP_inputPeerChat(d.vid);
cdata->setName(qs(d.vtitle));
cdata->setPhoto(MTP_chatPhotoEmpty());
cdata->date = 0;
cdata->count = -1;
cdata->invalidateParticipants();
cdata->flags = 0;
cdata->isForbidden = true;
if (canEdit != cdata->canEdit()) {
update.flags |= UpdateFlag::ChatCanEdit;
}
} break;
case mtpc_channel: {
auto &d(chat.c_channel());
auto peerId = peerFromChannel(d.vid.v);
minimal = d.is_min();
if (minimal) {
data = App::channelLoaded(peerId);
if (!data) {
return nullptr; // minimal is not loaded, need to make getDifference
}
} else {
data = App::channel(peerId);
data->input = MTP_inputPeerChannel(d.vid, d.has_access_hash() ? d.vaccess_hash : MTP_long(0));
}
auto cdata = data->asChannel();
auto wasInChannel = cdata->amIn();
auto canEditPhoto = cdata->canEditPhoto();
auto canViewAdmins = cdata->canViewAdmins();
auto canViewMembers = cdata->canViewMembers();
auto canAddMembers = cdata->canAddMembers();
auto wasEditor = cdata->amEditor();
if (minimal) {
auto mask = MTPDchannel::Flag::f_broadcast | MTPDchannel::Flag::f_verified | MTPDchannel::Flag::f_megagroup | MTPDchannel::Flag::f_democracy;
cdata->flags = (cdata->flags & ~mask) | (d.vflags.v & mask);
} else {
cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash);
cdata->access = d.vaccess_hash.v;
cdata->date = d.vdate.v;
if (cdata->version < d.vversion.v) {
cdata->version = d.vversion.v;
}
if (d.is_restricted()) {
cdata->setRestrictionReason(extractRestrictionReason(qs(d.vrestriction_reason)));
} else {
cdata->setRestrictionReason(QString());
}
cdata->flags = d.vflags.v;
}
cdata->flagsUpdated();
QString uname = d.has_username() ? textOneLine(qs(d.vusername)) : QString();
cdata->setName(qs(d.vtitle), uname);
cdata->isForbidden = false;
cdata->setPhoto(d.vphoto);
if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn;
if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto;
if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins;
if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers;
if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers;
if (wasEditor != cdata->amEditor()) {
cdata->selfAdminUpdated();
update.flags |= (UpdateFlag::ChannelAmEditor | UpdateFlag::AdminsChanged);
}
} break;
case mtpc_channelForbidden: {
auto &d(chat.c_channelForbidden());
auto peerId = peerFromChannel(d.vid.v);
data = App::channel(peerId);
data->input = MTP_inputPeerChannel(d.vid, d.vaccess_hash);
auto cdata = data->asChannel();
auto wasInChannel = cdata->amIn();
auto canEditPhoto = cdata->canEditPhoto();
auto canViewAdmins = cdata->canViewAdmins();
auto canViewMembers = cdata->canViewMembers();
auto canAddMembers = cdata->canAddMembers();
auto wasEditor = cdata->amEditor();
cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash);
auto mask = mtpCastFlags(MTPDchannelForbidden::Flag::f_broadcast | MTPDchannelForbidden::Flag::f_megagroup);
cdata->flags = (cdata->flags & ~mask) | (mtpCastFlags(d.vflags) & mask);
cdata->flagsUpdated();
cdata->setName(qs(d.vtitle), QString());
cdata->access = d.vaccess_hash.v;
cdata->setPhoto(MTP_chatPhotoEmpty());
cdata->date = 0;
cdata->setMembersCount(0);
cdata->isForbidden = true;
if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn;
if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto;
if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins;
if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers;
if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers;
if (wasEditor != cdata->amEditor()) {
cdata->selfAdminUpdated();
update.flags |= (UpdateFlag::ChannelAmEditor | UpdateFlag::AdminsChanged);
}
} break;
}
if (!data) {
return nullptr;
}
if (minimal) {
if (data->loadedStatus == PeerData::NotLoaded) {
data->loadedStatus = PeerData::MinimalLoaded;
}
} else if (data->loadedStatus != PeerData::FullLoaded) {
data->loadedStatus = PeerData::FullLoaded;
}
if (App::main()) {
markPeerUpdated(data);
if (update.flags) {
update.peer = data;
Notify::peerUpdatedDelayed(update);
}
}
return data;
}
PeerData *feedChats(const MTPVector<MTPChat> &chats) { PeerData *feedChats(const MTPVector<MTPChat> &chats) {
PeerData *result = nullptr; PeerData *result = nullptr;
for_const (auto &chat, chats.c_vector().v) { for_const (auto &chat, chats.c_vector().v) {
PeerData *data = nullptr; if (auto feededChat = feedChat(chat)) {
bool minimal = false; result = feededChat;
Notify::PeerUpdate update;
using UpdateFlag = Notify::PeerUpdate::Flag;
switch (chat.type()) {
case mtpc_chat: {
auto &d(chat.c_chat());
data = App::chat(peerFromChat(d.vid.v));
auto cdata = data->asChat();
auto canEdit = cdata->canEdit();
if (cdata->version < d.vversion.v) {
cdata->version = d.vversion.v;
cdata->invalidateParticipants();
}
data->input = MTP_inputPeerChat(d.vid);
cdata->setName(qs(d.vtitle));
cdata->setPhoto(d.vphoto);
cdata->date = d.vdate.v;
if (d.has_migrated_to() && d.vmigrated_to.type() == mtpc_inputChannel) {
const auto &c(d.vmigrated_to.c_inputChannel());
ChannelData *channel = App::channel(peerFromChannel(c.vchannel_id));
if (!channel->mgInfo) {
channel->flags |= MTPDchannel::Flag::f_megagroup;
channel->flagsUpdated();
}
if (!channel->access) {
channel->input = MTP_inputPeerChannel(c.vchannel_id, c.vaccess_hash);
channel->inputChannel = d.vmigrated_to;
channel->access = d.vmigrated_to.c_inputChannel().vaccess_hash.v;
}
bool updatedTo = (cdata->migrateToPtr != channel), updatedFrom = (channel->mgInfo->migrateFromPtr != cdata);
if (updatedTo) {
cdata->migrateToPtr = channel;
}
if (updatedFrom) {
channel->mgInfo->migrateFromPtr = cdata;
if (History *h = App::historyLoaded(cdata->id)) {
if (History *hto = App::historyLoaded(channel->id)) {
if (!h->isEmpty()) {
h->clear(true);
}
if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) {
App::removeDialog(h);
}
}
}
Notify::migrateUpdated(channel);
update.flags |= UpdateFlag::MigrationChanged;
}
if (updatedTo) {
Notify::migrateUpdated(cdata);
update.flags |= UpdateFlag::MigrationChanged;
}
}
if (!(cdata->flags & MTPDchat::Flag::f_admins_enabled) && (d.vflags.v & MTPDchat::Flag::f_admins_enabled)) {
cdata->invalidateParticipants();
}
cdata->flags = d.vflags.v;
cdata->count = d.vparticipants_count.v;
cdata->isForbidden = false;
if (canEdit != cdata->canEdit()) {
update.flags |= UpdateFlag::ChatCanEdit;
}
} break;
case mtpc_chatForbidden: {
auto &d(chat.c_chatForbidden());
data = App::chat(peerFromChat(d.vid.v));
auto cdata = data->asChat();
auto canEdit = cdata->canEdit();
data->input = MTP_inputPeerChat(d.vid);
cdata->setName(qs(d.vtitle));
cdata->setPhoto(MTP_chatPhotoEmpty());
cdata->date = 0;
cdata->count = -1;
cdata->invalidateParticipants();
cdata->flags = 0;
cdata->isForbidden = true;
if (canEdit != cdata->canEdit()) {
update.flags |= UpdateFlag::ChatCanEdit;
}
} break;
case mtpc_channel: {
auto &d(chat.c_channel());
auto peerId = peerFromChannel(d.vid.v);
minimal = d.is_min();
if (minimal) {
data = App::channelLoaded(peerId);
if (!data) {
continue; // minimal is not loaded, need to make getDifference
}
} else {
data = App::channel(peerId);
data->input = MTP_inputPeerChannel(d.vid, d.has_access_hash() ? d.vaccess_hash : MTP_long(0));
}
auto cdata = data->asChannel();
auto wasInChannel = cdata->amIn();
auto canEditPhoto = cdata->canEditPhoto();
auto canViewAdmins = cdata->canViewAdmins();
auto canViewMembers = cdata->canViewMembers();
auto canAddMembers = cdata->canAddMembers();
auto wasEditor = cdata->amEditor();
if (minimal) {
auto mask = MTPDchannel::Flag::f_broadcast | MTPDchannel::Flag::f_verified | MTPDchannel::Flag::f_megagroup | MTPDchannel::Flag::f_democracy;
cdata->flags = (cdata->flags & ~mask) | (d.vflags.v & mask);
} else {
cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash);
cdata->access = d.vaccess_hash.v;
cdata->date = d.vdate.v;
if (cdata->version < d.vversion.v) {
cdata->version = d.vversion.v;
}
if (d.is_restricted()) {
cdata->setRestrictionReason(extractRestrictionReason(qs(d.vrestriction_reason)));
} else {
cdata->setRestrictionReason(QString());
}
cdata->flags = d.vflags.v;
}
cdata->flagsUpdated();
QString uname = d.has_username() ? textOneLine(qs(d.vusername)) : QString();
cdata->setName(qs(d.vtitle), uname);
cdata->isForbidden = false;
cdata->setPhoto(d.vphoto);
if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn;
if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto;
if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins;
if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers;
if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers;
if (wasEditor != cdata->amEditor()) {
cdata->selfAdminUpdated();
update.flags |= (UpdateFlag::ChannelAmEditor | UpdateFlag::AdminsChanged);
}
} break;
case mtpc_channelForbidden: {
auto &d(chat.c_channelForbidden());
auto peerId = peerFromChannel(d.vid.v);
data = App::channel(peerId);
data->input = MTP_inputPeerChannel(d.vid, d.vaccess_hash);
auto cdata = data->asChannel();
auto wasInChannel = cdata->amIn();
auto canEditPhoto = cdata->canEditPhoto();
auto canViewAdmins = cdata->canViewAdmins();
auto canViewMembers = cdata->canViewMembers();
auto canAddMembers = cdata->canAddMembers();
auto wasEditor = cdata->amEditor();
cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash);
auto mask = mtpCastFlags(MTPDchannelForbidden::Flag::f_broadcast | MTPDchannelForbidden::Flag::f_megagroup);
cdata->flags = (cdata->flags & ~mask) | (mtpCastFlags(d.vflags) & mask);
cdata->flagsUpdated();
cdata->setName(qs(d.vtitle), QString());
cdata->access = d.vaccess_hash.v;
cdata->setPhoto(MTP_chatPhotoEmpty());
cdata->date = 0;
cdata->setMembersCount(0);
cdata->isForbidden = true;
if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn;
if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto;
if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins;
if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers;
if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers;
if (wasEditor != cdata->amEditor()) {
cdata->selfAdminUpdated();
update.flags |= (UpdateFlag::ChannelAmEditor | UpdateFlag::AdminsChanged);
}
} break;
} }
if (!data) continue;
if (minimal) {
if (data->loadedStatus == PeerData::NotLoaded) {
data->loadedStatus = PeerData::MinimalLoaded;
}
} else if (data->loadedStatus != PeerData::FullLoaded) {
data->loadedStatus = PeerData::FullLoaded;
}
if (App::main()) {
markPeerUpdated(data);
if (update.flags) {
update.peer = data;
Notify::peerUpdatedDelayed(update);
}
}
result = data;
} }
return result; return result;
} }
@ -1452,7 +1469,7 @@ namespace {
switch (document.type()) { switch (document.type()) {
case mtpc_document: { case mtpc_document: {
const auto &d(document.c_document()); const auto &d(document.c_document());
return App::documentSet(d.vid.v, 0, d.vaccess_hash.v, d.vdate.v, d.vattributes.c_vector().v, qs(d.vmime_type), ImagePtr(thumb, "JPG"), d.vdc_id.v, d.vsize.v, StorageImageLocation()); return App::documentSet(d.vid.v, 0, d.vaccess_hash.v, d.vversion.v, d.vdate.v, d.vattributes.c_vector().v, qs(d.vmime_type), ImagePtr(thumb, "JPG"), d.vdc_id.v, d.vsize.v, StorageImageLocation());
} break; } break;
case mtpc_documentEmpty: return App::document(document.c_documentEmpty().vid.v); case mtpc_documentEmpty: return App::document(document.c_documentEmpty().vid.v);
} }
@ -1465,14 +1482,14 @@ namespace {
return feedDocument(document.c_document(), convert); return feedDocument(document.c_document(), convert);
} break; } break;
case mtpc_documentEmpty: { case mtpc_documentEmpty: {
return App::documentSet(document.c_documentEmpty().vid.v, convert, 0, 0, QVector<MTPDocumentAttribute>(), QString(), ImagePtr(), 0, 0, StorageImageLocation()); return App::documentSet(document.c_documentEmpty().vid.v, convert, 0, 0, 0, QVector<MTPDocumentAttribute>(), QString(), ImagePtr(), 0, 0, StorageImageLocation());
} break; } break;
} }
return App::document(0); return App::document(0);
} }
DocumentData *feedDocument(const MTPDdocument &document, DocumentData *convert) { DocumentData *feedDocument(const MTPDdocument &document, DocumentData *convert) {
return App::documentSet(document.vid.v, convert, document.vaccess_hash.v, document.vdate.v, document.vattributes.c_vector().v, qs(document.vmime_type), App::image(document.vthumb), document.vdc_id.v, document.vsize.v, App::imageLocation(document.vthumb)); return App::documentSet(document.vid.v, convert, document.vaccess_hash.v, document.vversion.v, document.vdate.v, document.vattributes.c_vector().v, qs(document.vmime_type), App::image(document.vthumb), document.vdc_id.v, document.vsize.v, App::imageLocation(document.vthumb));
} }
WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert) { WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert) {
@ -1629,11 +1646,13 @@ namespace {
return i.value(); return i.value();
} }
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation) { DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 version, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation) {
bool versionChanged = false;
bool sentSticker = false; bool sentSticker = false;
if (convert) { if (convert) {
MediaKey oldKey = convert->mediaKey(); MediaKey oldKey = convert->mediaKey();
if (convert->id != document) { bool idChanged = (convert->id != document);
if (idChanged) {
DocumentsData::iterator i = ::documentsData.find(convert->id); DocumentsData::iterator i = ::documentsData.find(convert->id);
if (i != ::documentsData.cend() && i.value() == convert) { if (i != ::documentsData.cend() && i.value() == convert) {
::documentsData.erase(i); ::documentsData.erase(i);
@ -1645,10 +1664,11 @@ namespace {
} }
if (date) { if (date) {
convert->setattributes(attributes); convert->setattributes(attributes);
versionChanged = convert->setRemoteVersion(version);
convert->setRemoteLocation(dc, access); convert->setRemoteLocation(dc, access);
convert->date = date; convert->date = date;
convert->mime = mime; convert->mime = mime;
if (!thumb->isNull() && (convert->thumb->isNull() || convert->thumb->width() < thumb->width() || convert->thumb->height() < thumb->height())) { if (!thumb->isNull() && (convert->thumb->isNull() || convert->thumb->width() < thumb->width() || convert->thumb->height() < thumb->height() || versionChanged)) {
updateImage(convert->thumb, thumb); updateImage(convert->thumb, thumb);
} }
convert->size = size; convert->size = size;
@ -1658,7 +1678,7 @@ namespace {
} }
MediaKey newKey = convert->mediaKey(); MediaKey newKey = convert->mediaKey();
if (newKey != oldKey) { if (idChanged) {
if (convert->voice()) { if (convert->voice()) {
Local::copyAudio(oldKey, newKey); Local::copyAudio(oldKey, newKey);
} else if (convert->sticker() || convert->isAnimation()) { } else if (convert->sticker() || convert->isAnimation()) {
@ -1677,7 +1697,7 @@ namespace {
if (convert) { if (convert) {
result = convert; result = convert;
} else { } else {
result = DocumentData::create(document, dc, access, attributes); result = DocumentData::create(document, dc, access, version, attributes);
result->date = date; result->date = date;
result->mime = mime; result->mime = mime;
result->thumb = thumb; result->thumb = thumb;
@ -1692,12 +1712,13 @@ namespace {
result = i.value(); result = i.value();
if (result != convert && date) { if (result != convert && date) {
result->setattributes(attributes); result->setattributes(attributes);
versionChanged = result->setRemoteVersion(version);
if (!result->isValid()) { if (!result->isValid()) {
result->setRemoteLocation(dc, access); result->setRemoteLocation(dc, access);
} }
result->date = date; result->date = date;
result->mime = mime; result->mime = mime;
if (!thumb->isNull() && (result->thumb->isNull() || result->thumb->width() < thumb->width() || result->thumb->height() < thumb->height())) { if (!thumb->isNull() && (result->thumb->isNull() || result->thumb->width() < thumb->width() || result->thumb->height() < thumb->height() || versionChanged)) {
result->thumb = thumb; result->thumb = thumb;
} }
result->size = size; result->size = size;
@ -1710,6 +1731,30 @@ namespace {
if (sentSticker && App::main()) { if (sentSticker && App::main()) {
App::main()->incrementSticker(result); App::main()->incrementSticker(result);
} }
if (versionChanged) {
if (result->sticker() && result->sticker()->set.type() == mtpc_inputStickerSetID) {
auto it = Global::StickerSets().constFind(result->sticker()->set.c_inputStickerSetID().vid.v);
if (it != Global::StickerSets().cend()) {
if (it->id == Stickers::CloudRecentSetId) {
Local::writeRecentStickers();
} else if (it->flags & MTPDstickerSet::Flag::f_archived) {
Local::writeArchivedStickers();
} else if (it->flags & MTPDstickerSet::Flag::f_installed) {
Local::writeInstalledStickers();
}
if (it->flags & MTPDstickerSet_ClientFlag::f_featured) {
Local::writeFeaturedStickers();
}
}
}
auto &items = App::documentItems();
auto i = items.constFind(result);
if (i != items.cend()) {
for (auto j = i->cbegin(), e = i->cend(); j != e; ++j) {
j.key()->setPendingInitDimensions();
}
}
}
return result; return result;
} }
@ -1977,6 +2022,11 @@ namespace {
Global::SetStickerSets(Stickers::Sets()); Global::SetStickerSets(Stickers::Sets());
Global::SetStickerSetsOrder(Stickers::Order()); Global::SetStickerSetsOrder(Stickers::Order());
Global::SetLastStickersUpdate(0); Global::SetLastStickersUpdate(0);
Global::SetLastRecentStickersUpdate(0);
Global::SetFeaturedStickerSetsOrder(Stickers::Order());
Global::SetFeaturedStickerSetsUnreadCount(0);
Global::SetLastFeaturedStickersUpdate(0);
Global::SetArchivedStickerSetsOrder(Stickers::Order());
cSetSavedGifs(SavedGifs()); cSetSavedGifs(SavedGifs());
cSetLastSavedGifsUpdate(0); cSetLastSavedGifsUpdate(0);
cSetReportSpamStatuses(ReportSpamStatuses()); cSetReportSpamStatuses(ReportSpamStatuses());

View file

@ -65,7 +65,9 @@ namespace App {
bool onlineColorUse(UserData *user, TimeId now); bool onlineColorUse(UserData *user, TimeId now);
bool onlineColorUse(TimeId online, TimeId now); bool onlineColorUse(TimeId online, TimeId now);
UserData *feedUser(const MTPUser &user);
UserData *feedUsers(const MTPVector<MTPUser> &users); // returns last user UserData *feedUsers(const MTPVector<MTPUser> &users); // returns last user
PeerData *feedChat(const MTPChat &chat);
PeerData *feedChats(const MTPVector<MTPChat> &chats); // returns last chat PeerData *feedChats(const MTPVector<MTPChat> &chats); // returns last chat
void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos, bool emitPeerUpdated = true); void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos, bool emitPeerUpdated = true);
@ -149,7 +151,7 @@ namespace App {
PhotoData *photo(const PhotoId &photo); PhotoData *photo(const PhotoId &photo);
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full); PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
DocumentData *document(const DocumentId &document); DocumentData *document(const DocumentId &document);
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation); DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 version, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
WebPageData *webPage(const WebPageId &webPage); WebPageData *webPage(const WebPageId &webPage);
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill); WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill);
LocationData *location(const LocationCoords &coords); LocationData *location(const LocationCoords &coords);

View file

@ -0,0 +1,69 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
using "basic.style";
confirmInviteTitle: flatLabel(labelDefFlat) {
font: font(16px semibold);
align: align(center);
width: 320px;
maxHeight: 24px;
textFg: #333333;
}
confirmInviteStatus: flatLabel(labelDefFlat) {
font: font(boxFontSize);
align: align(center);
width: 320px;
maxHeight: 20px;
textFg: windowSubTextFg;
}
confirmInviteTitleTop: 106px;
confirmInvitePhotoSize: 76px;
confirmInvitePhotoTop: 20px;
confirmInviteStatusTop: 136px;
confirmInviteUserHeight: 80px;
confirmInviteUserPhotoSize: 56px;
confirmInviteUserPhotoTop: 166px;
confirmInviteUserName: flatLabel(labelDefFlat) {
font: normalFont;
align: align(center);
width: 66px;
maxHeight: 20px;
}
confirmInviteUserNameTop: 227px;
stickersAddIcon: icon {
{ "stickers_add", #ffffff },
};
stickersAddSize: size(30px, 24px);
stickersFeaturedHeight: 32px;
stickersFeaturedFont: contactsNameFont;
stickersFeaturedPosition: point(16px, 6px);
stickersFeaturedBadgeFont: semiboldFont;
stickersFeaturedBadgeSize: 21px;
stickersFeaturedPen: contactsNewItemFg;
stickersFeaturedUnreadBg: msgFileInBg;
stickersFeaturedUnreadSize: 5px;
stickersFeaturedUnreadSkip: 5px;
stickersFeaturedUnreadTop: 7px;
stickersFeaturedInstalled: icon {
{ "mediaview_save_check", #40ace3 }
};

View file

@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "apiwrap.h" #include "apiwrap.h"
#include "application.h" #include "application.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "styles/style_boxes.h"
TextParseOptions _confirmBoxTextOptions = { TextParseOptions _confirmBoxTextOptions = {
TextParseLinks | TextParseMultiline | TextParseRichText, // flags TextParseLinks | TextParseMultiline | TextParseRichText, // flags
@ -520,3 +521,86 @@ void KickMemberBox::onConfirm() {
App::api()->kickParticipant(channel, _member); App::api()->kickParticipant(channel, _member);
} }
} }
ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants) : AbstractBox()
, _title(this, st::confirmInviteTitle)
, _status(this, st::confirmInviteStatus)
, _photo(chatDefPhoto(0))
, _participants(participants)
, _join(this, lang(lng_group_invite_join), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
if (_participants.size() > 4) {
_participants.resize(4);
}
_title->setText(title);
QString status;
if (_participants.isEmpty() || _participants.size() >= count) {
status = lng_chat_status_members(lt_count, count);
} else {
status = lng_group_invite_members(lt_count, count);
}
_status->setText(status);
if (photo.type() == mtpc_chatPhoto) {
auto &d = photo.c_chatPhoto();
auto location = App::imageLocation(160, 160, d.vphoto_small);
if (!location.isNull()) {
_photo = ImagePtr(location);
if (!_photo->loaded()) {
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
_photo->load();
}
}
}
int h = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _join->height() + st::boxButtonPadding.bottom();
if (!_participants.isEmpty()) {
int skip = (width() - 4 * st::confirmInviteUserPhotoSize) / 5;
int padding = skip / 2;
_userWidth = (st::confirmInviteUserPhotoSize + 2 * padding);
int sumWidth = _participants.size() * _userWidth;
int left = (width() - sumWidth) / 2;
for_const (auto user, _participants) {
auto name = new FlatLabel(this, st::confirmInviteUserName);
name->resizeToWidth(st::confirmInviteUserPhotoSize + padding);
name->setText(user->firstName.isEmpty() ? App::peerName(user) : user->firstName);
name->moveToLeft(left + (padding / 2), st::confirmInviteUserNameTop);
left += _userWidth;
}
h += st::confirmInviteUserHeight;
}
setMaxHeight(h);
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_join, SIGNAL(clicked()), App::main(), SLOT(onInviteImport()));
}
void ConfirmInviteBox::resizeEvent(QResizeEvent *e) {
_title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop);
_status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop);
_join->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _join->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _join->width() + st::boxButtonPadding.left(), _join->y());
}
void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
Painter p(this);
if (paint(p)) return;
p.drawPixmap((width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, _photo->pixCircled(st::confirmInvitePhotoSize, st::confirmInvitePhotoSize));
int sumWidth = _participants.size() * _userWidth;
int left = (width() - sumWidth) / 2;
for_const (auto user, _participants) {
user->paintUserpicLeft(p, st::confirmInviteUserPhotoSize, left + (_userWidth - st::confirmInviteUserPhotoSize) / 2, st::confirmInviteUserPhotoTop, width());
left += _userWidth;
}
}
void ConfirmInviteBox::showAll() {
showChildren();
}
void ConfirmInviteBox::hideAll() {
hideChildren();
}

View file

@ -266,3 +266,26 @@ private:
UserData *_member; UserData *_member;
}; };
class ConfirmInviteBox : public AbstractBox, public RPCSender {
Q_OBJECT
public:
ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
protected:
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void showAll();
void hideAll();
private:
ChildWidget<FlatLabel> _title, _status;
ImagePtr _photo;
QVector<UserData*> _participants;
ChildWidget<BoxButton> _join, _cancel;
int _userWidth = 0;
};

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "abstractbox.h" #include "abstractbox.h"
class ConfirmBox;
class StickerSetInner : public TWidget, public RPCSender { class StickerSetInner : public TWidget, public RPCSender {
Q_OBJECT Q_OBJECT
@ -62,24 +64,26 @@ private:
void gotSet(const MTPmessages_StickerSet &set); void gotSet(const MTPmessages_StickerSet &set);
bool failedSet(const RPCError &error); bool failedSet(const RPCError &error);
void installDone(const MTPBool &result); void installDone(const MTPmessages_StickerSetInstallResult &result);
bool installFailed(const RPCError &error); bool installFail(const RPCError &error);
StickerPack _pack; StickerPack _pack;
StickersByEmojiMap _emoji; StickersByEmojiMap _emoji;
bool _loaded; bool _loaded = false;
uint64 _setId, _setAccess; uint64 _setId = 0;
uint64 _setAccess = 0;
QString _title, _setTitle, _setShortName; QString _title, _setTitle, _setShortName;
int32 _setCount, _setHash; int32 _setCount = 0;
MTPDstickerSet::Flags _setFlags; int32 _setHash = 0;
MTPDstickerSet::Flags _setFlags = 0;
int32 _bottom; int32 _bottom = 0;
MTPInputStickerSet _input; MTPInputStickerSet _input;
mtpRequestId _installRequest; mtpRequestId _installRequest = 0;
QTimer _previewTimer; QTimer _previewTimer;
int32 _previewShown; int32 _previewShown = -1;
}; };
class StickerSetBox : public ScrollableBox, public RPCSender { class StickerSetBox : public ScrollableBox, public RPCSender {
@ -93,7 +97,6 @@ public:
void resizeEvent(QResizeEvent *e); void resizeEvent(QResizeEvent *e);
public slots: public slots:
void onStickersUpdated(); void onStickersUpdated();
void onAddStickers(); void onAddStickers();
void onShareStickers(); void onShareStickers();
@ -101,122 +104,49 @@ public slots:
void onScroll(); void onScroll();
signals: private slots:
void onInstalled(uint64 id);
signals:
void installed(uint64 id); void installed(uint64 id);
protected: protected:
void hideAll(); void hideAll();
void showAll(); void showAll();
private: private:
StickerSetInner _inner; StickerSetInner _inner;
ScrollableBoxShadow _shadow; ScrollableBoxShadow _shadow;
BoxButton _add, _share, _cancel, _done; BoxButton _add, _share, _cancel, _done;
QString _title; QString _title;
}; };
class StickersInner : public TWidget { namespace internal {
Q_OBJECT class StickersInner;
} // namespace internal
public:
StickersInner();
void paintEvent(QPaintEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void rebuild();
bool savingStart() {
if (_saving) return false;
_saving = true;
return true;
}
QVector<uint64> getOrder() const;
QVector<uint64> getDisabledSets() const;
void setVisibleScrollbar(int32 width);
~StickersInner();
signals:
void checkDraggingScroll(int localY);
void noDraggingScroll();
public slots:
void onUpdateSelected();
private:
void step_shifting(uint64 ms, bool timer);
void paintRow(Painter &p, int32 index);
void clear();
void setRemoveSel(int32 removeSel);
float64 aboveShadowOpacity() const;
int32 _rowHeight;
struct StickerSetRow {
StickerSetRow(uint64 id, DocumentData *sticker, int32 count, const QString &title, bool official, bool disabled, int32 pixw, int32 pixh) : id(id)
, sticker(sticker)
, count(count)
, title(title)
, official(official)
, disabled(disabled)
, pixw(pixw)
, pixh(pixh)
, yadd(0, 0) {
}
uint64 id;
DocumentData *sticker;
int32 count;
QString title;
bool official, disabled;
int32 pixw, pixh;
anim::ivalue yadd;
};
typedef QList<StickerSetRow*> StickerSetRows;
StickerSetRows _rows;
QList<uint64> _animStartTimes;
uint64 _aboveShadowFadeStart;
anim::fvalue _aboveShadowFadeOpacity;
Animation _a_shifting;
int32 _itemsTop;
bool _saving;
int32 _removeSel, _removeDown, _removeWidth, _returnWidth, _restoreWidth;
QPoint _mouse;
int32 _selected;
QPoint _dragStart;
int32 _started, _dragging, _above;
BoxShadow _aboveShadow;
int32 _scrollbar;
};
class StickersBox : public ItemListBox, public RPCSender { class StickersBox : public ItemListBox, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
enum class Section {
Installed,
Featured,
Archived,
ArchivedPart,
};
StickersBox(Section section = Section::Installed);
StickersBox(const Stickers::Order &archivedIds);
StickersBox();
void resizeEvent(QResizeEvent *e); void resizeEvent(QResizeEvent *e);
void paintEvent(QPaintEvent *e); void paintEvent(QPaintEvent *e);
void closePressed(); void closePressed();
public slots: ~StickersBox();
public slots:
void onStickersUpdated(); void onStickersUpdated();
void onCheckDraggingScroll(int localY); void onCheckDraggingScroll(int localY);
@ -225,35 +155,184 @@ public slots:
void onSave(); void onSave();
protected: private slots:
void onScroll();
protected:
void hideAll(); void hideAll();
void showAll(); void showAll();
private: private:
void setup();
int32 countHeight() const; int32 countHeight() const;
void rebuildList();
void disenableDone(const MTPBool &result, mtpRequestId req); void disenableDone(const MTPmessages_StickerSetInstallResult &result, mtpRequestId req);
bool disenableFail(const RPCError &error, mtpRequestId req); bool disenableFail(const RPCError &error, mtpRequestId req);
void reorderDone(const MTPBool &result); void reorderDone(const MTPBool &result);
bool reorderFail(const RPCError &result); bool reorderFail(const RPCError &result);
void saveOrder(); void saveOrder();
StickersInner _inner; void checkLoadMoreArchived();
BoxButton _save, _cancel; void getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result);
Section _section;
ChildWidget<internal::StickersInner> _inner;
ChildWidget<BoxButton> _save = { nullptr };
ChildWidget<BoxButton> _cancel = { nullptr };
QMap<mtpRequestId, NullType> _disenableRequests; QMap<mtpRequestId, NullType> _disenableRequests;
mtpRequestId _reorderRequest; mtpRequestId _reorderRequest = 0;
PlainShadow _topShadow; ChildWidget<PlainShadow> _topShadow = { nullptr };
ScrollableBoxShadow _bottomShadow; ChildWidget<ScrollableBoxShadow> _bottomShadow = { nullptr };
QTimer _scrollTimer; QTimer _scrollTimer;
int32 _scrollDelta; int32 _scrollDelta = 0;
int32 _aboutWidth; int _aboutWidth = 0;
Text _about; Text _about;
int32 _aboutHeight; int _aboutHeight = 0;
mtpRequestId _archivedRequestId = 0;
bool _allArchivedLoaded = false;
}; };
int32 stickerPacksCount(bool includeDisabledOfficial = false); int32 stickerPacksCount(bool includeDisabledOfficial = false);
namespace internal {
class StickersInner : public TWidget, public RPCSender {
Q_OBJECT
public:
using Section = StickersBox::Section;
StickersInner(Section section);
StickersInner(const Stickers::Order &archivedIds);
void rebuild();
void updateSize();
void updateRows(); // refresh only pack cover stickers
bool appendSet(const Stickers::Set &set);
bool savingStart() {
if (_saving) return false;
_saving = true;
return true;
}
Stickers::Order getOrder() const;
Stickers::Order getDisabledSets() const;
void setVisibleScrollbar(int32 width);
~StickersInner();
protected:
void paintEvent(QPaintEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void leaveEvent(QEvent *e) override;
signals:
void checkDraggingScroll(int localY);
void noDraggingScroll();
public slots:
void onUpdateSelected();
void onClearRecent();
void onClearBoxDestroyed(QObject *box);
private:
void setup();
void paintButton(Painter &p, int y, bool selected, const QString &text, int badgeCounter) const;
void step_shifting(uint64 ms, bool timer);
void paintRow(Painter &p, int32 index);
void clear();
void setActionSel(int32 actionSel);
float64 aboveShadowOpacity() const;
void installSet(uint64 setId);
void installDone(const MTPmessages_StickerSetInstallResult &result);
bool installFail(uint64 setId, const RPCError &error);
void readFeaturedDone(const MTPBool &result);
bool readFeaturedFail(const RPCError &error);
Section _section;
Stickers::Order _archivedIds;
int32 _rowHeight;
struct StickerSetRow {
StickerSetRow(uint64 id, DocumentData *sticker, int32 count, const QString &title, bool installed, bool official, bool unread, bool disabled, bool recent, int32 pixw, int32 pixh) : id(id)
, sticker(sticker)
, count(count)
, title(title)
, installed(installed)
, official(official)
, unread(unread)
, disabled(disabled)
, recent(recent)
, pixw(pixw)
, pixh(pixh)
, yadd(0, 0) {
}
uint64 id;
DocumentData *sticker;
int32 count;
QString title;
bool installed, official, unread, disabled, recent;
int32 pixw, pixh;
anim::ivalue yadd;
};
using StickerSetRows = QList<StickerSetRow*>;
void rebuildAppendSet(const Stickers::Set &set, int maxNameWidth);
void fillSetCover(const Stickers::Set &set, DocumentData **outSticker, int *outWidth, int *outHeight) const;
int fillSetCount(const Stickers::Set &set) const;
QString fillSetTitle(const Stickers::Set &set, int maxNameWidth) const;
void fillSetFlags(const Stickers::Set &set, bool *outRecent, bool *outInstalled, bool *outOfficial, bool *outUnread, bool *outDisabled);
int countMaxNameWidth() const;
StickerSetRows _rows;
QList<uint64> _animStartTimes;
uint64 _aboveShadowFadeStart = 0;
anim::fvalue _aboveShadowFadeOpacity = { 0., 0. };
Animation _a_shifting;
int32 _itemsTop;
bool _saving = false;
int _actionSel = -1;
int _actionDown = -1;
int _clearWidth, _removeWidth, _returnWidth, _restoreWidth;
ConfirmBox *_clearBox = nullptr;
QString _addText;
int _addWidth;
int _buttonHeight = 0;
bool _hasFeaturedButton = false;
bool _hasArchivedButton = false;
// Remember all the unread set ids to display unread dots.
OrderedSet<uint64> _unreadSets;
QPoint _mouse;
int _selected = -3; // -2 - featured stickers button, -1 - archived stickers button
int _pressed = -2;
QPoint _dragStart;
int _started = -1;
int _dragging = -1;
int _above = -1;
BoxShadow _aboveShadow;
int32 _scrollbar = 0;
};
} // namespace internal

View file

@ -141,7 +141,10 @@ private:
void reallocate(int newCapacity) { void reallocate(int newCapacity) {
auto newPlainData = operator new[](newCapacity * sizeof(T)); auto newPlainData = operator new[](newCapacity * sizeof(T));
for (int i = 0; i < _size; ++i) { for (int i = 0; i < _size; ++i) {
*(reinterpret_cast<T*>(newPlainData) + i) = std_::move(*(data() + i)); auto oldLocation = data() + i;
auto newLocation = reinterpret_cast<T*>(newPlainData) + i;
new (newLocation) T(std_::move(*oldLocation));
oldLocation->~T();
} }
std::swap(_plaindata, newPlainData); std::swap(_plaindata, newPlainData);
_capacity = newCapacity; _capacity = newCapacity;

View file

@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#define BETA_VERSION_MACRO (0ULL) #define BETA_VERSION_MACRO (0ULL)
constexpr int AppVersion = 9060; constexpr int AppVersion = 9061;
constexpr str_const AppVersionStr = "0.9.60"; constexpr str_const AppVersionStr = "0.9.61";
constexpr bool AppAlphaVersion = true; constexpr bool AppAlphaVersion = false;
constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO; constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;

View file

@ -29,7 +29,6 @@ dialogsUnreadBgActive: #ffffff;
dialogsUnreadBgMutedActive: #d3e2ee; dialogsUnreadBgMutedActive: #d3e2ee;
dialogsUnreadFont: font(12px bold); dialogsUnreadFont: font(12px bold);
dialogsUnreadHeight: 19px; dialogsUnreadHeight: 19px;
dialogsUnreadTop: 1px;
dialogsUnreadPadding: 5px; dialogsUnreadPadding: 5px;
dialogsBg: windowBg; dialogsBg: windowBg;
@ -86,8 +85,8 @@ dialogsTextStyleActive: textStyle(dialogsTextStyle) {
linkFgDown: dialogsTextFgActive; linkFgDown: dialogsTextFgActive;
} }
dialogsTextStyleDraftActive: textStyle(dialogsTextStyle) { dialogsTextStyleDraftActive: textStyle(dialogsTextStyle) {
linkFg: #ffd6d6; linkFg: #c6e1f7;
linkFgDown: #ffd6d6; linkFgDown: #c6e1f7;
} }
dialogsNewChatIcon: icon { dialogsNewChatIcon: icon {

View file

@ -222,7 +222,7 @@ void paintUnreadCount(Painter &p, const QString &text, int x, int y, const Unrea
p.setFont(st.font); p.setFont(st.font);
p.setPen(st.active ? st::dialogsUnreadFgActive : st::dialogsUnreadFg); p.setPen(st.active ? st::dialogsUnreadFgActive : st::dialogsUnreadFg);
p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + st::dialogsUnreadTop + st.font->ascent, text); p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + (unreadRectHeight - st.font->height) / 2 + st.font->ascent, text);
} }
void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground) { void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground) {
@ -258,7 +258,7 @@ void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool sele
auto counter = QString::number(unreadCount); auto counter = QString::number(unreadCount);
auto mutedCounter = history->mute(); auto mutedCounter = history->mute();
int unreadRight = w - st::dialogsPadding.x(); int unreadRight = w - st::dialogsPadding.x();
int unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - st::dialogsUnreadTop; int unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2;
int unreadWidth = 0; int unreadWidth = 0;
UnreadBadgeStyle st; UnreadBadgeStyle st;
@ -297,7 +297,7 @@ void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool o
int unreadTop = (st::dialogsImportantBarHeight - st::dialogsUnreadHeight) / 2; int unreadTop = (st::dialogsImportantBarHeight - st::dialogsUnreadHeight) / 2;
bool mutedHidden = (current == Dialogs::Mode::Important); bool mutedHidden = (current == Dialogs::Mode::Important);
QString text = mutedHidden ? qsl("Show all chats") : qsl("Hide muted chats"); QString text = mutedHidden ? qsl("Show all chats") : qsl("Hide muted chats");
int textBaseline = unreadTop + st::dialogsUnreadTop + st::dialogsUnreadFont->ascent; int textBaseline = unreadTop + (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2 + st::dialogsUnreadFont->ascent;
p.drawText(st::dialogsPadding.x(), textBaseline, text); p.drawText(st::dialogsPadding.x(), textBaseline, text);
if (mutedHidden) { if (mutedHidden) {

View file

@ -38,6 +38,8 @@ void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool o
enum UnreadBadgeSize { enum UnreadBadgeSize {
UnreadBadgeInDialogs = 0, UnreadBadgeInDialogs = 0,
UnreadBadgeInHistoryToDown, UnreadBadgeInHistoryToDown,
UnreadBadgeInStickersPanel,
UnreadBadgeInStickersBox,
UnreadBadgeSizesCount UnreadBadgeSizesCount
}; };

View file

@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/stickersetbox.h" #include "boxes/stickersetbox.h"
#include "inline_bots/inline_bot_result.h" #include "inline_bots/inline_bot_result.h"
#include "inline_bots/inline_bot_layout_item.h" #include "inline_bots/inline_bot_layout_item.h"
#include "dialogs/dialogs_layout.h"
#include "historywidget.h" #include "historywidget.h"
#include "localstorage.h" #include "localstorage.h"
#include "lang.h" #include "lang.h"
@ -713,7 +714,7 @@ void EmojiColorPicker::drawVariant(Painter &p, int variant) {
} }
EmojiPanInner::EmojiPanInner() : TWidget() EmojiPanInner::EmojiPanInner() : TWidget()
, _maxHeight(int(st::emojiPanMaxHeight)) , _maxHeight(int(st::emojiPanMaxHeight) - st::rbEmoji.height)
, _a_selected(animation(this, &EmojiPanInner::step_selected)) , _a_selected(animation(this, &EmojiPanInner::step_selected))
, _top(0) , _top(0)
, _selected(-1) , _selected(-1)
@ -1229,7 +1230,7 @@ StickerPanInner::StickerPanInner() : TWidget()
, _pressedSel(-1) , _pressedSel(-1)
, _settings(this, lang(lng_stickers_you_have)) , _settings(this, lang(lng_stickers_you_have))
, _previewShown(false) { , _previewShown(false) {
setMaxHeight(st::emojiPanMaxHeight); setMaxHeight(st::emojiPanMaxHeight - st::rbEmoji.height);
setMouseTracking(true); setMouseTracking(true);
setFocusPolicy(Qt::NoFocus); setFocusPolicy(Qt::NoFocus);
@ -1508,7 +1509,7 @@ void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
break; break;
} }
} }
Stickers::Sets &sets(Global::RefStickerSets()); auto &sets = Global::RefStickerSets();
auto it = sets.find(Stickers::CustomSetId); auto it = sets.find(Stickers::CustomSetId);
if (it != sets.cend()) { if (it != sets.cend()) {
for (int32 i = 0, l = it->stickers.size(); i < l; ++i) { for (int32 i = 0, l = it->stickers.size(); i < l; ++i) {
@ -1517,7 +1518,7 @@ void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
if (it->stickers.isEmpty()) { if (it->stickers.isEmpty()) {
sets.erase(it); sets.erase(it);
} }
Local::writeStickers(); Local::writeInstalledStickers();
refresh = true; refresh = true;
break; break;
} }
@ -1628,8 +1629,8 @@ void StickerPanInner::hideFinish(bool completely) {
void StickerPanInner::refreshStickers() { void StickerPanInner::refreshStickers() {
clearSelection(true); clearSelection(true);
const Stickers::Sets &sets(Global::StickerSets()); _sets.clear();
_sets.clear(); _sets.reserve(sets.size() + 1); _sets.reserve(Global::StickerSetsOrder().size() + 1);
refreshRecentStickers(false); refreshRecentStickers(false);
for (auto i = Global::StickerSetsOrder().cbegin(), e = Global::StickerSetsOrder().cend(); i != e; ++i) { for (auto i = Global::StickerSetsOrder().cbegin(), e = Global::StickerSetsOrder().cend(); i != e; ++i) {
@ -2085,9 +2086,9 @@ bool StickerPanInner::ui_isInlineItemBeingChosen() {
} }
void StickerPanInner::appendSet(uint64 setId) { void StickerPanInner::appendSet(uint64 setId) {
const Stickers::Sets &sets(Global::StickerSets()); auto &sets = Global::StickerSets();
auto it = sets.constFind(setId); auto it = sets.constFind(setId);
if (it == sets.cend() || (it->flags & MTPDstickerSet::Flag::f_disabled) || it->stickers.isEmpty()) return; if (it == sets.cend() || (it->flags & MTPDstickerSet::Flag::f_archived) || it->stickers.isEmpty()) return;
StickerPack pack; StickerPack pack;
pack.reserve(it->stickers.size()); pack.reserve(it->stickers.size());
@ -2110,37 +2111,49 @@ void StickerPanInner::refreshRecent() {
void StickerPanInner::refreshRecentStickers(bool performResize) { void StickerPanInner::refreshRecentStickers(bool performResize) {
_custom.clear(); _custom.clear();
clearSelection(true); clearSelection(true);
auto customIt = Global::StickerSets().constFind(Stickers::CustomSetId); auto &sets = Global::StickerSets();
if (cGetRecentStickers().isEmpty() && (customIt == Global::StickerSets().cend() || customIt->stickers.isEmpty())) { auto &recent = cGetRecentStickers();
auto customIt = sets.constFind(Stickers::CustomSetId);
auto cloudIt = sets.constFind(Stickers::CloudRecentSetId);
if (recent.isEmpty()
&& (customIt == sets.cend() || customIt->stickers.isEmpty())
&& (cloudIt == sets.cend() || cloudIt->stickers.isEmpty())) {
if (!_sets.isEmpty() && _sets.at(0).id == Stickers::RecentSetId) { if (!_sets.isEmpty() && _sets.at(0).id == Stickers::RecentSetId) {
_sets.pop_front(); _sets.pop_front();
} }
} else { } else {
StickerPack recent; StickerPack recentPack;
int32 customCnt = (customIt == Global::StickerSets().cend() ? 0 : customIt->stickers.size()); int customCnt = (customIt == sets.cend()) ? 0 : customIt->stickers.size();
QMap<DocumentData*, bool> recentOnly; int cloudCnt = (cloudIt == sets.cend()) ? 0 : cloudIt->stickers.size();
recent.reserve(cGetRecentStickers().size() + customCnt); recentPack.reserve(cloudCnt + recent.size() + customCnt);
_custom.reserve(cGetRecentStickers().size() + customCnt); _custom.reserve(cloudCnt + recent.size() + customCnt);
for (int32 i = 0, l = cGetRecentStickers().size(); i < l; ++i) { if (cloudCnt > 0) {
DocumentData *s = cGetRecentStickers().at(i).first; for_const (auto sticker, cloudIt->stickers) {
recent.push_back(s); recentPack.push_back(sticker);
recentOnly.insert(s, true); _custom.push_back(false);
}
}
for_const (auto &recentSticker, recent) {
auto sticker = recentSticker.first;
recentPack.push_back(sticker);
_custom.push_back(false); _custom.push_back(false);
} }
for (int32 i = 0; i < customCnt; ++i) { if (customCnt > 0) {
DocumentData *s = customIt->stickers.at(i); for_const (auto &sticker, customIt->stickers) {
if (recentOnly.contains(s)) { auto index = recentPack.indexOf(sticker);
_custom[recent.indexOf(s)] = true; if (index >= cloudCnt) {
} else { _custom[index] = true; // mark stickers from recent as custom
recent.push_back(s); } else {
_custom.push_back(true); recentPack.push_back(sticker);
_custom.push_back(true);
}
} }
} }
if (_sets.isEmpty() || _sets.at(0).id != Stickers::RecentSetId) { if (_sets.isEmpty() || _sets.at(0).id != Stickers::RecentSetId) {
_sets.push_back(DisplayedSet(Stickers::RecentSetId, MTPDstickerSet::Flag::f_official, lang(lng_emoji_category0), recent.size() * 2, recent)); _sets.push_back(DisplayedSet(Stickers::RecentSetId, MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special, lang(lng_emoji_category0), recentPack.size() * 2, recentPack));
} else { } else {
_sets[0].pack = recent; _sets[0].pack = recentPack;
_sets[0].hovers.resize(recent.size() * 2); _sets[0].hovers.resize(recentPack.size() * 2);
} }
} }
@ -2829,6 +2842,20 @@ void EmojiPan::onSaveConfigDelayed(int32 delay) {
_saveConfigTimer.start(delay); _saveConfigTimer.start(delay);
} }
void EmojiPan::paintStickerSettingsIcon(Painter &p) const {
int settingsLeft = _iconsLeft + 7 * st::rbEmoji.width;
p.drawSpriteLeft(settingsLeft + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), st::stickersSettings);
if (auto unread = Global::FeaturedStickerSetsUnreadCount()) {
Dialogs::Layout::UnreadBadgeStyle unreadSt;
unreadSt.sizeId = Dialogs::Layout::UnreadBadgeInStickersPanel;
unreadSt.size = st::stickersSettingsUnreadSize;
int unreadRight = settingsLeft + st::rbEmoji.width - st::stickersSettingsUnreadPosition.x();
if (rtl()) unreadRight = width() - unreadRight;
int unreadTop = _iconsTop + st::stickersSettingsUnreadPosition.y();
Dialogs::Layout::paintUnreadCount(p, QString::number(unread), unreadRight, unreadTop, unreadSt);
}
}
void EmojiPan::paintEvent(QPaintEvent *e) { void EmojiPan::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
@ -2846,7 +2873,7 @@ void EmojiPan::paintEvent(QPaintEvent *e) {
p.fillRect(myrtlrect(r.x() + r.width() - st::emojiScroll.width, r.y(), st::emojiScroll.width, e_scroll.height()), st::white->b); p.fillRect(myrtlrect(r.x() + r.width() - st::emojiScroll.width, r.y(), st::emojiScroll.width, e_scroll.height()), st::white->b);
if (_stickersShown && s_inner.showSectionIcons()) { if (_stickersShown && s_inner.showSectionIcons()) {
p.fillRect(r.left(), _iconsTop, r.width(), st::rbEmoji.height, st::emojiPanCategories); p.fillRect(r.left(), _iconsTop, r.width(), st::rbEmoji.height, st::emojiPanCategories);
p.drawSpriteLeft(_iconsLeft + 7 * st::rbEmoji.width + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), st::stickersSettings); paintStickerSettingsIcon(p);
if (!_icons.isEmpty()) { if (!_icons.isEmpty()) {
int32 x = _iconsLeft, i = 0, selxrel = _iconsLeft + _iconSelX.current(), selx = selxrel - _iconsX.current(); int32 x = _iconsLeft, i = 0, selxrel = _iconsLeft + _iconSelX.current(), selx = selxrel - _iconsX.current();
@ -3093,6 +3120,7 @@ void EmojiPan::refreshStickers() {
if (!_stickersShown) { if (!_stickersShown) {
s_inner.preloadImages(); s_inner.preloadImages();
} }
update();
} }
void EmojiPan::refreshSavedGifs() { void EmojiPan::refreshSavedGifs() {
@ -3228,7 +3256,7 @@ void EmojiPan::step_icons(uint64 ms, bool timer) {
} }
if (_iconsStartAnim) { if (_iconsStartAnim) {
float64 dt = (ms - _iconsStartAnim) / st::stickerIconMove; float64 dt = (ms - _iconsStartAnim) / float64(st::stickerIconMove);
if (dt >= 1) { if (dt >= 1) {
_iconsStartAnim = 0; _iconsStartAnim = 0;
_iconsX.finish(); _iconsX.finish();
@ -3584,7 +3612,7 @@ void EmojiPan::onSwitch() {
} else { } else {
if (cShowingSavedGifs() && cSavedGifs().isEmpty()) { if (cShowingSavedGifs() && cSavedGifs().isEmpty()) {
s_inner.showStickerSet(Stickers::DefaultSetId); s_inner.showStickerSet(Stickers::DefaultSetId);
} else if (!cShowingSavedGifs() && !cSavedGifs().isEmpty() && Global::StickerSets().isEmpty()) { } else if (!cShowingSavedGifs() && !cSavedGifs().isEmpty() && Global::StickerSetsOrder().isEmpty()) {
s_inner.showStickerSet(Stickers::NoneSetId); s_inner.showStickerSet(Stickers::NoneSetId);
} else { } else {
s_inner.updateShowingSavedGifs(); s_inner.updateShowingSavedGifs();
@ -3623,8 +3651,9 @@ void EmojiPan::onSwitch() {
} }
void EmojiPan::onRemoveSet(quint64 setId) { void EmojiPan::onRemoveSet(quint64 setId) {
auto it = Global::StickerSets().constFind(setId); auto &sets = Global::StickerSets();
if (it != Global::StickerSets().cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { auto it = sets.constFind(setId);
if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) {
_removingSetId = it->id; _removingSetId = it->id;
ConfirmBox *box = new ConfirmBox(lng_stickers_remove_pack(lt_sticker_pack, it->title), lang(lng_box_remove)); ConfirmBox *box = new ConfirmBox(lng_stickers_remove_pack(lt_sticker_pack, it->title), lang(lng_box_remove));
connect(box, SIGNAL(confirmed()), this, SLOT(onRemoveSetSure())); connect(box, SIGNAL(confirmed()), this, SLOT(onRemoveSetSure()));
@ -3635,8 +3664,9 @@ void EmojiPan::onRemoveSet(quint64 setId) {
void EmojiPan::onRemoveSetSure() { void EmojiPan::onRemoveSetSure() {
Ui::hideLayer(); Ui::hideLayer();
auto it = Global::RefStickerSets().find(_removingSetId); auto &sets = Global::RefStickerSets();
if (it != Global::RefStickerSets().cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { auto it = sets.find(_removingSetId);
if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) {
if (it->id && it->access) { if (it->id && it->access) {
MTP::send(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)))); MTP::send(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access))));
} else if (!it->shortName.isEmpty()) { } else if (!it->shortName.isEmpty()) {
@ -3652,11 +3682,14 @@ void EmojiPan::onRemoveSetSure() {
++i; ++i;
} }
} }
Global::RefStickerSets().erase(it); it->flags &= ~MTPDstickerSet::Flag::f_installed;
if (!(it->flags & MTPDstickerSet_ClientFlag::f_featured) && !(it->flags & MTPDstickerSet_ClientFlag::f_special)) {
sets.erase(it);
}
int removeIndex = Global::StickerSetsOrder().indexOf(_removingSetId); int removeIndex = Global::StickerSetsOrder().indexOf(_removingSetId);
if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex); if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex);
refreshStickers(); refreshStickers();
Local::writeStickers(); Local::writeInstalledStickers();
if (writeRecent) Local::writeUserSettings(); if (writeRecent) Local::writeUserSettings();
} }
_removingSetId = 0; _removingSetId = 0;

View file

@ -656,6 +656,7 @@ signals:
void updateStickers(); void updateStickers();
private: private:
void paintStickerSettingsIcon(Painter &p) const;
void validateSelectedIcon(bool animated = false); void validateSelectedIcon(bool animated = false);

View file

@ -33,6 +33,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
Q_DECLARE_METATYPE(ClickHandlerPtr); Q_DECLARE_METATYPE(ClickHandlerPtr);
Q_DECLARE_METATYPE(Qt::MouseButton); Q_DECLARE_METATYPE(Qt::MouseButton);
Q_DECLARE_METATYPE(Ui::ShowWay);
namespace App { namespace App {
@ -253,13 +254,14 @@ void showPeerOverview(const PeerId &peer, MediaOverviewType type) {
} }
} }
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back) { void showPeerHistory(const PeerId &peer, MsgId msgId, ShowWay way) {
if (MainWidget *m = App::main()) m->ui_showPeerHistory(peer, msgId, back); if (MainWidget *m = App::main()) m->ui_showPeerHistory(peer, msgId, way);
} }
void showPeerHistoryAsync(const PeerId &peer, MsgId msgId) { void showPeerHistoryAsync(const PeerId &peer, MsgId msgId, ShowWay way) {
if (MainWidget *m = App::main()) { if (MainWidget *m = App::main()) {
QMetaObject::invokeMethod(m, "ui_showPeerHistoryAsync", Qt::QueuedConnection, Q_ARG(quint64, peer), Q_ARG(qint32, msgId)); qRegisterMetaType<Ui::ShowWay>();
QMetaObject::invokeMethod(m, "ui_showPeerHistoryAsync", Qt::QueuedConnection, Q_ARG(quint64, peer), Q_ARG(qint32, msgId), Q_ARG(Ui::ShowWay, way));
} }
} }
@ -518,6 +520,45 @@ DefineVar(Sandbox, ConnectionProxy, PreLaunchProxy);
} // namespace Sandbox } // namespace Sandbox
namespace Stickers {
Set *feedSet(const MTPDstickerSet &set) {
MTPDstickerSet::Flags flags = 0;
auto &sets = Global::RefStickerSets();
auto it = sets.find(set.vid.v);
auto title = stickerSetTitle(set);
if (it == sets.cend()) {
it = sets.insert(set.vid.v, Stickers::Set(set.vid.v, set.vaccess_hash.v, title, qs(set.vshort_name), set.vcount.v, set.vhash.v, set.vflags.v | MTPDstickerSet_ClientFlag::f_not_loaded));
} else {
it->access = set.vaccess_hash.v;
it->title = title;
it->shortName = qs(set.vshort_name);
flags = it->flags;
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;
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
}
}
auto changedFlags = (flags ^ it->flags);
if (changedFlags & MTPDstickerSet::Flag::f_archived) {
auto index = Global::ArchivedStickerSetsOrder().indexOf(it->id);
if (it->flags & MTPDstickerSet::Flag::f_archived) {
if (index < 0) {
Global::RefArchivedStickerSetsOrder().push_front(it->id);
}
} else if (index >= 0) {
Global::RefArchivedStickerSetsOrder().removeAt(index);
}
}
return &it.value();
}
} // namespace Stickers
namespace Global { namespace Global {
namespace internal { namespace internal {
@ -557,6 +598,7 @@ struct Data {
int32 PushChatLimit = 2; int32 PushChatLimit = 2;
int32 SavedGifsLimit = 200; int32 SavedGifsLimit = 200;
int32 EditTimeLimit = 172800; int32 EditTimeLimit = 172800;
int32 StickersRecentLimit = 30;
HiddenPinnedMessagesMap HiddenPinnedMessages; HiddenPinnedMessagesMap HiddenPinnedMessages;
@ -565,6 +607,11 @@ struct Data {
Stickers::Sets StickerSets; Stickers::Sets StickerSets;
Stickers::Order StickerSetsOrder; Stickers::Order StickerSetsOrder;
uint64 LastStickersUpdate = 0; uint64 LastStickersUpdate = 0;
uint64 LastRecentStickersUpdate = 0;
Stickers::Order FeaturedStickerSetsOrder;
int FeaturedStickerSetsUnreadCount = 0;
uint64 LastFeaturedStickersUpdate = 0;
Stickers::Order ArchivedStickerSetsOrder;
MTP::DcOptions DcOptions; MTP::DcOptions DcOptions;
@ -628,6 +675,7 @@ DefineVar(Global, int32, PushChatPeriod);
DefineVar(Global, int32, PushChatLimit); DefineVar(Global, int32, PushChatLimit);
DefineVar(Global, int32, SavedGifsLimit); DefineVar(Global, int32, SavedGifsLimit);
DefineVar(Global, int32, EditTimeLimit); DefineVar(Global, int32, EditTimeLimit);
DefineVar(Global, int32, StickersRecentLimit);
DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages); DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages);
@ -636,6 +684,11 @@ DefineRefVar(Global, PendingItemsMap, PendingRepaintItems);
DefineVar(Global, Stickers::Sets, StickerSets); DefineVar(Global, Stickers::Sets, StickerSets);
DefineVar(Global, Stickers::Order, StickerSetsOrder); DefineVar(Global, Stickers::Order, StickerSetsOrder);
DefineVar(Global, uint64, LastStickersUpdate); DefineVar(Global, uint64, LastStickersUpdate);
DefineVar(Global, uint64, LastRecentStickersUpdate);
DefineVar(Global, Stickers::Order, FeaturedStickerSetsOrder);
DefineVar(Global, int, FeaturedStickerSetsUnreadCount);
DefineVar(Global, uint64, LastFeaturedStickersUpdate);
DefineVar(Global, Stickers::Order, ArchivedStickerSetsOrder);
DefineVar(Global, MTP::DcOptions, DcOptions); DefineVar(Global, MTP::DcOptions, DcOptions);

View file

@ -83,22 +83,27 @@ inline void showPeerOverview(const History *history, MediaOverviewType type) {
showPeerOverview(history->peer->id, type); showPeerOverview(history->peer->id, type);
} }
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back = false); enum class ShowWay {
inline void showPeerHistory(const PeerData *peer, MsgId msgId, bool back = false) { ClearStack,
showPeerHistory(peer->id, msgId, back); Forward,
Backward,
};
void showPeerHistory(const PeerId &peer, MsgId msgId, ShowWay way = ShowWay::ClearStack);
inline void showPeerHistory(const PeerData *peer, MsgId msgId, ShowWay way = ShowWay::ClearStack) {
showPeerHistory(peer->id, msgId, way);
} }
inline void showPeerHistory(const History *history, MsgId msgId, bool back = false) { inline void showPeerHistory(const History *history, MsgId msgId, ShowWay way = ShowWay::ClearStack) {
showPeerHistory(history->peer->id, msgId, back); showPeerHistory(history->peer->id, msgId, way);
} }
inline void showPeerHistoryAtItem(const HistoryItem *item) { inline void showPeerHistoryAtItem(const HistoryItem *item, ShowWay way = ShowWay::ClearStack) {
showPeerHistory(item->history()->peer->id, item->id); showPeerHistory(item->history()->peer->id, item->id, way);
} }
void showPeerHistoryAsync(const PeerId &peer, MsgId msgId); void showPeerHistoryAsync(const PeerId &peer, MsgId msgId, ShowWay way = ShowWay::ClearStack);
inline void showChatsList() { inline void showChatsList() {
showPeerHistory(PeerId(0), 0); showPeerHistory(PeerId(0), 0, ShowWay::ClearStack);
} }
inline void showChatsListAsync() { inline void showChatsListAsync() {
showPeerHistoryAsync(PeerId(0), 0); showPeerHistoryAsync(PeerId(0), 0, ShowWay::ClearStack);
} }
PeerData *getPeerForMouseAction(); PeerData *getPeerForMouseAction();
@ -178,10 +183,19 @@ enum Flags {
namespace Stickers { namespace Stickers {
static const uint64 DefaultSetId = 0; // for backward compatibility static const uint64 DefaultSetId = 0; // for backward compatibility
static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL, RecentSetId = 0xFFFFFFFFFFFFFFFEULL; static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL;
static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel static const uint64 RecentSetId = 0xFFFFFFFFFFFFFFFEULL; // for emoji/stickers panel, should not appear in Sets
static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel, should not appear in Sets
static const uint64 CloudRecentSetId = 0xFFFFFFFFFFFFFFFCULL; // for cloud-stored recent stickers
struct Set { struct Set {
Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags) : id(id), access(access), title(title), shortName(shortName), count(count), hash(hash), flags(flags) { Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags)
: id(id)
, access(access)
, title(title)
, shortName(shortName)
, count(count)
, hash(hash)
, flags(flags) {
} }
uint64 id, access; uint64 id, access;
QString title, shortName; QString title, shortName;
@ -193,6 +207,15 @@ struct Set {
using Sets = QMap<uint64, Set>; using Sets = QMap<uint64, Set>;
using Order = QList<uint64>; using Order = QList<uint64>;
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));
}
Set *feedSet(const MTPDstickerSet &set);
} // namespace Stickers } // namespace Stickers
namespace Global { namespace Global {
@ -236,6 +259,7 @@ DeclareVar(int32, PushChatPeriod);
DeclareVar(int32, PushChatLimit); DeclareVar(int32, PushChatLimit);
DeclareVar(int32, SavedGifsLimit); DeclareVar(int32, SavedGifsLimit);
DeclareVar(int32, EditTimeLimit); DeclareVar(int32, EditTimeLimit);
DeclareVar(int32, StickersRecentLimit);
typedef QMap<PeerId, MsgId> HiddenPinnedMessagesMap; typedef QMap<PeerId, MsgId> HiddenPinnedMessagesMap;
DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages); DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages);
@ -246,6 +270,11 @@ DeclareRefVar(PendingItemsMap, PendingRepaintItems);
DeclareVar(Stickers::Sets, StickerSets); DeclareVar(Stickers::Sets, StickerSets);
DeclareVar(Stickers::Order, StickerSetsOrder); DeclareVar(Stickers::Order, StickerSetsOrder);
DeclareVar(uint64, LastStickersUpdate); DeclareVar(uint64, LastStickersUpdate);
DeclareVar(uint64, LastRecentStickersUpdate);
DeclareVar(Stickers::Order, FeaturedStickerSetsOrder);
DeclareVar(int, FeaturedStickerSetsUnreadCount);
DeclareVar(uint64, LastFeaturedStickersUpdate);
DeclareVar(Stickers::Order, ArchivedStickerSetsOrder);
DeclareVar(MTP::DcOptions, DcOptions); DeclareVar(MTP::DcOptions, DcOptions);

View file

@ -2869,7 +2869,9 @@ bool HistoryItem::unread() const {
if (id > 0) { if (id > 0) {
if (id < history()->outboxReadBefore) return false; if (id < history()->outboxReadBefore) return false;
if (auto channel = history()->peer->asChannel()) { if (auto user = history()->peer->asUser()) {
if (user->botInfo) return false;
} else if (auto channel = history()->peer->asChannel()) {
if (!channel->isMegagroup()) return false; if (!channel->isMegagroup()) return false;
} }
} }
@ -4079,10 +4081,10 @@ void HistoryDocument::draw(Painter &p, const QRect &r, TextSelection selection,
bottom = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); bottom = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width)); QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width));
QPixmap thumb = loaded ? _data->thumb->pixSingle(ImageRoundRadius::Small, thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(ImageRoundRadius::Small, thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize); QPixmap thumb = loaded ? _data->thumb->pixSingle(ImageRoundRadius::Large, thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(ImageRoundRadius::Small, thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize);
p.drawPixmap(rthumb.topLeft(), thumb); p.drawPixmap(rthumb.topLeft(), thumb);
if (selected) { if (selected) {
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlaySmallCorners); App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayLargeCorners);
} }
if (radial || (!loaded && !_data->loading())) { if (radial || (!loaded && !_data->loading())) {
@ -5170,7 +5172,7 @@ int HistorySticker::additionalWidth(const HistoryMessageVia *via, const HistoryM
} }
void SendMessageClickHandler::onClickImpl() const { void SendMessageClickHandler::onClickImpl() const {
Ui::showPeerHistory(peer()->id, ShowAtUnreadMsgId); Ui::showPeerHistory(peer()->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward);
} }
void AddContactClickHandler::onClickImpl() const { void AddContactClickHandler::onClickImpl() const {

View file

@ -153,15 +153,15 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
StickerPack srows; StickerPack srows;
if (_emoji) { if (_emoji) {
QMap<uint64, uint64> setsToRequest; QMap<uint64, uint64> setsToRequest;
Stickers::Sets &sets(Global::RefStickerSets()); auto &sets = Global::RefStickerSets();
const Stickers::Order &order(Global::StickerSetsOrder()); auto &order = Global::StickerSetsOrder();
for (int i = 0, l = order.size(); i < l; ++i) { for (int i = 0, l = order.size(); i < l; ++i) {
auto it = sets.find(order.at(i)); auto it = sets.find(order.at(i));
if (it != sets.cend()) { if (it != sets.cend()) {
if (it->emoji.isEmpty()) { if (it->emoji.isEmpty()) {
setsToRequest.insert(it->id, it->access); setsToRequest.insert(it->id, it->access);
it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded; it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded;
} else if (!(it->flags & MTPDstickerSet::Flag::f_disabled)) { } else if (!(it->flags & MTPDstickerSet::Flag::f_archived)) {
StickersByEmojiMap::const_iterator i = it->emoji.constFind(emojiGetNoColor(_emoji)); StickersByEmojiMap::const_iterator i = it->emoji.constFind(emojiGetNoColor(_emoji));
if (i != it->emoji.cend()) { if (i != it->emoji.cend()) {
srows += *i; srows += *i;
@ -196,14 +196,14 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
} }
return true; return true;
}; };
auto filterNotPassedByName = [this](UserData *user) -> bool { auto filterNotPassedByName = [this, &filterNotPassedByUsername](UserData *user) -> bool {
for_const (auto &namePart, user->names) { for_const (auto &namePart, user->names) {
if (namePart.startsWith(_filter, Qt::CaseInsensitive)) { if (namePart.startsWith(_filter, Qt::CaseInsensitive)) {
bool exactUsername = (user->username.compare(_filter, Qt::CaseInsensitive) == 0); bool exactUsername = (user->username.compare(_filter, Qt::CaseInsensitive) == 0);
return exactUsername; return exactUsername;
} }
} }
return true; return filterNotPassedByUsername(user);
}; };
bool listAllSuggestions = _filter.isEmpty(); bool listAllSuggestions = _filter.isEmpty();

View file

@ -29,6 +29,8 @@ historyToDownArrow: icon {
{ "history_down_arrow", #b9b9b9, point(14px, 19px) }, { "history_down_arrow", #b9b9b9, point(14px, 19px) },
}; };
historyToDownPaddingTop: 10px; historyToDownPaddingTop: 10px;
historyToDownBadgeFont: semiboldFont;
historyToDownBadgeSize: 22px;
membersInnerScroll: flatScroll(solidScroll) { membersInnerScroll: flatScroll(solidScroll) {
deltat: 3px; deltat: 3px;
@ -43,8 +45,6 @@ membersInnerDropdown: InnerDropdown(defaultInnerDropdown) {
scrollMargin: margins(0px, 5px, 0px, 5px); scrollMargin: margins(0px, 5px, 0px, 5px);
scrollPadding: margins(0px, 3px, 8px, 3px); scrollPadding: margins(0px, 3px, 8px, 3px);
} }
historyToDownBadgeFont: semiboldFont;
historyToDownBadgeSize: 22px;
historyServiceMsgRadius: 12px; historyServiceMsgRadius: 12px;
historyServiceMsgInvertedRadius: 6px; historyServiceMsgInvertedRadius: 6px;

View file

@ -33,6 +33,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "data/data_drafts.h" #include "data/data_drafts.h"
#include "history/history_service_layout.h" #include "history/history_service_layout.h"
#include "profile/profile_members_widget.h" #include "profile/profile_members_widget.h"
#include "core/click_handler_types.h"
#include "lang.h" #include "lang.h"
#include "application.h" #include "application.h"
#include "mainwidget.h" #include "mainwidget.h"
@ -3523,12 +3524,23 @@ void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) {
} }
void HistoryWidget::updateStickers() { void HistoryWidget::updateStickers() {
if (!Global::LastStickersUpdate() || getms(true) >= Global::LastStickersUpdate() + StickersUpdateTimeout) { auto now = getms(true);
if (!Global::LastStickersUpdate() || now >= Global::LastStickersUpdate() + StickersUpdateTimeout) {
if (!_stickersUpdateRequest) { if (!_stickersUpdateRequest) {
_stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_int(Local::countStickersHash(true))), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed)); _stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_int(Local::countStickersHash(true))), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed));
} }
} }
if (!cLastSavedGifsUpdate() || getms(true) >= cLastSavedGifsUpdate() + StickersUpdateTimeout) { if (!Global::LastRecentStickersUpdate() || now >= Global::LastRecentStickersUpdate() + StickersUpdateTimeout) {
if (!_recentStickersUpdateRequest) {
_recentStickersUpdateRequest = MTP::send(MTPmessages_GetRecentStickers(MTP_int(Local::countRecentStickersHash())), rpcDone(&HistoryWidget::recentStickersGot), rpcFail(&HistoryWidget::recentStickersFailed));
}
}
if (!Global::LastFeaturedStickersUpdate() || now >= Global::LastFeaturedStickersUpdate() + StickersUpdateTimeout) {
if (!_featuredStickersUpdateRequest) {
_featuredStickersUpdateRequest = MTP::send(MTPmessages_GetFeaturedStickers(MTP_int(Local::countFeaturedStickersHash())), rpcDone(&HistoryWidget::featuredStickersGot), rpcFail(&HistoryWidget::featuredStickersFailed));
}
}
if (!cLastSavedGifsUpdate() || now >= cLastSavedGifsUpdate() + StickersUpdateTimeout) {
if (!_savedGifsUpdateRequest) { if (!_savedGifsUpdateRequest) {
_savedGifsUpdateRequest = MTP::send(MTPmessages_GetSavedGifs(MTP_int(Local::countSavedGifsHash())), rpcDone(&HistoryWidget::savedGifsGot), rpcFail(&HistoryWidget::savedGifsFailed)); _savedGifsUpdateRequest = MTP::send(MTPmessages_GetSavedGifs(MTP_int(Local::countSavedGifsHash())), rpcDone(&HistoryWidget::savedGifsGot), rpcFail(&HistoryWidget::savedGifsFailed));
} }
@ -3654,36 +3666,23 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
const auto &d_sets(d.vsets.c_vector().v); const auto &d_sets(d.vsets.c_vector().v);
Stickers::Order &setsOrder(Global::RefStickerSetsOrder()); auto &setsOrder = Global::RefStickerSetsOrder();
setsOrder.clear(); setsOrder.clear();
Stickers::Sets &sets(Global::RefStickerSets()); auto &sets = Global::RefStickerSets();
QMap<uint64, uint64> setsToRequest; QMap<uint64, uint64> setsToRequest;
for (auto i = sets.begin(), e = sets.end(); i != e; ++i) { for (auto &set : sets) {
i->access = 0; // mark for removing if (!(set.flags & MTPDstickerSet::Flag::f_archived)) {
set.flags &= ~MTPDstickerSet::Flag::f_installed; // mark for removing
}
} }
for (int i = 0, l = d_sets.size(); i != l; ++i) { for_const (auto &setData, d_sets) {
if (d_sets.at(i).type() == mtpc_stickerSet) { if (setData.type() == mtpc_stickerSet) {
const auto &set(d_sets.at(i).c_stickerSet()); auto set = Stickers::feedSet(setData.c_stickerSet());
auto it = sets.find(set.vid.v); if (!(set->flags & MTPDstickerSet::Flag::f_archived) || (set->flags & MTPDstickerSet::Flag::f_official)) {
QString title = stickerSetTitle(set); setsOrder.push_back(set->id);
if (it == sets.cend()) { if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
it = sets.insert(set.vid.v, Stickers::Set(set.vid.v, set.vaccess_hash.v, title, qs(set.vshort_name), set.vcount.v, set.vhash.v, set.vflags.v | MTPDstickerSet_ClientFlag::f_not_loaded)); setsToRequest.insert(set->id, set->access);
} else {
it->access = set.vaccess_hash.v;
it->title = title;
it->shortName = qs(set.vshort_name);
it->flags = set.vflags.v;
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
}
}
if (!(it->flags & MTPDstickerSet::Flag::f_disabled) || (it->flags & MTPDstickerSet::Flag::f_official)) {
setsOrder.push_back(set.vid.v);
if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
setsToRequest.insert(set.vid.v, set.vaccess_hash.v);
} }
} }
} }
@ -3691,9 +3690,11 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
bool writeRecent = false; bool writeRecent = false;
RecentStickerPack &recent(cGetRecentStickers()); RecentStickerPack &recent(cGetRecentStickers());
for (Stickers::Sets::iterator it = sets.begin(), e = sets.end(); it != e;) { for (Stickers::Sets::iterator it = sets.begin(), e = sets.end(); it != e;) {
if (it->id == Stickers::CustomSetId || it->access != 0) { bool installed = (it->flags & MTPDstickerSet::Flag::f_installed);
++it; bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured);
} else { bool special = (it->flags & MTPDstickerSet_ClientFlag::f_special);
bool archived = (it->flags & MTPDstickerSet::Flag::f_archived);
if (!installed) { // remove not mine sets from recent stickers
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0) { if (it->stickers.indexOf(i->first) >= 0) {
i = recent.erase(i); i = recent.erase(i);
@ -3702,6 +3703,10 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
++i; ++i;
} }
} }
}
if (installed || featured || special || archived) {
++it;
} else {
it = sets.erase(it); it = sets.erase(it);
} }
} }
@ -3717,7 +3722,7 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
App::api()->requestStickerSets(); App::api()->requestStickerSets();
} }
Local::writeStickers(); Local::writeInstalledStickers();
if (writeRecent) Local::writeUserSettings(); if (writeRecent) Local::writeUserSettings();
if (App::main()) emit App::main()->stickersUpdated(); if (App::main()) emit App::main()->stickersUpdated();
@ -3733,6 +3738,193 @@ bool HistoryWidget::stickersFailed(const RPCError &error) {
return true; return true;
} }
void HistoryWidget::recentStickersGot(const MTPmessages_RecentStickers &stickers) {
Global::SetLastRecentStickersUpdate(getms(true));
_recentStickersUpdateRequest = 0;
if (stickers.type() != mtpc_messages_recentStickers) return;
auto &d = stickers.c_messages_recentStickers();
auto &sets = Global::RefStickerSets();
auto it = sets.find(Stickers::CloudRecentSetId);
auto &d_docs = d.vstickers.c_vector().v;
if (d_docs.isEmpty()) {
if (it != sets.cend()) {
sets.erase(it);
}
} else {
if (it == sets.cend()) {
it = sets.insert(Stickers::CloudRecentSetId, Stickers::Set(Stickers::CloudRecentSetId, 0, lang(lng_emoji_category0), QString(), 0, 0, qFlags(MTPDstickerSet_ClientFlag::f_special)));
} else {
it->title = lang(lng_emoji_category0);
}
it->hash = d.vhash.v;
auto custom = sets.find(Stickers::CustomSetId);
StickerPack pack;
pack.reserve(d_docs.size());
for (int32 i = 0, l = d_docs.size(); i != l; ++i) {
DocumentData *doc = App::feedDocument(d_docs.at(i));
if (!doc || !doc->sticker()) continue;
pack.push_back(doc);
if (custom != sets.cend()) {
int32 index = custom->stickers.indexOf(doc);
if (index >= 0) {
custom->stickers.removeAt(index);
}
}
}
if (custom != sets.cend() && custom->stickers.isEmpty()) {
sets.erase(custom);
custom = sets.end();
}
bool writeRecent = false;
RecentStickerPack &recent(cGetRecentStickers());
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
i = recent.erase(i);
writeRecent = true;
} else {
++i;
}
}
if (pack.isEmpty()) {
sets.erase(it);
} else {
it->stickers = pack;
it->emoji.clear();
}
if (writeRecent) {
Local::writeUserSettings();
}
}
if (Local::countRecentStickersHash() != d.vhash.v) {
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countRecentStickersHash()));
}
Local::writeRecentStickers();
if (App::main()) emit App::main()->stickersUpdated();
}
bool HistoryWidget::recentStickersFailed(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
LOG(("App Fail: Failed to get recent stickers!"));
Global::SetLastRecentStickersUpdate(getms(true));
_recentStickersUpdateRequest = 0;
return true;
}
void HistoryWidget::featuredStickersGot(const MTPmessages_FeaturedStickers &stickers) {
Global::SetLastFeaturedStickersUpdate(getms(true));
_featuredStickersUpdateRequest = 0;
if (stickers.type() != mtpc_messages_featuredStickers) return;
auto &d(stickers.c_messages_featuredStickers());
OrderedSet<uint64> unread;
for_const (auto &unreadSetId, d.vunread.c_vector().v) {
unread.insert(unreadSetId.v);
}
auto &d_sets(d.vsets.c_vector().v);
auto &setsOrder = Global::RefFeaturedStickerSetsOrder();
setsOrder.clear();
auto &sets = Global::RefStickerSets();
QMap<uint64, uint64> setsToRequest;
for (auto &set : sets) {
set.flags &= ~MTPDstickerSet_ClientFlag::f_featured; // mark for removing
}
for (int i = 0, l = d_sets.size(); i != l; ++i) {
if (d_sets.at(i).type() == mtpc_stickerSetCovered && d_sets.at(i).c_stickerSetCovered().vset.type() == mtpc_stickerSet) {
const auto &set(d_sets.at(i).c_stickerSetCovered().vset.c_stickerSet());
auto it = sets.find(set.vid.v);
QString title = stickerSetTitle(set);
if (it == sets.cend()) {
auto setClientFlags = MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_not_loaded;
if (unread.contains(set.vid.v)) {
setClientFlags |= MTPDstickerSet_ClientFlag::f_unread;
}
it = sets.insert(set.vid.v, Stickers::Set(set.vid.v, set.vaccess_hash.v, title, qs(set.vshort_name), set.vcount.v, set.vhash.v, set.vflags.v | setClientFlags));
} 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;
if (unread.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
}
}
setsOrder.push_back(set.vid.v);
if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
setsToRequest.insert(set.vid.v, set.vaccess_hash.v);
}
}
}
int unreadCount = 0;
for (auto it = sets.begin(), e = sets.end(); it != e;) {
bool installed = (it->flags & MTPDstickerSet::Flag::f_installed);
bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured);
bool special = (it->flags & MTPDstickerSet_ClientFlag::f_special);
bool archived = (it->flags & MTPDstickerSet::Flag::f_archived);
if (installed || featured || special || archived) {
if (featured && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) {
++unreadCount;
}
++it;
} else {
it = sets.erase(it);
}
}
Global::SetFeaturedStickerSetsUnreadCount(unreadCount);
if (Local::countFeaturedStickersHash() != d.vhash.v) {
LOG(("API Error: received featured stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countFeaturedStickersHash()));
}
if (!setsToRequest.isEmpty() && App::api()) {
for (QMap<uint64, uint64>::const_iterator i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
App::api()->scheduleStickerSetRequest(i.key(), i.value());
}
App::api()->requestStickerSets();
}
Local::writeFeaturedStickers();
if (App::main()) emit App::main()->stickersUpdated();
}
bool HistoryWidget::featuredStickersFailed(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
LOG(("App Fail: Failed to get featured stickers!"));
Global::SetLastFeaturedStickersUpdate(getms(true));
_featuredStickersUpdateRequest = 0;
return true;
}
void HistoryWidget::savedGifsGot(const MTPmessages_SavedGifs &gifs) { void HistoryWidget::savedGifsGot(const MTPmessages_SavedGifs &gifs) {
cSetLastSavedGifsUpdate(getms(true)); cSetLastSavedGifsUpdate(getms(true));
_savedGifsUpdateRequest = 0; _savedGifsUpdateRequest = 0;
@ -4575,7 +4767,7 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId
if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) { if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
PeerData *was = _peer; PeerData *was = _peer;
Ui::showChatsList(); App::main()->showBackFromStack();
Ui::showLayer(new InformBox(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); Ui::showLayer(new InformBox(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible)));
return true; return true;
} }
@ -4587,7 +4779,7 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId
_preloadDownRequest = 0; _preloadDownRequest = 0;
} else if (_firstLoadRequest == requestId) { } else if (_firstLoadRequest == requestId) {
_firstLoadRequest = 0; _firstLoadRequest = 0;
Ui::showChatsList(); App::main()->showBackFromStack();
} else if (_delayedShowAtRequest == requestId) { } else if (_delayedShowAtRequest == requestId) {
_delayedShowAtRequest = 0; _delayedShowAtRequest = 0;
} }
@ -5605,6 +5797,8 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC
toast.text = qs(answerData.vmessage); toast.text = qs(answerData.vmessage);
Ui::Toast::Show(App::wnd(), toast); Ui::Toast::Show(App::wnd(), toast);
} }
} else if (answerData.has_url()) {
HiddenUrlClickHandler(qs(answerData.vurl)).onClick(Qt::LeftButton);
} }
} }
} }
@ -6040,7 +6234,7 @@ void HistoryWidget::paintTopBar(Painter &p, float64 over, int32 decreaseWidth) {
if (!_history) return; if (!_history) return;
int32 increaseLeft = Adaptive::OneColumn() ? (st::topBarForwardPadding.right() - st::topBarForwardPadding.left()) : 0; int32 increaseLeft = (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) ? (st::topBarForwardPadding.right() - st::topBarForwardPadding.left()) : 0;
decreaseWidth += increaseLeft; decreaseWidth += increaseLeft;
QRect rectForName(st::topBarForwardPadding.left() + increaseLeft, st::topBarForwardPadding.top(), width() - decreaseWidth - st::topBarForwardPadding.left() - st::topBarForwardPadding.right(), st::msgNameFont->height); QRect rectForName(st::topBarForwardPadding.left() + increaseLeft, st::topBarForwardPadding.top(), width() - decreaseWidth - st::topBarForwardPadding.left() - st::topBarForwardPadding.right(), st::msgNameFont->height);
p.setFont(st::dialogsTextFont); p.setFont(st::dialogsTextFont);
@ -6055,7 +6249,7 @@ void HistoryWidget::paintTopBar(Painter &p, float64 over, int32 decreaseWidth) {
p.setPen(st::dialogsNameFg); p.setPen(st::dialogsNameFg);
_peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); _peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
if (Adaptive::OneColumn()) { if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) {
p.setOpacity(st::topBarForwardAlpha + (1 - st::topBarForwardAlpha) * over); p.setOpacity(st::topBarForwardAlpha + (1 - st::topBarForwardAlpha) * over);
p.drawSprite(QPoint((st::topBarForwardPadding.right() - st::topBarBackwardImg.pxWidth()) / 2, (st::topBarHeight - st::topBarBackwardImg.pxHeight()) / 2), st::topBarBackwardImg); p.drawSprite(QPoint((st::topBarForwardPadding.right() - st::topBarBackwardImg.pxWidth()) / 2, (st::topBarHeight - st::topBarBackwardImg.pxHeight()) / 2), st::topBarBackwardImg);
} else { } else {
@ -6065,7 +6259,7 @@ void HistoryWidget::paintTopBar(Painter &p, float64 over, int32 decreaseWidth) {
} }
QRect HistoryWidget::getMembersShowAreaGeometry() const { QRect HistoryWidget::getMembersShowAreaGeometry() const {
int increaseLeft = Adaptive::OneColumn() ? (st::topBarForwardPadding.right() - st::topBarForwardPadding.left()) : 0; int increaseLeft = (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) ? (st::topBarForwardPadding.right() - st::topBarForwardPadding.left()) : 0;
int membersTextLeft = st::topBarForwardPadding.left() + increaseLeft; int membersTextLeft = st::topBarForwardPadding.left() + increaseLeft;
int membersTextTop = st::topBarHeight - st::topBarForwardPadding.bottom() - st::dialogsTextFont->height; int membersTextTop = st::topBarHeight - st::topBarForwardPadding.bottom() - st::dialogsTextFont->height;
int membersTextWidth = _titlePeerTextWidth; int membersTextWidth = _titlePeerTextWidth;
@ -6111,8 +6305,8 @@ void HistoryWidget::onMembersDropdownHidden() {
} }
void HistoryWidget::topBarClick() { void HistoryWidget::topBarClick() {
if (Adaptive::OneColumn()) { if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) {
Ui::showChatsList(); App::main()->showBackFromStack();
} else { } else {
if (_history) Ui::showPeerProfile(_peer); if (_history) Ui::showPeerProfile(_peer);
} }
@ -6664,10 +6858,10 @@ void HistoryWidget::onReportSpamClear() {
if (_clearPeer->isUser()) { if (_clearPeer->isUser()) {
App::main()->deleteConversation(_clearPeer); App::main()->deleteConversation(_clearPeer);
} else if (_clearPeer->isChat()) { } else if (_clearPeer->isChat()) {
Ui::showChatsList(); App::main()->showBackFromStack();
MTP::send(MTPmessages_DeleteChatUser(_clearPeer->asChat()->inputChat, App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, _clearPeer), App::main()->rpcFail(&MainWidget::leaveChatFailed, _clearPeer)); MTP::send(MTPmessages_DeleteChatUser(_clearPeer->asChat()->inputChat, App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, _clearPeer), App::main()->rpcFail(&MainWidget::leaveChatFailed, _clearPeer));
} else if (_clearPeer->isChannel()) { } else if (_clearPeer->isChannel()) {
Ui::showChatsList(); App::main()->showBackFromStack();
if (_clearPeer->migrateFrom()) { if (_clearPeer->migrateFrom()) {
App::main()->deleteConversation(_clearPeer->migrateFrom()); App::main()->deleteConversation(_clearPeer->migrateFrom());
} }
@ -7195,7 +7389,7 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Escape) { if (e->key() == Qt::Key_Escape) {
e->ignore(); e->ignore();
} else if (e->key() == Qt::Key_Back) { } else if (e->key() == Qt::Key_Back) {
Ui::showChatsList(); App::main()->showBackFromStack();
emit cancelled(); emit cancelled();
} else if (e->key() == Qt::Key_PageDown) { } else if (e->key() == Qt::Key_PageDown) {
_scroll.keyPressEvent(e); _scroll.keyPressEvent(e);
@ -7973,7 +8167,7 @@ void HistoryWidget::onCancel() {
} else if (!_fieldAutocomplete->isHidden()) { } else if (!_fieldAutocomplete->isHidden()) {
_fieldAutocomplete->hideStart(); _fieldAutocomplete->hideStart();
} else { } else {
Ui::showChatsList(); App::main()->showBackFromStack();
emit cancelled(); emit cancelled();
} }
} }
@ -8011,7 +8205,7 @@ void HistoryWidget::peerUpdated(PeerData *data) {
} }
QString restriction = _peer->restrictionReason(); QString restriction = _peer->restrictionReason();
if (!restriction.isEmpty()) { if (!restriction.isEmpty()) {
Ui::showChatsList(); App::main()->showBackFromStack();
Ui::showLayer(new InformBox(restriction)); Ui::showLayer(new InformBox(restriction));
return; return;
} }

View file

@ -1005,6 +1005,14 @@ private:
void stickersGot(const MTPmessages_AllStickers &stickers); void stickersGot(const MTPmessages_AllStickers &stickers);
bool stickersFailed(const RPCError &error); bool stickersFailed(const RPCError &error);
mtpRequestId _recentStickersUpdateRequest = 0;
void recentStickersGot(const MTPmessages_RecentStickers &stickers);
bool recentStickersFailed(const RPCError &error);
mtpRequestId _featuredStickersUpdateRequest = 0;
void featuredStickersGot(const MTPmessages_FeaturedStickers &stickers);
bool featuredStickersFailed(const RPCError &error);
mtpRequestId _savedGifsUpdateRequest = 0; mtpRequestId _savedGifsUpdateRequest = 0;
void savedGifsGot(const MTPmessages_SavedGifs &gifs); void savedGifsGot(const MTPmessages_SavedGifs &gifs);
bool savedGifsFailed(const RPCError &error); bool savedGifsFailed(const RPCError &error);

View file

@ -352,7 +352,7 @@ void Result::createDocument() {
attributes.push_back(MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(_duration), MTPstring(), MTPstring(), MTPbytes())); attributes.push_back(MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(_duration), MTPstring(), MTPstring(), MTPbytes()));
} }
MTPDocument document = MTP_document(MTP_long(docId), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(0), MTP_photoSizeEmpty(MTP_string("")), MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes)); MTPDocument document = MTP_document(MTP_long(docId), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(0), MTP_photoSizeEmpty(MTP_string("")), MTP_int(MTP::maindc()), MTP_int(0), MTP_vector<MTPDocumentAttribute>(attributes));
_document = App::feedDocument(document); _document = App::feedDocument(document);
_document->setContentUrl(_content_url); _document->setContentUrl(_content_url);

View file

@ -414,9 +414,9 @@ void FileLoadTask::process() {
if (voice) { if (voice) {
attributes[0] = MTP_documentAttributeAudio(MTP_flags(MTPDdocumentAttributeAudio::Flag::f_voice | MTPDdocumentAttributeAudio::Flag::f_waveform), MTP_int(_duration), MTPstring(), MTPstring(), MTP_bytes(documentWaveformEncode5bit(_waveform))); attributes[0] = MTP_documentAttributeAudio(MTP_flags(MTPDdocumentAttributeAudio::Flag::f_voice | MTPDdocumentAttributeAudio::Flag::f_waveform), MTP_int(_duration), MTPstring(), MTPstring(), MTP_bytes(documentWaveformEncode5bit(_waveform)));
attributes.resize(1); attributes.resize(1);
document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes)); document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_int(0), MTP_vector<MTPDocumentAttribute>(attributes));
} else { } else {
document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes)); document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_int(0), MTP_vector<MTPDocumentAttribute>(attributes));
if (photo.type() == mtpc_photoEmpty) { if (photo.type() == mtpc_photoEmpty) {
_type = PrepareDocument; _type = PrepareDocument;
} }

View file

@ -479,11 +479,12 @@ namespace {
lskBackground = 0x08, // no data lskBackground = 0x08, // no data
lskUserSettings = 0x09, // no data lskUserSettings = 0x09, // no data
lskRecentHashtagsAndBots = 0x0a, // no data lskRecentHashtagsAndBots = 0x0a, // no data
lskStickers = 0x0b, // no data lskStickersOld = 0x0b, // no data
lskSavedPeers = 0x0c, // no data lskSavedPeers = 0x0c, // no data
lskReportSpamStatuses = 0x0d, // no data lskReportSpamStatuses = 0x0d, // no data
lskSavedGifsOld = 0x0e, // no data lskSavedGifsOld = 0x0e, // no data
lskSavedGifs = 0x0f, // no data lskSavedGifs = 0x0f, // no data
lskStickersKeys = 0x10, // no data
}; };
enum { enum {
@ -542,6 +543,7 @@ namespace {
dbiDialogsMode = 0x40, dbiDialogsMode = 0x40,
dbiModerateMode = 0x41, dbiModerateMode = 0x41,
dbiVideoVolume = 0x42, dbiVideoVolume = 0x42,
dbiStickersRecentLimit = 0x43,
dbiEncryptedWithSalt = 333, dbiEncryptedWithSalt = 333,
dbiEncrypted = 444, dbiEncrypted = 444,
@ -571,7 +573,9 @@ namespace {
uint64 _storageWebFilesSize = 0; uint64 _storageWebFilesSize = 0;
FileKey _locationsKey = 0, _reportSpamStatusesKey = 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; FileKey _backgroundKey = 0;
bool _backgroundWasRead = false; bool _backgroundWasRead = false;
@ -835,6 +839,14 @@ namespace {
Global::SetSavedGifsLimit(limit); Global::SetSavedGifsLimit(limit);
} break; } break;
case dbiStickersRecentLimit: {
qint32 limit;
stream >> limit;
if (!_checkStreamStatus(stream)) return false;
Global::SetStickersRecentLimit(limit);
} break;
case dbiMegagroupSizeMax: { case dbiMegagroupSizeMax: {
qint32 maxSize; qint32 maxSize;
stream >> maxSize; stream >> maxSize;
@ -1725,7 +1737,9 @@ namespace {
StorageMap imagesMap, stickerImagesMap, audiosMap; StorageMap imagesMap, stickerImagesMap, audiosMap;
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0; qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
quint64 locationsKey = 0, reportSpamStatusesKey = 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; quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsAndBotsKey = 0, savedPeersKey = 0;
while (!map.stream.atEnd()) { while (!map.stream.atEnd()) {
quint32 keyType; quint32 keyType;
@ -1806,8 +1820,11 @@ namespace {
case lskRecentHashtagsAndBots: { case lskRecentHashtagsAndBots: {
map.stream >> recentHashtagsAndBotsKey; map.stream >> recentHashtagsAndBotsKey;
} break; } break;
case lskStickers: { case lskStickersOld: {
map.stream >> stickersKey; map.stream >> installedStickersKey;
} break;
case lskStickersKeys: {
map.stream >> installedStickersKey >> featuredStickersKey >> recentStickersKey >> archivedStickersKey;
} break; } break;
case lskSavedGifsOld: { case lskSavedGifsOld: {
quint64 key; quint64 key;
@ -1842,7 +1859,10 @@ namespace {
_locationsKey = locationsKey; _locationsKey = locationsKey;
_reportSpamStatusesKey = reportSpamStatusesKey; _reportSpamStatusesKey = reportSpamStatusesKey;
_recentStickersKeyOld = recentStickersKeyOld; _recentStickersKeyOld = recentStickersKeyOld;
_stickersKey = stickersKey; _installedStickersKey = installedStickersKey;
_featuredStickersKey = featuredStickersKey;
_recentStickersKey = recentStickersKey;
_archivedStickersKey = archivedStickersKey;
_savedGifsKey = savedGifsKey; _savedGifsKey = savedGifsKey;
_savedPeersKey = savedPeersKey; _savedPeersKey = savedPeersKey;
_backgroundKey = backgroundKey; _backgroundKey = backgroundKey;
@ -1915,7 +1935,9 @@ namespace {
if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_reportSpamStatusesKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_reportSpamStatusesKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_recentStickersKeyOld) 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 (_savedGifsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
@ -1961,8 +1983,9 @@ namespace {
if (_recentStickersKeyOld) { if (_recentStickersKeyOld) {
mapData.stream << quint32(lskRecentStickersOld) << quint64(_recentStickersKeyOld); mapData.stream << quint32(lskRecentStickersOld) << quint64(_recentStickersKeyOld);
} }
if (_stickersKey) { if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) {
mapData.stream << quint32(lskStickers) << quint64(_stickersKey); mapData.stream << quint32(lskStickersKeys);
mapData.stream << quint64(_installedStickersKey) << quint64(_featuredStickersKey) << quint64(_recentStickersKey) << quint64(_archivedStickersKey);
} }
if (_savedGifsKey) { if (_savedGifsKey) {
mapData.stream << quint32(lskSavedGifs) << quint64(_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 += 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); EncryptedDescriptor data(size);
data.stream << quint32(dbiChatSizeMax) << qint32(Global::ChatSizeMax()); data.stream << quint32(dbiChatSizeMax) << qint32(Global::ChatSizeMax());
data.stream << quint32(dbiMegagroupSizeMax) << qint32(Global::MegagroupSizeMax()); data.stream << quint32(dbiMegagroupSizeMax) << qint32(Global::MegagroupSizeMax());
data.stream << quint32(dbiSavedGifsLimit) << qint32(Global::SavedGifsLimit()); data.stream << quint32(dbiSavedGifsLimit) << qint32(Global::SavedGifsLimit());
data.stream << quint32(dbiStickersRecentLimit) << qint32(Global::StickersRecentLimit());
data.stream << quint32(dbiAutoStart) << qint32(cAutoStart()); data.stream << quint32(dbiAutoStart) << qint32(cAutoStart());
data.stream << quint32(dbiStartMinimized) << qint32(cStartMinimized()); data.stream << quint32(dbiStartMinimized) << qint32(cStartMinimized());
data.stream << quint32(dbiSendToMenu) << qint32(cSendToMenu()); data.stream << quint32(dbiSendToMenu) << qint32(cSendToMenu());
@ -2247,7 +2271,9 @@ namespace Local {
_webFilesMap.clear(); _webFilesMap.clear();
_storageWebFilesSize = 0; _storageWebFilesSize = 0;
_locationsKey = _reportSpamStatusesKey = 0; _locationsKey = _reportSpamStatusesKey = 0;
_recentStickersKeyOld = _stickersKey = _savedGifsKey = 0; _recentStickersKeyOld = 0;
_installedStickersKey = _featuredStickersKey = _recentStickersKey = _archivedStickersKey = 0;
_savedGifsKey = 0;
_backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0; _backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0;
_oldMapVersion = _oldSettingsVersion = 0; _oldMapVersion = _oldSettingsVersion = 0;
_mapChanged = true; _mapChanged = true;
@ -3017,26 +3043,23 @@ namespace Local {
} }
} }
void _writeStickerSet(QDataStream &stream, uint64 setId) { void _writeStickerSet(QDataStream &stream, const Stickers::Set &set) {
auto it = Global::StickerSets().constFind(setId); bool notLoaded = (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded);
if (it == Global::StickerSets().cend()) return;
bool notLoaded = (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded);
if (notLoaded) { 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; return;
} else { } 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); 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 = it->stickers.cbegin(), e = it->stickers.cend(); j != e; ++j) { for (StickerPack::const_iterator j = set.stickers.cbegin(), e = set.stickers.cend(); j != e; ++j) {
Serialize::Document::writeToStream(stream, *j); Serialize::Document::writeToStream(stream, *j);
} }
if (AppVersion > 9018) { if (AppVersion > 9018) {
stream << qint32(it->emoji.size()); stream << qint32(set.emoji.size());
for (StickersByEmojiMap::const_iterator j = it->emoji.cbegin(), e = it->emoji.cend(); j != e; ++j) { for (StickersByEmojiMap::const_iterator j = set.emoji.cbegin(), e = set.emoji.cend(); j != e; ++j) {
stream << emojiString(j.key()) << qint32(j->size()); stream << emojiString(j.key()) << qint32(j->size());
for (int32 k = 0, l = j->size(); k < l; ++k) { for (int32 k = 0, l = j->size(); k < l; ++k) {
stream << quint64(j->at(k)->id); 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; if (!_working()) return;
const Stickers::Sets &sets(Global::StickerSets()); auto &sets = Global::StickerSets();
if (sets.isEmpty()) { if (sets.isEmpty()) {
if (_stickersKey) { if (stickersKey) {
clearKey(_stickersKey); clearKey(stickersKey);
_stickersKey = 0; stickersKey = 0;
_mapChanged = true; _mapChanged = true;
} }
_writeMap(); _writeMap();
} else { return;
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);
} }
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() { void importOldRecentStickers() {
@ -3113,17 +3349,17 @@ namespace Local {
return; return;
} }
Stickers::Sets &sets(Global::RefStickerSets()); auto &sets = Global::RefStickerSets();
sets.clear(); sets.clear();
Stickers::Order &order(Global::RefStickerSetsOrder()); auto &order = Global::RefStickerSetsOrder();
order.clear(); order.clear();
RecentStickerPack &recent(cRefRecentStickers()); auto &recent = cRefRecentStickers();
recent.clear(); 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()); 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();
Stickers::Set &custom(sets.insert(Stickers::CustomSetId, Stickers::Set(Stickers::CustomSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, 0)).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; QMap<uint64, bool> read;
while (!stickers.stream.atEnd()) { while (!stickers.stream.atEnd()) {
@ -3149,7 +3385,7 @@ namespace Local {
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height))); 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 (!doc->sticker()) continue;
if (value > 0) { if (value > 0) {
@ -3159,7 +3395,9 @@ namespace Local {
custom.stickers.push_back(doc); custom.stickers.push_back(doc);
++custom.count; ++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()) { if (def.stickers.isEmpty()) {
sets.remove(Stickers::DefaultSetId); sets.remove(Stickers::DefaultSetId);
@ -3168,7 +3406,7 @@ namespace Local {
} }
if (custom.stickers.isEmpty()) sets.remove(Stickers::CustomSetId); if (custom.stickers.isEmpty()) sets.remove(Stickers::CustomSetId);
writeStickers(); writeInstalledStickers();
writeUserSettings(); writeUserSettings();
clearKey(_recentStickersKeyOld); clearKey(_recentStickersKeyOld);
@ -3176,130 +3414,95 @@ namespace Local {
_writeMap(); _writeMap();
} }
void readStickers() { void readInstalledStickers() {
if (!_stickersKey) { if (!_installedStickersKey) {
return importOldRecentStickers(); return importOldRecentStickers();
} }
FileReadDescriptor stickers; Global::RefStickerSets().clear();
if (!readEncryptedFile(stickers, _stickersKey)) { _readStickerSets(_installedStickersKey, &Global::RefStickerSetsOrder(), qFlags(MTPDstickerSet::Flag::f_installed));
clearKey(_stickersKey); }
_stickersKey = 0;
_writeMap(); void readFeaturedStickers() {
return; _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()); void readRecentStickers() {
sets.clear(); _readStickerSets(_recentStickersKey);
}
Stickers::Order &order(Global::RefStickerSetsOrder()); void readArchivedStickers() {
order.clear(); static bool archivedStickersRead = false;
if (!archivedStickersRead) {
quint32 cnt; _readStickerSets(_archivedStickersKey, &Global::RefArchivedStickerSetsOrder());
QByteArray hash; archivedStickersRead = true;
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);
}
}
}
} }
} }
int32 countStickersHash(bool checkOfficial) { int32 countStickersHash(bool checkOutdatedInfo) {
uint32 acc = 0; uint32 acc = 0;
bool foundOfficial = false, foundBad = false;; bool foundOutdated = false;
const Stickers::Sets &sets(Global::StickerSets()); auto &sets = Global::StickerSets();
const Stickers::Order &order(Global::StickerSetsOrder()); auto &order = Global::StickerSetsOrder();
for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) { for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) {
auto j = sets.constFind(*i); auto j = sets.constFind(*i);
if (j != sets.cend()) { if (j != sets.cend()) {
if (j->id == 0) { if (j->id == Stickers::DefaultSetId) {
foundBad = true; foundOutdated = true;
} else if (j->flags & MTPDstickerSet::Flag::f_official) { } else if (!(j->flags & MTPDstickerSet_ClientFlag::f_special)
foundOfficial = true; && !(j->flags & MTPDstickerSet::Flag::f_archived)) {
}
if (!(j->flags & MTPDstickerSet::Flag::f_disabled)) {
acc = (acc * 20261) + j->hash; 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() { int32 countSavedGifsHash() {
uint32 acc = 0; uint32 acc = 0;
const SavedGifs &saved(cSavedGifs()); auto &saved = cSavedGifs();
for (SavedGifs::const_iterator i = saved.cbegin(), e = saved.cend(); i != e; ++i) { for_const (auto doc, saved) {
uint64 docId = (*i)->id; auto docId = doc->id;
acc = (acc * 20261) + uint32(docId >> 32); acc = (acc * 20261) + uint32(docId >> 32);
acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF); acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF);
} }
@ -3357,7 +3560,7 @@ namespace Local {
saved.reserve(cnt); saved.reserve(cnt);
OrderedSet<DocumentId> read; OrderedSet<DocumentId> read;
for (uint32 i = 0; i < cnt; ++i) { 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 (!document || !document->isAnimation()) continue;
if (read.contains(document->id)) continue; if (read.contains(document->id)) continue;
@ -3862,8 +4065,8 @@ namespace Local {
_recentStickersKeyOld = 0; _recentStickersKeyOld = 0;
_mapChanged = true; _mapChanged = true;
} }
if (_stickersKey) { if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) {
_stickersKey = 0; _installedStickersKey = _featuredStickersKey = _recentStickersKey = _archivedStickersKey = 0;
_mapChanged = true; _mapChanged = true;
} }
if (_recentHashtagsAndBotsKey) { if (_recentHashtagsAndBotsKey) {

View file

@ -153,9 +153,17 @@ namespace Local {
void cancelTask(TaskId id); void cancelTask(TaskId id);
void writeStickers(); void writeInstalledStickers();
void readStickers(); void writeFeaturedStickers();
int32 countStickersHash(bool checkOfficial = false); void writeRecentStickers();
void writeArchivedStickers();
void readInstalledStickers();
void readFeaturedStickers();
void readRecentStickers();
void readArchivedStickers();
int32 countStickersHash(bool checkOutdatedInfo = false);
int32 countRecentStickersHash();
int32 countFeaturedStickersHash();
void writeSavedGifs(); void writeSavedGifs();
void readSavedGifs(); void readSavedGifs();

View file

@ -298,11 +298,6 @@ void MainWidget::finishForwarding(History *history, bool silent) {
FullMsgId newId(peerToChannel(history->peer->id), clientMsgId()); FullMsgId newId(peerToChannel(history->peer->id), clientMsgId());
HistoryMessage *msg = static_cast<HistoryMessage*>(_toForward.cbegin().value()); HistoryMessage *msg = static_cast<HistoryMessage*>(_toForward.cbegin().value());
history->addNewForwarded(newId.msg, flags, date(MTP_int(unixtime())), showFromName ? MTP::authedId() : 0, msg); history->addNewForwarded(newId.msg, flags, date(MTP_int(unixtime())), showFromName ? MTP::authedId() : 0, msg);
if (HistoryMedia *media = msg->getMedia()) {
if (media->type() == MediaTypeSticker) {
App::main()->incrementSticker(media->getDocument());
}
}
App::historyRegRandom(randomId, newId); App::historyRegRandom(randomId, newId);
} }
if (forwardFrom != i.value()->history()->peer) { if (forwardFrom != i.value()->history()->peer) {
@ -1519,8 +1514,8 @@ void MainWidget::onSharePhoneWithBot(PeerData *recipient) {
onShareContact(recipient->id, App::self()); onShareContact(recipient->id, App::self());
} }
void MainWidget::ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId) { void MainWidget::ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId, Ui::ShowWay way) {
Ui::showPeerHistory(peerId, showAtMsgId); Ui::showPeerHistory(peerId, showAtMsgId, way);
} }
void MainWidget::ui_autoplayMediaInlineAsync(qint32 channelId, qint32 msgId) { void MainWidget::ui_autoplayMediaInlineAsync(qint32 channelId, qint32 msgId) {
@ -1995,7 +1990,7 @@ void MainWidget::ctrlEnterSubmitUpdated() {
_history->updateFieldSubmitSettings(); _history->updateFieldSubmitSettings();
} }
void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool back) { void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, Ui::ShowWay way) {
if (PeerData *peer = App::peerLoaded(peerId)) { if (PeerData *peer = App::peerLoaded(peerId)) {
if (peer->migrateTo()) { if (peer->migrateTo()) {
peer = peer->migrateTo(); peer = peer->migrateTo();
@ -2009,8 +2004,37 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac
return; return;
} }
} }
if (!back && (!peerId || (_stack.size() == 1 && _stack[0]->type() == HistoryStackItem && _stack[0]->peer->id == peerId))) {
back = true; bool back = (way == Ui::ShowWay::Backward || !peerId);
bool foundInStack = !peerId;
if (foundInStack || (way == Ui::ShowWay::ClearStack)) {
for_const (auto &item, _stack) {
clearBotStartToken(item->peer);
}
_stack.clear();
} else {
for (int i = 0, s = _stack.size(); i < s; ++i) {
if (_stack.at(i)->type() == HistoryStackItem && _stack.at(i)->peer->id == peerId) {
foundInStack = true;
while (_stack.size() > i) {
clearBotStartToken(_stack.back()->peer);
_stack.pop_back();
}
if (!back) {
back = true;
}
break;
}
}
}
if (back || (way == Ui::ShowWay::ClearStack)) {
dlgUpdated();
_peerInStack = nullptr;
_msgIdInStack = 0;
dlgUpdated();
} else {
saveSectionInStack();
} }
PeerData *wasActivePeer = activePeer(); PeerData *wasActivePeer = activePeer();
@ -2022,10 +2046,12 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac
} }
Window::SectionSlideParams animationParams; Window::SectionSlideParams animationParams;
if (!_a_show.animating() && ((_history->isHidden() && (_wideSection || _overview)) || (Adaptive::OneColumn() && (_history->isHidden() || !peerId)))) { if (!_a_show.animating() && ((_history->isHidden() && (_wideSection || _overview)) || (Adaptive::OneColumn() && (_history->isHidden() || !peerId)) || back || (way == Ui::ShowWay::Forward))) {
animationParams = prepareHistoryAnimation(peerId); animationParams = prepareHistoryAnimation(peerId);
} }
if (_history->peer() && _history->peer()->id != peerId) clearBotStartToken(_history->peer()); if (_history->peer() && _history->peer()->id != peerId) {
clearBotStartToken(_history->peer());
}
_history->showHistory(peerId, showAtMsgId); _history->showHistory(peerId, showAtMsgId);
bool noPeer = (!_history->peer() || !_history->peer()->id), onlyDialogs = noPeer && Adaptive::OneColumn(); bool noPeer = (!_history->peer() || !_history->peer()->id), onlyDialogs = noPeer && Adaptive::OneColumn();
@ -2042,11 +2068,6 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac
_overview->rpcClear(); _overview->rpcClear();
_overview = nullptr; _overview = nullptr;
} }
clearBotStartToken(_peerInStack);
dlgUpdated();
_peerInStack = 0;
_msgIdInStack = 0;
_stack.clear();
} }
if (onlyDialogs) { if (onlyDialogs) {
_topBar->hide(); _topBar->hide();
@ -2090,6 +2111,7 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac
} }
_dialogs->update(); _dialogs->update();
} }
topBar()->showAll();
App::wnd()->getTitle()->updateBackButton(); App::wnd()->getTitle()->updateBackButton();
} }
@ -2146,6 +2168,21 @@ bool MainWidget::mediaTypeSwitch() {
return true; return true;
} }
void MainWidget::saveSectionInStack() {
if (_overview) {
_stack.push_back(std_::make_unique<StackItemOverview>(_overview->peer(), _overview->type(), _overview->lastWidth(), _overview->lastScrollTop()));
} else if (_wideSection) {
_stack.push_back(std_::make_unique<StackItemSection>(_wideSection->createMemento()));
} else if (_history->peer()) {
dlgUpdated();
_peerInStack = _history->peer();
_msgIdInStack = _history->msgId();
dlgUpdated();
_stack.push_back(std_::make_unique<StackItemHistory>(_peerInStack, _msgIdInStack, _history->replyReturns()));
}
}
void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool back, int32 lastScrollTop) { void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool back, int32 lastScrollTop) {
if (peer->migrateTo()) { if (peer->migrateTo()) {
peer = peer->migrateTo(); peer = peer->migrateTo();
@ -2166,17 +2203,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
animationParams = prepareOverviewAnimation(); animationParams = prepareOverviewAnimation();
} }
if (!back) { if (!back) {
if (_overview) { saveSectionInStack();
_stack.push_back(new StackItemOverview(_overview->peer(), _overview->type(), _overview->lastWidth(), _overview->lastScrollTop()));
} else if (_wideSection) {
_stack.push_back(new StackItemSection(_wideSection->createMemento()));
} else if (_history->peer()) {
dlgUpdated();
_peerInStack = _history->peer();
_msgIdInStack = _history->msgId();
dlgUpdated();
_stack.push_back(new StackItemHistory(_peerInStack, _msgIdInStack, _history->replyReturns()));
}
} }
if (_overview) { if (_overview) {
_overview->hide(); _overview->hide();
@ -2201,7 +2228,9 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
_overview->fastShow(); _overview->fastShow();
} }
_history->animStop(); _history->animStop();
if (back) clearBotStartToken(_history->peer()); if (back) {
clearBotStartToken(_history->peer());
}
_history->showHistory(0, 0); _history->showHistory(0, 0);
_history->hide(); _history->hide();
if (Adaptive::OneColumn()) _dialogs->hide(); if (Adaptive::OneColumn()) _dialogs->hide();
@ -2217,17 +2246,7 @@ void MainWidget::showWideSection(const Window::SectionMemento &memento) {
return; return;
} }
if (_overview) { saveSectionInStack();
_stack.push_back(new StackItemOverview(_overview->peer(), _overview->type(), _overview->lastWidth(), _overview->lastScrollTop()));
} else if (_wideSection) {
_stack.push_back(new StackItemSection(_wideSection->createMemento()));
} else if (_history->peer()) {
dlgUpdated();
_peerInStack = _history->peer();
_msgIdInStack = _history->msgId();
dlgUpdated();
_stack.push_back(new StackItemHistory(_peerInStack, _msgIdInStack, _history->replyReturns()));
}
showWideSectionAnimated(&memento, false); showWideSectionAnimated(&memento, false);
} }
@ -2320,6 +2339,10 @@ void MainWidget::showWideSectionAnimated(const Window::SectionMemento *memento,
App::wnd()->getTitle()->updateBackButton(); App::wnd()->getTitle()->updateBackButton();
} }
bool MainWidget::stackIsEmpty() const {
return _stack.isEmpty();
}
void MainWidget::showBackFromStack() { void MainWidget::showBackFromStack() {
if (selectingPeer()) return; if (selectingPeer()) return;
if (_stack.isEmpty()) { if (_stack.isEmpty()) {
@ -2327,34 +2350,33 @@ void MainWidget::showBackFromStack() {
if (App::wnd()) QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus())); if (App::wnd()) QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus()));
return; return;
} }
StackItem *item = _stack.back(); auto item = std_::move(_stack.back());
_stack.pop_back(); _stack.pop_back();
if (auto currentHistoryPeer = _history->peer()) { if (auto currentHistoryPeer = _history->peer()) {
clearBotStartToken(currentHistoryPeer); clearBotStartToken(currentHistoryPeer);
} }
if (item->type() == HistoryStackItem) { if (item->type() == HistoryStackItem) {
dlgUpdated(); dlgUpdated();
_peerInStack = 0; _peerInStack = nullptr;
_msgIdInStack = 0; _msgIdInStack = 0;
for (int32 i = _stack.size(); i > 0;) { for (int32 i = _stack.size(); i > 0;) {
if (_stack.at(--i)->type() == HistoryStackItem) { if (_stack.at(--i)->type() == HistoryStackItem) {
_peerInStack = static_cast<StackItemHistory*>(_stack.at(i))->peer; _peerInStack = static_cast<StackItemHistory*>(_stack.at(i).get())->peer;
_msgIdInStack = static_cast<StackItemHistory*>(_stack.at(i))->msgId; _msgIdInStack = static_cast<StackItemHistory*>(_stack.at(i).get())->msgId;
dlgUpdated(); dlgUpdated();
break; break;
} }
} }
StackItemHistory *histItem = static_cast<StackItemHistory*>(item); StackItemHistory *histItem = static_cast<StackItemHistory*>(item.get());
Ui::showPeerHistory(histItem->peer->id, App::main()->activeMsgId(), true); Ui::showPeerHistory(histItem->peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Backward);
_history->setReplyReturns(histItem->peer->id, histItem->replyReturns); _history->setReplyReturns(histItem->peer->id, histItem->replyReturns);
} else if (item->type() == SectionStackItem) { } else if (item->type() == SectionStackItem) {
StackItemSection *sectionItem = static_cast<StackItemSection*>(item); StackItemSection *sectionItem = static_cast<StackItemSection*>(item.get());
showWideSectionAnimated(sectionItem->memento(), true); showWideSectionAnimated(sectionItem->memento(), true);
} else if (item->type() == OverviewStackItem) { } else if (item->type() == OverviewStackItem) {
StackItemOverview *overItem = static_cast<StackItemOverview*>(item); StackItemOverview *overItem = static_cast<StackItemOverview*>(item.get());
showMediaOverview(overItem->peer, overItem->mediaType, true, overItem->lastScrollTop); showMediaOverview(overItem->peer, overItem->mediaType, true, overItem->lastScrollTop);
} }
delete item;
} }
void MainWidget::orderWidgets() { void MainWidget::orderWidgets() {
@ -3251,7 +3273,9 @@ void MainWidget::start(const MTPUser &user) {
} }
_started = true; _started = true;
App::wnd()->sendServiceHistoryRequest(); App::wnd()->sendServiceHistoryRequest();
Local::readStickers(); Local::readInstalledStickers();
Local::readFeaturedStickers();
Local::readRecentStickers();
Local::readSavedGifs(); Local::readSavedGifs();
_history->start(); _history->start();
} }
@ -3322,7 +3346,7 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr
Ui::showLayer(new ContactsBox(peer->asUser())); Ui::showLayer(new ContactsBox(peer->asUser()));
} else if (peer->isUser() && peer->asUser()->botInfo) { } else if (peer->isUser() && peer->asUser()->botInfo) {
// Always open bot chats, even from mention links. // Always open bot chats, even from mention links.
Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId); Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward);
} else { } else {
Ui::showPeerProfile(peer); Ui::showPeerProfile(peer);
} }
@ -3337,7 +3361,7 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr
_history->resizeEvent(0); _history->resizeEvent(0);
} }
} }
Ui::showPeerHistoryAsync(peer->id, msgId); Ui::showPeerHistoryAsync(peer->id, msgId, Ui::ShowWay::Forward);
} }
} else { } else {
MTP::send(MTPcontacts_ResolveUsername(MTP_string(username)), rpcDone(&MainWidget::usernameResolveDone, qMakePair(msgId, startToken)), rpcFail(&MainWidget::usernameResolveFail, username)); MTP::send(MTPcontacts_ResolveUsername(MTP_string(username)), rpcDone(&MainWidget::usernameResolveDone, qMakePair(msgId, startToken)), rpcFail(&MainWidget::usernameResolveFail, username));
@ -3357,7 +3381,6 @@ void MainWidget::stickersBox(const MTPInputStickerSet &set) {
} }
void MainWidget::onStickersInstalled(uint64 setId) { void MainWidget::onStickersInstalled(uint64 setId) {
emit stickersUpdated();
_history->stickersInstalled(setId); _history->stickersInstalled(setId);
} }
@ -3405,7 +3428,7 @@ void MainWidget::usernameResolveDone(QPair<MsgId, QString> msgIdAndStartToken, c
Ui::showLayer(new ContactsBox(peer->asUser())); Ui::showLayer(new ContactsBox(peer->asUser()));
} else if (peer->isUser() && peer->asUser()->botInfo) { } else if (peer->isUser() && peer->asUser()->botInfo) {
// Always open bot chats, even from mention links. // Always open bot chats, even from mention links.
Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId); Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward);
} else { } else {
Ui::showPeerProfile(peer); Ui::showPeerProfile(peer);
} }
@ -3436,11 +3459,21 @@ bool MainWidget::usernameResolveFail(QString name, const RPCError &error) {
void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) { void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) {
switch (invite.type()) { switch (invite.type()) {
case mtpc_chatInvite: { case mtpc_chatInvite: {
const auto &d(invite.c_chatInvite()); auto &d(invite.c_chatInvite());
ConfirmBox *box = new ConfirmBox(((d.is_channel() && !d.is_megagroup()) ? lng_group_invite_want_join_channel : lng_group_invite_want_join)(lt_title, qs(d.vtitle)), lang(lng_group_invite_join));
QVector<UserData*> participants;
if (d.has_participants()) {
auto &v = d.vparticipants.c_vector().v;
participants.reserve(v.size());
for_const (auto &user, v) {
if (auto feededUser = App::feedUser(user)) {
participants.push_back(feededUser);
}
}
}
auto box = std_::make_unique<ConfirmInviteBox>(qs(d.vtitle), d.vphoto, d.vparticipants_count.v, participants);
_inviteHash = hash; _inviteHash = hash;
connect(box, SIGNAL(confirmed()), this, SLOT(onInviteImport())); Ui::showLayer(box.release());
Ui::showLayer(box);
} break; } break;
case mtpc_chatInviteAlready: { case mtpc_chatInviteAlready: {
@ -3618,72 +3651,65 @@ void MainWidget::updateNotifySetting(PeerData *peer, NotifySettingStatus notify,
void MainWidget::incrementSticker(DocumentData *sticker) { void MainWidget::incrementSticker(DocumentData *sticker) {
if (!sticker || !sticker->sticker()) return; if (!sticker || !sticker->sticker()) return;
if (sticker->sticker()->set.type() == mtpc_inputStickerSetEmpty) return;
RecentStickerPack &recent(cGetRecentStickers()); bool writeRecentStickers = false;
RecentStickerPack::iterator i = recent.begin(), e = recent.end(); auto &sets = Global::RefStickerSets();
for (; i != e; ++i) { auto it = sets.find(Stickers::CloudRecentSetId);
if (it == sets.cend()) {
if (it == sets.cend()) {
it = sets.insert(Stickers::CloudRecentSetId, Stickers::Set(Stickers::CloudRecentSetId, 0, lang(lng_emoji_category0), QString(), 0, 0, qFlags(MTPDstickerSet_ClientFlag::f_special)));
} else {
it->title = lang(lng_emoji_category0);
}
}
auto index = it->stickers.indexOf(sticker);
if (index > 0) {
it->stickers.removeAt(index);
}
if (index) {
it->stickers.push_front(sticker);
writeRecentStickers = true;
}
// Remove that sticker from old recent, now it is in cloud recent stickers.
bool writeOldRecent = false;
auto &recent = cGetRecentStickers();
for (auto i = recent.begin(), e = recent.end(); i != e; ++i) {
if (i->first == sticker) { if (i->first == sticker) {
i->second = recent.begin()->second; // throw to the first place writeOldRecent = true;
//++i->second; recent.erase(i);
//if (i->second > 0x8000) {
// for (RecentStickerPack::iterator j = recent.begin(); j != e; ++j) {
// if (j->second > 1) {
// j->second /= 2;
// } else {
// j->second = 1;
// }
// }
//}
for (; i != recent.begin(); --i) {
if ((i - 1)->second > i->second) {
break;
}
qSwap(*i, *(i - 1));
}
break; break;
} }
} }
if (i == e) { while (!recent.isEmpty() && it->stickers.size() + recent.size() > Global::StickersRecentLimit()) {
while (recent.size() >= StickerPanPerRow * StickerPanRowsPerPage) recent.pop_back(); writeOldRecent = true;
recent.push_front(qMakePair(sticker, recent.isEmpty() ? 1 : recent.begin()->second)); recent.pop_back();
//recent.push_back(qMakePair(sticker, 1));
//for (i = recent.end() - 1; i != recent.begin(); --i) {
// if ((i - 1)->second > i->second) {
// break;
// }
// qSwap(*i, *(i - 1));
//}
} }
Local::writeUserSettings(); if (writeOldRecent) {
Local::writeUserSettings();
bool found = false;
uint64 setId = 0;
QString setName;
switch (sticker->sticker()->set.type()) {
case mtpc_inputStickerSetID: setId = sticker->sticker()->set.c_inputStickerSetID().vid.v; break;
case mtpc_inputStickerSetShortName: setName = qs(sticker->sticker()->set.c_inputStickerSetShortName().vshort_name).toLower().trimmed(); break;
} }
Stickers::Sets &sets(Global::RefStickerSets());
for (auto i = sets.cbegin(); i != sets.cend(); ++i) { // Remove that sticker from custom stickers, now it is in cloud recent stickers.
if (i->id == Stickers::CustomSetId || i->id == Stickers::DefaultSetId || (setId && i->id == setId) || (!setName.isEmpty() && i->shortName.toLower().trimmed() == setName)) { bool writeInstalledStickers = false;
for (int32 j = 0, l = i->stickers.size(); j < l; ++j) { auto custom = sets.find(Stickers::CustomSetId);
if (i->stickers.at(j) == sticker) { if (custom != sets.cend()) {
found = true; int removeIndex = custom->stickers.indexOf(sticker);
break; if (removeIndex >= 0) {
} custom->stickers.removeAt(removeIndex);
if (custom->stickers.isEmpty()) {
sets.erase(custom);
} }
if (found) break; writeInstalledStickers = true;
} }
} }
if (!found) {
Stickers::Sets::iterator it = sets.find(Stickers::CustomSetId); if (writeInstalledStickers) {
if (it == sets.cend()) { Local::writeInstalledStickers();
it = sets.insert(Stickers::CustomSetId, Stickers::Set(Stickers::CustomSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, 0)); }
} if (writeRecentStickers) {
it->stickers.push_back(sticker); Local::writeRecentStickers();
++it->count;
Local::writeStickers();
} }
_history->updateRecentStickers(); _history->updateRecentStickers();
} }
@ -4625,16 +4651,23 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
////// Cloud sticker sets ////// Cloud sticker sets
case mtpc_updateNewStickerSet: { case mtpc_updateNewStickerSet: {
const auto &d(update.c_updateNewStickerSet()); auto &d = update.c_updateNewStickerSet();
bool writeArchived = false;
if (d.vstickerset.type() == mtpc_messages_stickerSet) { if (d.vstickerset.type() == mtpc_messages_stickerSet) {
const auto &set(d.vstickerset.c_messages_stickerSet()); auto &set = d.vstickerset.c_messages_stickerSet();
if (set.vset.type() == mtpc_stickerSet) { if (set.vset.type() == mtpc_stickerSet) {
const auto &s(set.vset.c_stickerSet()); auto &s = set.vset.c_stickerSet();
Stickers::Sets &sets(Global::RefStickerSets()); auto &sets = Global::RefStickerSets();
auto it = sets.find(s.vid.v); auto it = sets.find(s.vid.v);
if (it == sets.cend()) { if (it == sets.cend()) {
it = sets.insert(s.vid.v, Stickers::Set(s.vid.v, s.vaccess_hash.v, stickerSetTitle(s), qs(s.vshort_name), s.vcount.v, s.vhash.v, s.vflags.v)); it = sets.insert(s.vid.v, Stickers::Set(s.vid.v, s.vaccess_hash.v, stickerSetTitle(s), qs(s.vshort_name), s.vcount.v, s.vhash.v, s.vflags.v | MTPDstickerSet::Flag::f_installed));
} else {
it->flags |= MTPDstickerSet::Flag::f_installed;
if (it->flags & MTPDstickerSet::Flag::f_archived) {
it->flags &= ~MTPDstickerSet::Flag::f_archived;
writeArchived = true;
}
} }
const auto &v(set.vdocuments.c_vector().v); const auto &v(set.vdocuments.c_vector().v);
@ -4647,12 +4680,12 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
it->stickers.push_back(doc); it->stickers.push_back(doc);
} }
it->emoji.clear(); it->emoji.clear();
const auto &packs(set.vpacks.c_vector().v); auto &packs = set.vpacks.c_vector().v;
for (int32 i = 0, l = packs.size(); i < l; ++i) { for (int32 i = 0, l = packs.size(); i < l; ++i) {
if (packs.at(i).type() != mtpc_stickerPack) continue; if (packs.at(i).type() != mtpc_stickerPack) continue;
const auto &pack(packs.at(i).c_stickerPack()); auto &pack = packs.at(i).c_stickerPack();
if (EmojiPtr e = emojiGetNoColor(emojiFromText(qs(pack.vemoticon)))) { if (EmojiPtr e = emojiGetNoColor(emojiFromText(qs(pack.vemoticon)))) {
const auto &stickers(pack.vdocuments.c_vector().v); auto &stickers = pack.vdocuments.c_vector().v;
StickerPack p; StickerPack p;
p.reserve(stickers.size()); p.reserve(stickers.size());
for (int32 j = 0, c = stickers.size(); j < c; ++j) { for (int32 j = 0, c = stickers.size(); j < c; ++j) {
@ -4684,16 +4717,17 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
sets.erase(custom); sets.erase(custom);
} }
} }
Local::writeStickers(); Local::writeInstalledStickers();
if (writeArchived) Local::writeArchivedStickers();
emit stickersUpdated(); emit stickersUpdated();
} }
} }
} break; } break;
case mtpc_updateStickerSetsOrder: { case mtpc_updateStickerSetsOrder: {
const auto &d(update.c_updateStickerSetsOrder()); auto &d = update.c_updateStickerSetsOrder();
const auto &order(d.vorder.c_vector().v); auto &order = d.vorder.c_vector().v;
const auto &sets(Global::StickerSets()); auto &sets = Global::StickerSets();
Stickers::Order result; Stickers::Order result;
for (int32 i = 0, l = order.size(); i < l; ++i) { for (int32 i = 0, l = order.size(); i < l; ++i) {
if (sets.constFind(order.at(i).v) == sets.cend()) { if (sets.constFind(order.at(i).v) == sets.cend()) {
@ -4706,7 +4740,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
App::main()->updateStickers(); App::main()->updateStickers();
} else { } else {
Global::SetStickerSetsOrder(result); Global::SetStickerSetsOrder(result);
Local::writeStickers(); Local::writeInstalledStickers();
emit stickersUpdated(); emit stickersUpdated();
} }
} break; } break;
@ -4716,6 +4750,24 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
App::main()->updateStickers(); App::main()->updateStickers();
} break; } break;
case mtpc_updateRecentStickers: {
Global::SetLastStickersUpdate(0);
App::main()->updateStickers();
} break;
case mtpc_updateReadFeaturedStickers: {
for (auto &set : Global::RefStickerSets()) {
if (set.flags & MTPDstickerSet_ClientFlag::f_unread) {
set.flags &= ~MTPDstickerSet_ClientFlag::f_unread;
}
}
if (Global::FeaturedStickerSetsUnreadCount()) {
Global::SetFeaturedStickerSetsUnreadCount(0);
Local::writeFeaturedStickers();
emit stickersUpdated();
}
} break;
////// Cloud saved GIFs ////// Cloud saved GIFs
case mtpc_updateSavedGifs: { case mtpc_updateSavedGifs: {
cSetLastSavedGifsUpdate(0); cSetLastSavedGifsUpdate(0);

View file

@ -108,27 +108,6 @@ public:
int32 lastWidth, lastScrollTop; int32 lastWidth, lastScrollTop;
}; };
class StackItems : public QVector<StackItem*> {
public:
bool contains(PeerData *peer) const {
for (int32 i = 0, l = size(); i < l; ++i) {
if (at(i)->peer == peer) {
return true;
}
}
return false;
}
void clear() {
for (int32 i = 0, l = size(); i < l; ++i) {
delete at(i);
}
QVector<StackItem*>::clear();
}
~StackItems() {
clear();
}
};
enum SilentNotifiesStatus { enum SilentNotifiesStatus {
SilentNotifiesDontChange, SilentNotifiesDontChange,
SilentNotifiesSetSilent, SilentNotifiesSetSilent,
@ -224,6 +203,7 @@ public:
bool mediaTypeSwitch(); bool mediaTypeSwitch();
void showWideSection(const Window::SectionMemento &memento); void showWideSection(const Window::SectionMemento &memento);
void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1); void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1);
bool stackIsEmpty() const;
void showBackFromStack(); void showBackFromStack();
void orderWidgets(); void orderWidgets();
QRect historyRect() const; QRect historyRect() const;
@ -404,7 +384,7 @@ public:
void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout); void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
bool ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout); bool ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout);
bool ui_isInlineItemBeingChosen(); bool ui_isInlineItemBeingChosen();
void ui_showPeerHistory(quint64 peer, qint32 msgId, bool back); void ui_showPeerHistory(quint64 peer, qint32 msgId, Ui::ShowWay way);
PeerData *ui_getPeerForMouseAction(); PeerData *ui_getPeerForMouseAction();
void notify_botCommandsChanged(UserData *bot); void notify_botCommandsChanged(UserData *bot);
@ -492,7 +472,7 @@ public slots:
void onSharePhoneWithBot(PeerData *recipient); void onSharePhoneWithBot(PeerData *recipient);
void ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId); void ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId, Ui::ShowWay way);
void ui_autoplayMediaInlineAsync(qint32 channelId, qint32 msgId); void ui_autoplayMediaInlineAsync(qint32 channelId, qint32 msgId);
private slots: private slots:
@ -518,6 +498,8 @@ private:
Window::SectionSlideParams prepareOverviewAnimation(); Window::SectionSlideParams prepareOverviewAnimation();
Window::SectionSlideParams prepareDialogsAnimation(); Window::SectionSlideParams prepareDialogsAnimation();
void saveSectionInStack();
bool _started = false; bool _started = false;
uint64 failedObjId = 0; uint64 failedObjId = 0;
@ -597,7 +579,7 @@ private:
ChildWidget<Window::TopBarWidget> _topBar; ChildWidget<Window::TopBarWidget> _topBar;
ConfirmBox *_forwardConfirm = nullptr; // for single column layout ConfirmBox *_forwardConfirm = nullptr; // for single column layout
ChildWidget<HistoryHider> _hider = { nullptr }; ChildWidget<HistoryHider> _hider = { nullptr };
StackItems _stack; std_::vector_of_moveable<std_::unique_ptr<StackItem>> _stack;
PeerData *_peerInStack = nullptr; PeerData *_peerInStack = nullptr;
MsgId _msgIdInStack = 0; MsgId _msgIdInStack = 0;

View file

@ -1556,7 +1556,7 @@ void MediaView::paintEvent(QPaintEvent *e) {
if (_saveMsgOpacity.current() > 0) { if (_saveMsgOpacity.current() > 0) {
p.setOpacity(_saveMsgOpacity.current()); p.setOpacity(_saveMsgOpacity.current());
App::roundRect(p, _saveMsg, st::medviewSaveMsg, MediaviewSaveCorners); App::roundRect(p, _saveMsg, st::medviewSaveMsg, MediaviewSaveCorners);
p.drawSprite(_saveMsg.topLeft() + st::medviewSaveMsgCheckPos, st::medviewSaveMsgCheck); st::medviewSaveMsgCheck.paint(p, _saveMsg.topLeft() + st::medviewSaveMsgCheckPos, width());
p.setPen(st::white->p); p.setPen(st::white->p);
textstyleSet(&st::medviewSaveAsTextStyle); textstyleSet(&st::medviewSaveAsTextStyle);

View file

@ -1060,8 +1060,17 @@ enum class MTPDstickerSet_ClientFlag : int32 {
// sticker set is not yet loaded // sticker set is not yet loaded
f_not_loaded = (1 << 30), f_not_loaded = (1 << 30),
// sticker set is one of featured (should be saved locally)
f_featured = (1 << 29),
// sticker set is an unread featured set
f_unread = (1 << 28),
// special set like recent or custom stickers
f_special = (1 << 27),
// update this when adding new client side flags // update this when adding new client side flags
MIN_FIELD = (1 << 30), MIN_FIELD = (1 << 27),
}; };
DEFINE_MTP_CLIENT_FLAGS(MTPDstickerSet) DEFINE_MTP_CLIENT_FLAGS(MTPDstickerSet)

View file

@ -170,6 +170,7 @@ namespace {
Global::SetPushChatLimit(data.vpush_chat_limit.v); // ? Global::SetPushChatLimit(data.vpush_chat_limit.v); // ?
Global::SetSavedGifsLimit(data.vsaved_gifs_limit.v); Global::SetSavedGifsLimit(data.vsaved_gifs_limit.v);
Global::SetEditTimeLimit(data.vedit_time_limit.v); // ? Global::SetEditTimeLimit(data.vedit_time_limit.v); // ?
Global::SetStickersRecentLimit(data.vstickers_recent_limit.v);
configLoadedOnce = true; configLoadedOnce = true;
Local::writeSettings(); Local::writeSettings();

View file

@ -351,13 +351,8 @@ void FileLoader::startLoading(bool loadFirst, bool prior) {
mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading) mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading)
: FileLoader(QString(), size, UnknownFileLocation, LoadToCacheAsWell, fromCloud, autoLoading) : FileLoader(QString(), size, UnknownFileLocation, LoadToCacheAsWell, fromCloud, autoLoading)
, _lastComplete(false)
, _skippedBytes(0)
, _nextRequestOffset(0)
, _dc(location->dc()) , _dc(location->dc())
, _location(location) , _location(location) {
, _id(0)
, _access(0) {
LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0)); LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0));
if (i == queues.cend()) { if (i == queues.cend()) {
i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries)); i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries));
@ -365,15 +360,12 @@ mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, L
_queue = &i.value(); _queue = &i.value();
} }
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &to, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading) mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, int32 version, LocationType type, const QString &to, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading)
: FileLoader(to, size, type, toCache, fromCloud, autoLoading) : FileLoader(to, size, type, toCache, fromCloud, autoLoading)
, _lastComplete(false)
, _skippedBytes(0)
, _nextRequestOffset(0)
, _dc(dc) , _dc(dc)
, _location(0)
, _id(id) , _id(id)
, _access(access) { , _access(access)
, _version(version) {
LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0)); LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0));
if (i == queues.cend()) { if (i == queues.cend()) {
i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries)); i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries));
@ -422,7 +414,7 @@ bool mtpFileLoader::loadPart() {
switch (_locationType) { switch (_locationType) {
case VideoFileLocation: case VideoFileLocation:
case AudioFileLocation: case AudioFileLocation:
case DocumentFileLocation: loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access)); break; case DocumentFileLocation: loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access), MTP_int(_version)); break;
default: cancel(true); return false; break; default: cancel(true); return false; break;
} }
} }
@ -532,7 +524,7 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
if (_localStatus == LocalNotFound || _localStatus == LocalFailed) { if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
if (_locationType != UnknownFileLocation) { // audio, video, document if (_locationType != UnknownFileLocation) { // audio, video, document
MediaKey mkey = mediaKey(_locationType, _dc, _id); MediaKey mkey = mediaKey(_locationType, _dc, _id, _version);
if (!_fname.isEmpty()) { if (!_fname.isEmpty()) {
Local::writeFileLocation(mkey, FileLocation(mtpToStorageType(_type), _fname)); Local::writeFileLocation(mkey, FileLocation(mtpToStorageType(_type), _fname));
} }
@ -594,7 +586,7 @@ bool mtpFileLoader::tryLoadLocal() {
_localTaskId = Local::startImageLoad(storageKey(*_location), this); _localTaskId = Local::startImageLoad(storageKey(*_location), this);
} else { } else {
if (_toCache == LoadToCacheAsWell) { if (_toCache == LoadToCacheAsWell) {
MediaKey mkey = mediaKey(_locationType, _dc, _id); MediaKey mkey = mediaKey(_locationType, _dc, _id, _version);
if (_locationType == DocumentFileLocation) { if (_locationType == DocumentFileLocation) {
_localTaskId = Local::startStickerImageLoad(mkey, this); _localTaskId = Local::startStickerImageLoad(mkey, this);
} else if (_locationType == AudioFileLocation) { } else if (_locationType == AudioFileLocation) {

View file

@ -28,6 +28,8 @@ namespace MTP {
enum LocationType { enum LocationType {
UnknownFileLocation = 0, UnknownFileLocation = 0,
// 1, 2, etc are used as "version" value in mediaKey() method.
DocumentFileLocation = 0x4e45abe9, // mtpc_inputDocumentFileLocation DocumentFileLocation = 0x4e45abe9, // mtpc_inputDocumentFileLocation
AudioFileLocation = 0x74dc404d, // mtpc_inputAudioFileLocation AudioFileLocation = 0x74dc404d, // mtpc_inputAudioFileLocation
VideoFileLocation = 0x3d0364ec, // mtpc_inputVideoFileLocation VideoFileLocation = 0x3d0364ec, // mtpc_inputVideoFileLocation
@ -221,9 +223,8 @@ class mtpFileLoader : public FileLoader, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading); mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading);
mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &toFile, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading); mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, int32 version, LocationType type, const QString &toFile, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading);
virtual int32 currentOffset(bool includeSkipped = false) const; virtual int32 currentOffset(bool includeSkipped = false) const;
@ -245,7 +246,6 @@ public:
~mtpFileLoader(); ~mtpFileLoader();
protected: protected:
virtual bool tryLoadLocal(); virtual bool tryLoadLocal();
virtual void cancelRequests(); virtual void cancelRequests();
@ -256,15 +256,16 @@ protected:
void partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req); void partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req);
bool partFailed(const RPCError &error); bool partFailed(const RPCError &error);
bool _lastComplete; bool _lastComplete = false;
int32 _skippedBytes; int32 _skippedBytes = 0;
int32 _nextRequestOffset; int32 _nextRequestOffset = 0;
int32 _dc; int32 _dc;
const StorageImageLocation *_location; const StorageImageLocation *_location = nullptr;
uint64 _id; // for other locations uint64 _id = 0; // for other locations
uint64 _access; uint64 _access = 0;
int32 _version = 0;
}; };

View file

@ -168,7 +168,7 @@ inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto;
inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation; inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation;
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation; inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation; inputDocumentFileLocation#430f0724 id:long access_hash:long version:int = InputFileLocation;
inputPhotoCropAuto#ade6b004 = InputPhotoCrop; inputPhotoCropAuto#ade6b004 = InputPhotoCrop;
inputPhotoCrop#d9915325 crop_left:double crop_top:double crop_width:double = InputPhotoCrop; inputPhotoCrop#d9915325 crop_left:double crop_top:double crop_width:double = InputPhotoCrop;
@ -392,6 +392,8 @@ updateEditMessage#e40370a3 message:Message pts:int pts_count:int = Update;
updateInlineBotCallbackQuery#2cbd95af query_id:long user_id:int msg_id:InputBotInlineMessageID data:bytes = Update; updateInlineBotCallbackQuery#2cbd95af query_id:long user_id:int msg_id:InputBotInlineMessageID data:bytes = Update;
updateReadChannelOutbox#25d6c9c7 channel_id:int max_id:int = Update; updateReadChannelOutbox#25d6c9c7 channel_id:int max_id:int = Update;
updateDraftMessage#ee2bb969 peer:Peer draft:DraftMessage = Update; updateDraftMessage#ee2bb969 peer:Peer draft:DraftMessage = Update;
updateReadFeaturedStickers#571d2742 = Update;
updateRecentStickers#9a422c20 = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -416,7 +418,7 @@ upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true id:int ip_address:string port:int = DcOption; dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true id:int ip_address:string port:int = DcOption;
config#c9411388 date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int disabled_features:Vector<DisabledFeature> = Config; config#f401a4bf date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int disabled_features:Vector<DisabledFeature> = Config;
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc; nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
@ -454,7 +456,7 @@ inputDocumentEmpty#72f0eaae = InputDocument;
inputDocument#18798952 id:long access_hash:long = InputDocument; inputDocument#18798952 id:long access_hash:long = InputDocument;
documentEmpty#36f8c871 id:long = Document; documentEmpty#36f8c871 id:long = Document;
document#f9a39f4f id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector<DocumentAttribute> = Document; document#87232bc7 id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int version:int attributes:Vector<DocumentAttribute> = Document;
help.support#17c6b5f6 phone_number:string user:User = help.Support; help.support#17c6b5f6 phone_number:string user:User = help.Support;
@ -547,13 +549,13 @@ chatInviteEmpty#69df3769 = ExportedChatInvite;
chatInviteExported#fc2e05bc link:string = ExportedChatInvite; chatInviteExported#fc2e05bc link:string = ExportedChatInvite;
chatInviteAlready#5a686d7c chat:Chat = ChatInvite; chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
chatInvite#93e99b60 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string = ChatInvite; chatInvite#db74f558 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:ChatPhoto participants_count:int participants:flags.4?Vector<User> = ChatInvite;
inputStickerSetEmpty#ffb62b95 = InputStickerSet; inputStickerSetEmpty#ffb62b95 = InputStickerSet;
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet; inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet; inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
stickerSet#cd303b41 flags:# installed:flags.0?true disabled:flags.1?true official:flags.2?true id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet; stickerSet#cd303b41 flags:# installed:flags.0?true archived:flags.1?true official:flags.2?true id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet;
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet; messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
@ -670,7 +672,7 @@ auth.sentCodeTypeSms#c000bba2 length:int = auth.SentCodeType;
auth.sentCodeTypeCall#5353e5a7 length:int = auth.SentCodeType; auth.sentCodeTypeCall#5353e5a7 length:int = auth.SentCodeType;
auth.sentCodeTypeFlashCall#ab03c6d9 pattern:string = auth.SentCodeType; auth.sentCodeTypeFlashCall#ab03c6d9 pattern:string = auth.SentCodeType;
messages.botCallbackAnswer#1264f1c6 flags:# alert:flags.1?true message:flags.0?string = messages.BotCallbackAnswer; messages.botCallbackAnswer#b10df1fb flags:# alert:flags.1?true message:flags.0?string url:flags.2?string = messages.BotCallbackAnswer;
messages.messageEditData#26b5dde6 flags:# caption:flags.0?true = messages.MessageEditData; messages.messageEditData#26b5dde6 flags:# caption:flags.0?true = messages.MessageEditData;
@ -696,6 +698,19 @@ contacts.topPeers#70b772a8 categories:Vector<TopPeerCategoryPeers> chats:Vector<
draftMessageEmpty#ba4baec5 = DraftMessage; draftMessageEmpty#ba4baec5 = DraftMessage;
draftMessage#fd8e711f flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int message:string entities:flags.3?Vector<MessageEntity> date:int = DraftMessage; draftMessage#fd8e711f flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int message:string entities:flags.3?Vector<MessageEntity> date:int = DraftMessage;
messages.featuredStickersNotModified#4ede3cf = messages.FeaturedStickers;
messages.featuredStickers#f89d88e5 hash:int sets:Vector<StickerSetCovered> unread:Vector<long> = messages.FeaturedStickers;
messages.recentStickersNotModified#b17f890 = messages.RecentStickers;
messages.recentStickers#5ce20970 hash:int stickers:Vector<Document> = messages.RecentStickers;
messages.archivedStickers#4fcba9c8 count:int sets:Vector<StickerSetCovered> = messages.ArchivedStickers;
messages.stickerSetInstallResultSuccess#38641628 = messages.StickerSetInstallResult;
messages.stickerSetInstallResultArchive#35e410a8 sets:Vector<StickerSetCovered> = messages.StickerSetInstallResult;
stickerSetCovered#6410a5d2 set:StickerSet cover:Document = StickerSetCovered;
---functions--- ---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -806,7 +821,7 @@ messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite;
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite; messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
messages.importChatInvite#6c50051c hash:string = Updates; messages.importChatInvite#6c50051c hash:string = Updates;
messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet; messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
messages.installStickerSet#7b30c3a6 stickerset:InputStickerSet disabled:Bool = Bool; messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult;
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool; messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates; messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates;
messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector<int> increment:Bool = Vector<int>; messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector<int> increment:Bool = Vector<int>;
@ -826,10 +841,17 @@ messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEdi
messages.editMessage#ce91e4ca flags:# no_webpage:flags.1?true peer:InputPeer id:int message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Updates; messages.editMessage#ce91e4ca flags:# no_webpage:flags.1?true peer:InputPeer id:int message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Updates;
messages.editInlineBotMessage#130c2c85 flags:# no_webpage:flags.1?true id:InputBotInlineMessageID message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Bool; messages.editInlineBotMessage#130c2c85 flags:# no_webpage:flags.1?true id:InputBotInlineMessageID message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Bool;
messages.getBotCallbackAnswer#a6e94f04 peer:InputPeer msg_id:int data:bytes = messages.BotCallbackAnswer; messages.getBotCallbackAnswer#a6e94f04 peer:InputPeer msg_id:int data:bytes = messages.BotCallbackAnswer;
messages.setBotCallbackAnswer#481c591a flags:# alert:flags.1?true query_id:long message:flags.0?string = Bool; messages.setBotCallbackAnswer#c927d44b flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string = Bool;
messages.getPeerDialogs#2d9776b9 peers:Vector<InputPeer> = messages.PeerDialogs; messages.getPeerDialogs#2d9776b9 peers:Vector<InputPeer> = messages.PeerDialogs;
messages.saveDraft#bc39e14b flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int peer:InputPeer message:string entities:flags.3?Vector<MessageEntity> = Bool; messages.saveDraft#bc39e14b flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int peer:InputPeer message:string entities:flags.3?Vector<MessageEntity> = Bool;
messages.getAllDrafts#6a3f8d65 = Updates; messages.getAllDrafts#6a3f8d65 = Updates;
messages.getFeaturedStickers#2dacca4f hash:int = messages.FeaturedStickers;
messages.readFeaturedStickers#e21cbb = Bool;
messages.getRecentStickers#99197c2c hash:int = messages.RecentStickers;
messages.saveRecentSticker#348e39bf id:InputDocument unsave:Bool = Bool;
messages.clearRecentStickers#ab02e5d2 = Bool;
messages.getUnusedStickers#4309d65b limit:int = Vector<StickerSetCovered>;
messages.getArchivedStickers#906e241f offset_id:long limit:int = messages.ArchivedStickers;
updates.getState#edd4882a = updates.State; updates.getState#edd4882a = updates.State;
updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference; updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference;
@ -880,4 +902,4 @@ channels.exportMessageLink#c846d22d channel:InputChannel id:int = ExportedMessag
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates; channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
channels.updatePinnedMessage#a72ded52 flags:# silent:flags.0?true channel:InputChannel id:int = Updates; channels.updatePinnedMessage#a72ded52 flags:# silent:flags.0?true channel:InputChannel id:int = Updates;
// LAYER 53 // LAYER 54

View file

@ -828,6 +828,7 @@ void _serialize_inputDocumentFileLocation(MTPStringLogger &to, int32 stage, int3
switch (stage) { switch (stage) {
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" version: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
} }
} }
@ -3012,6 +3013,14 @@ void _serialize_updateDraftMessage(MTPStringLogger &to, int32 stage, int32 lev,
} }
} }
void _serialize_updateReadFeaturedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ updateReadFeaturedStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_updateRecentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ updateRecentStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_updates_state(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { void _serialize_updates_state(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) { if (stage) {
to.add(",\n").addSpaces(lev); to.add(",\n").addSpaces(lev);
@ -3320,7 +3329,8 @@ void _serialize_config(MTPStringLogger &to, int32 stage, int32 lev, Types &types
case 17: to.add(" saved_gifs_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 17: to.add(" saved_gifs_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 18: to.add(" edit_time_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 18: to.add(" edit_time_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 19: to.add(" rating_e_decay: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 19: to.add(" rating_e_decay: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 20: to.add(" disabled_features: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 20: to.add(" stickers_recent_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 21: to.add(" disabled_features: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
} }
} }
@ -3672,7 +3682,8 @@ void _serialize_document(MTPStringLogger &to, int32 stage, int32 lev, Types &typ
case 4: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 4: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" thumb: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 5: to.add(" thumb: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 6: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 7: to.add(" attributes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 7: to.add(" version: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 8: to.add(" attributes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
} }
} }
@ -4339,6 +4350,9 @@ void _serialize_chatInvite(MTPStringLogger &to, int32 stage, int32 lev, Types &t
case 3: to.add(" public: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_public) { to.add("YES [ BY BIT 2 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break; case 3: to.add(" public: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_public) { to.add("YES [ BY BIT 2 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 4: to.add(" megagroup: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_megagroup) { to.add("YES [ BY BIT 3 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break; case 4: to.add(" megagroup: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_megagroup) { to.add("YES [ BY BIT 3 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
case 5: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 5: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 7: to.add(" participants_count: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 8: to.add(" participants: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_participants) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 4 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
} }
} }
@ -4386,7 +4400,7 @@ void _serialize_stickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &t
switch (stage) { switch (stage) {
case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" installed: "); ++stages.back(); if (flag & MTPDstickerSet::Flag::f_installed) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; case 1: to.add(" installed: "); ++stages.back(); if (flag & MTPDstickerSet::Flag::f_installed) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
case 2: to.add(" disabled: "); ++stages.back(); if (flag & MTPDstickerSet::Flag::f_disabled) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break; case 2: to.add(" archived: "); ++stages.back(); if (flag & MTPDstickerSet::Flag::f_archived) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
case 3: to.add(" official: "); ++stages.back(); if (flag & MTPDstickerSet::Flag::f_official) { to.add("YES [ BY BIT 2 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break; case 3: to.add(" official: "); ++stages.back(); if (flag & MTPDstickerSet::Flag::f_official) { to.add("YES [ BY BIT 2 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 4: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 4: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 5: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
@ -5587,6 +5601,7 @@ void _serialize_messages_botCallbackAnswer(MTPStringLogger &to, int32 stage, int
case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" alert: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_alert) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break; case 1: to.add(" alert: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_alert) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
case 2: to.add(" message: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_message) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; case 2: to.add(" message: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_message) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
case 3: to.add(" url: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_url) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
} }
} }
@ -5745,6 +5760,88 @@ void _serialize_draftMessage(MTPStringLogger &to, int32 stage, int32 lev, Types
} }
} }
void _serialize_messages_featuredStickersNotModified(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ messages_featuredStickersNotModified }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_messages_featuredStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_featuredStickers");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" sets: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" unread: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long+0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_messages_recentStickersNotModified(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ messages_recentStickersNotModified }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_messages_recentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_recentStickers");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" stickers: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_messages_archivedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_archivedStickers");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" count: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" sets: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_messages_stickerSetInstallResultSuccess(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ messages_stickerSetInstallResultSuccess }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_messages_stickerSetInstallResultArchive(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_stickerSetInstallResultArchive");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" sets: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_stickerSetCovered(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ stickerSetCovered");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" set: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" cover: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_req_pq(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { void _serialize_req_pq(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) { if (stage) {
to.add(",\n").addSpaces(lev); to.add(",\n").addSpaces(lev);
@ -6421,20 +6518,6 @@ void _serialize_messages_readEncryptedHistory(MTPStringLogger &to, int32 stage,
} }
} }
void _serialize_messages_installStickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_installStickerSet");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" stickerset: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" disabled: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_messages_uninstallStickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { void _serialize_messages_uninstallStickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) { if (stage) {
to.add(",\n").addSpaces(lev); to.add(",\n").addSpaces(lev);
@ -6546,6 +6629,7 @@ void _serialize_messages_setBotCallbackAnswer(MTPStringLogger &to, int32 stage,
case 1: to.add(" alert: "); ++stages.back(); if (flag & MTPmessages_setBotCallbackAnswer::Flag::f_alert) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break; case 1: to.add(" alert: "); ++stages.back(); if (flag & MTPmessages_setBotCallbackAnswer::Flag::f_alert) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
case 2: to.add(" query_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 2: to.add(" query_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" message: "); ++stages.back(); if (flag & MTPmessages_setBotCallbackAnswer::Flag::f_message) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; case 3: to.add(" message: "); ++stages.back(); if (flag & MTPmessages_setBotCallbackAnswer::Flag::f_message) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
case 4: to.add(" url: "); ++stages.back(); if (flag & MTPmessages_setBotCallbackAnswer::Flag::f_url) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
} }
} }
@ -6570,6 +6654,28 @@ void _serialize_messages_saveDraft(MTPStringLogger &to, int32 stage, int32 lev,
} }
} }
void _serialize_messages_readFeaturedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ messages_readFeaturedStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_messages_saveRecentSticker(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_saveRecentSticker");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" unsave: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_messages_clearRecentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ messages_clearRecentStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_upload_saveFilePart(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { void _serialize_upload_saveFilePart(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) { if (stage) {
to.add(",\n").addSpaces(lev); to.add(",\n").addSpaces(lev);
@ -7906,6 +8012,20 @@ void _serialize_messages_getStickerSet(MTPStringLogger &to, int32 stage, int32 l
} }
} }
void _serialize_messages_installStickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_installStickerSet");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" stickerset: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" archived: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_messages_getDocumentByHash(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { void _serialize_messages_getDocumentByHash(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) { if (stage) {
to.add(",\n").addSpaces(lev); to.add(",\n").addSpaces(lev);
@ -8010,6 +8130,59 @@ void _serialize_messages_getPeerDialogs(MTPStringLogger &to, int32 stage, int32
} }
} }
void _serialize_messages_getFeaturedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_getFeaturedStickers");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_messages_getRecentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_getRecentStickers");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_messages_getUnusedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_getUnusedStickers");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_messages_getArchivedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_getArchivedStickers");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_updates_getState(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { void _serialize_updates_getState(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ updates_getState }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); to.add("{ updates_getState }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
} }
@ -8467,6 +8640,8 @@ namespace {
_serializers.insert(mtpc_updateInlineBotCallbackQuery, _serialize_updateInlineBotCallbackQuery); _serializers.insert(mtpc_updateInlineBotCallbackQuery, _serialize_updateInlineBotCallbackQuery);
_serializers.insert(mtpc_updateReadChannelOutbox, _serialize_updateReadChannelOutbox); _serializers.insert(mtpc_updateReadChannelOutbox, _serialize_updateReadChannelOutbox);
_serializers.insert(mtpc_updateDraftMessage, _serialize_updateDraftMessage); _serializers.insert(mtpc_updateDraftMessage, _serialize_updateDraftMessage);
_serializers.insert(mtpc_updateReadFeaturedStickers, _serialize_updateReadFeaturedStickers);
_serializers.insert(mtpc_updateRecentStickers, _serialize_updateRecentStickers);
_serializers.insert(mtpc_updates_state, _serialize_updates_state); _serializers.insert(mtpc_updates_state, _serialize_updates_state);
_serializers.insert(mtpc_updates_differenceEmpty, _serialize_updates_differenceEmpty); _serializers.insert(mtpc_updates_differenceEmpty, _serialize_updates_differenceEmpty);
_serializers.insert(mtpc_updates_difference, _serialize_updates_difference); _serializers.insert(mtpc_updates_difference, _serialize_updates_difference);
@ -8680,6 +8855,14 @@ namespace {
_serializers.insert(mtpc_contacts_topPeers, _serialize_contacts_topPeers); _serializers.insert(mtpc_contacts_topPeers, _serialize_contacts_topPeers);
_serializers.insert(mtpc_draftMessageEmpty, _serialize_draftMessageEmpty); _serializers.insert(mtpc_draftMessageEmpty, _serialize_draftMessageEmpty);
_serializers.insert(mtpc_draftMessage, _serialize_draftMessage); _serializers.insert(mtpc_draftMessage, _serialize_draftMessage);
_serializers.insert(mtpc_messages_featuredStickersNotModified, _serialize_messages_featuredStickersNotModified);
_serializers.insert(mtpc_messages_featuredStickers, _serialize_messages_featuredStickers);
_serializers.insert(mtpc_messages_recentStickersNotModified, _serialize_messages_recentStickersNotModified);
_serializers.insert(mtpc_messages_recentStickers, _serialize_messages_recentStickers);
_serializers.insert(mtpc_messages_archivedStickers, _serialize_messages_archivedStickers);
_serializers.insert(mtpc_messages_stickerSetInstallResultSuccess, _serialize_messages_stickerSetInstallResultSuccess);
_serializers.insert(mtpc_messages_stickerSetInstallResultArchive, _serialize_messages_stickerSetInstallResultArchive);
_serializers.insert(mtpc_stickerSetCovered, _serialize_stickerSetCovered);
_serializers.insert(mtpc_req_pq, _serialize_req_pq); _serializers.insert(mtpc_req_pq, _serialize_req_pq);
_serializers.insert(mtpc_req_DH_params, _serialize_req_DH_params); _serializers.insert(mtpc_req_DH_params, _serialize_req_DH_params);
@ -8731,7 +8914,6 @@ namespace {
_serializers.insert(mtpc_messages_discardEncryption, _serialize_messages_discardEncryption); _serializers.insert(mtpc_messages_discardEncryption, _serialize_messages_discardEncryption);
_serializers.insert(mtpc_messages_setEncryptedTyping, _serialize_messages_setEncryptedTyping); _serializers.insert(mtpc_messages_setEncryptedTyping, _serialize_messages_setEncryptedTyping);
_serializers.insert(mtpc_messages_readEncryptedHistory, _serialize_messages_readEncryptedHistory); _serializers.insert(mtpc_messages_readEncryptedHistory, _serialize_messages_readEncryptedHistory);
_serializers.insert(mtpc_messages_installStickerSet, _serialize_messages_installStickerSet);
_serializers.insert(mtpc_messages_uninstallStickerSet, _serialize_messages_uninstallStickerSet); _serializers.insert(mtpc_messages_uninstallStickerSet, _serialize_messages_uninstallStickerSet);
_serializers.insert(mtpc_messages_editChatAdmin, _serialize_messages_editChatAdmin); _serializers.insert(mtpc_messages_editChatAdmin, _serialize_messages_editChatAdmin);
_serializers.insert(mtpc_messages_reorderStickerSets, _serialize_messages_reorderStickerSets); _serializers.insert(mtpc_messages_reorderStickerSets, _serialize_messages_reorderStickerSets);
@ -8740,6 +8922,9 @@ namespace {
_serializers.insert(mtpc_messages_editInlineBotMessage, _serialize_messages_editInlineBotMessage); _serializers.insert(mtpc_messages_editInlineBotMessage, _serialize_messages_editInlineBotMessage);
_serializers.insert(mtpc_messages_setBotCallbackAnswer, _serialize_messages_setBotCallbackAnswer); _serializers.insert(mtpc_messages_setBotCallbackAnswer, _serialize_messages_setBotCallbackAnswer);
_serializers.insert(mtpc_messages_saveDraft, _serialize_messages_saveDraft); _serializers.insert(mtpc_messages_saveDraft, _serialize_messages_saveDraft);
_serializers.insert(mtpc_messages_readFeaturedStickers, _serialize_messages_readFeaturedStickers);
_serializers.insert(mtpc_messages_saveRecentSticker, _serialize_messages_saveRecentSticker);
_serializers.insert(mtpc_messages_clearRecentStickers, _serialize_messages_clearRecentStickers);
_serializers.insert(mtpc_upload_saveFilePart, _serialize_upload_saveFilePart); _serializers.insert(mtpc_upload_saveFilePart, _serialize_upload_saveFilePart);
_serializers.insert(mtpc_upload_saveBigFilePart, _serialize_upload_saveBigFilePart); _serializers.insert(mtpc_upload_saveBigFilePart, _serialize_upload_saveBigFilePart);
_serializers.insert(mtpc_help_saveAppLog, _serialize_help_saveAppLog); _serializers.insert(mtpc_help_saveAppLog, _serialize_help_saveAppLog);
@ -8836,6 +9021,7 @@ namespace {
_serializers.insert(mtpc_channels_exportInvite, _serialize_channels_exportInvite); _serializers.insert(mtpc_channels_exportInvite, _serialize_channels_exportInvite);
_serializers.insert(mtpc_messages_checkChatInvite, _serialize_messages_checkChatInvite); _serializers.insert(mtpc_messages_checkChatInvite, _serialize_messages_checkChatInvite);
_serializers.insert(mtpc_messages_getStickerSet, _serialize_messages_getStickerSet); _serializers.insert(mtpc_messages_getStickerSet, _serialize_messages_getStickerSet);
_serializers.insert(mtpc_messages_installStickerSet, _serialize_messages_installStickerSet);
_serializers.insert(mtpc_messages_getDocumentByHash, _serialize_messages_getDocumentByHash); _serializers.insert(mtpc_messages_getDocumentByHash, _serialize_messages_getDocumentByHash);
_serializers.insert(mtpc_messages_searchGifs, _serialize_messages_searchGifs); _serializers.insert(mtpc_messages_searchGifs, _serialize_messages_searchGifs);
_serializers.insert(mtpc_messages_getSavedGifs, _serialize_messages_getSavedGifs); _serializers.insert(mtpc_messages_getSavedGifs, _serialize_messages_getSavedGifs);
@ -8843,6 +9029,10 @@ namespace {
_serializers.insert(mtpc_messages_getMessageEditData, _serialize_messages_getMessageEditData); _serializers.insert(mtpc_messages_getMessageEditData, _serialize_messages_getMessageEditData);
_serializers.insert(mtpc_messages_getBotCallbackAnswer, _serialize_messages_getBotCallbackAnswer); _serializers.insert(mtpc_messages_getBotCallbackAnswer, _serialize_messages_getBotCallbackAnswer);
_serializers.insert(mtpc_messages_getPeerDialogs, _serialize_messages_getPeerDialogs); _serializers.insert(mtpc_messages_getPeerDialogs, _serialize_messages_getPeerDialogs);
_serializers.insert(mtpc_messages_getFeaturedStickers, _serialize_messages_getFeaturedStickers);
_serializers.insert(mtpc_messages_getRecentStickers, _serialize_messages_getRecentStickers);
_serializers.insert(mtpc_messages_getUnusedStickers, _serialize_messages_getUnusedStickers);
_serializers.insert(mtpc_messages_getArchivedStickers, _serialize_messages_getArchivedStickers);
_serializers.insert(mtpc_updates_getState, _serialize_updates_getState); _serializers.insert(mtpc_updates_getState, _serialize_updates_getState);
_serializers.insert(mtpc_updates_getDifference, _serialize_updates_getDifference); _serializers.insert(mtpc_updates_getDifference, _serialize_updates_getDifference);
_serializers.insert(mtpc_updates_getChannelDifference, _serialize_updates_getChannelDifference); _serializers.insert(mtpc_updates_getChannelDifference, _serialize_updates_getChannelDifference);

File diff suppressed because it is too large Load diff

View file

@ -467,7 +467,7 @@ void CoverWidget::onOnlineCountUpdated(int onlineCount) {
} }
void CoverWidget::onSendMessage() { void CoverWidget::onSendMessage() {
Ui::showPeerHistory(_peer, ShowAtUnreadMsgId); Ui::showPeerHistory(_peer, ShowAtUnreadMsgId, Ui::ShowWay::Forward);
} }
void CoverWidget::onShareContact() { void CoverWidget::onShareContact() {

View file

@ -37,6 +37,7 @@ namespace Serialize {
void Document::writeToStream(QDataStream &stream, DocumentData *document) { void Document::writeToStream(QDataStream &stream, DocumentData *document) {
stream << quint64(document->id) << quint64(document->_access) << qint32(document->date); stream << quint64(document->id) << quint64(document->_access) << qint32(document->date);
stream << qint32(document->_version);
stream << document->name << document->mime << qint32(document->_dc) << qint32(document->size); stream << document->name << document->mime << qint32(document->_dc) << qint32(document->size);
stream << qint32(document->dimensions.width()) << qint32(document->dimensions.height()); stream << qint32(document->dimensions.width()) << qint32(document->dimensions.height());
stream << qint32(document->type); stream << qint32(document->type);
@ -61,11 +62,16 @@ void Document::writeToStream(QDataStream &stream, DocumentData *document) {
} }
} }
DocumentData *Document::readFromStreamHelper(QDataStream &stream, const StickerSetInfo *info) { DocumentData *Document::readFromStreamHelper(int streamAppVersion, QDataStream &stream, const StickerSetInfo *info) {
quint64 id, access; quint64 id, access;
QString name, mime; QString name, mime;
qint32 date, dc, size, width, height, type; qint32 date, dc, size, width, height, type, version;
stream >> id >> access >> date; stream >> id >> access >> date;
if (streamAppVersion >= 9061) {
stream >> version;
} else {
version = 0;
}
stream >> name >> mime >> dc >> size; stream >> name >> mime >> dc >> size;
stream >> width >> height; stream >> width >> height;
stream >> type; stream >> type;
@ -87,7 +93,7 @@ DocumentData *Document::readFromStreamHelper(QDataStream &stream, const StickerS
if (typeOfSet == StickerSetTypeEmpty) { if (typeOfSet == StickerSetTypeEmpty) {
attributes.push_back(MTP_documentAttributeSticker(MTP_string(alt), MTP_inputStickerSetEmpty())); attributes.push_back(MTP_documentAttributeSticker(MTP_string(alt), MTP_inputStickerSetEmpty()));
} else if (info) { } else if (info) {
if (info->setId == Stickers::DefaultSetId || info->setId == Stickers::CustomSetId) { if (info->setId == Stickers::DefaultSetId || info->setId == Stickers::CloudRecentSetId || info->setId == Stickers::CustomSetId) {
typeOfSet = StickerSetTypeEmpty; typeOfSet = StickerSetTypeEmpty;
} }
@ -122,22 +128,22 @@ DocumentData *Document::readFromStreamHelper(QDataStream &stream, const StickerS
if (!dc && !access) { if (!dc && !access) {
return nullptr; return nullptr;
} }
return App::documentSet(id, nullptr, access, date, attributes, mime, thumb.isNull() ? ImagePtr() : ImagePtr(thumb), dc, size, thumb); return App::documentSet(id, nullptr, access, version, date, attributes, mime, thumb.isNull() ? ImagePtr() : ImagePtr(thumb), dc, size, thumb);
} }
DocumentData *Document::readStickerFromStream(QDataStream &stream, const StickerSetInfo &info) { DocumentData *Document::readStickerFromStream(int streamAppVersion, QDataStream &stream, const StickerSetInfo &info) {
return readFromStreamHelper(stream, &info); return readFromStreamHelper(streamAppVersion, stream, &info);
} }
DocumentData *Document::readFromStream(QDataStream &stream) { DocumentData *Document::readFromStream(int streamAppVersion, QDataStream &stream) {
return readFromStreamHelper(stream, nullptr); return readFromStreamHelper(streamAppVersion, stream, nullptr);
} }
int Document::sizeInStream(DocumentData *document) { int Document::sizeInStream(DocumentData *document) {
int result = 0; int result = 0;
// id + access + date // id + access + date + version
result += sizeof(quint64) + sizeof(quint64) + sizeof(qint32); result += sizeof(quint64) + sizeof(quint64) + sizeof(qint32) + sizeof(qint32);
// + namelen + name + mimelen + mime + dc + size // + namelen + name + mimelen + mime + dc + size
result += stringSize(document->name) + stringSize(document->mime) + sizeof(qint32) + sizeof(qint32); result += stringSize(document->name) + stringSize(document->mime) + sizeof(qint32) + sizeof(qint32);
// + width + height // + width + height

View file

@ -39,12 +39,12 @@ public:
}; };
static void writeToStream(QDataStream &stream, DocumentData *document); static void writeToStream(QDataStream &stream, DocumentData *document);
static DocumentData *readStickerFromStream(QDataStream &stream, const StickerSetInfo &info); static DocumentData *readStickerFromStream(int streamAppVersion, QDataStream &stream, const StickerSetInfo &info);
static DocumentData *readFromStream(QDataStream &stream); static DocumentData *readFromStream(int streamAppVersion, QDataStream &stream);
static int sizeInStream(DocumentData *document); static int sizeInStream(DocumentData *document);
private: private:
static DocumentData *readFromStreamHelper(QDataStream &stream, const StickerSetInfo *info); static DocumentData *readFromStreamHelper(int streamAppVersion, QDataStream &stream, const StickerSetInfo *info);
}; };

View file

@ -849,16 +849,10 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) {
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onSwitchModerateMode())); connect(box.get(), SIGNAL(confirmed()), this, SLOT(onSwitchModerateMode()));
Ui::showLayer(box.release()); Ui::showLayer(box.release());
break; break;
} else if (str == qstr("clearstickers")) {
auto box = std_::make_unique<ConfirmBox>(qsl("Clear frequently used stickers list?"));
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onClearStickers()));
Ui::showLayer(box.release());
break;
} else if ( } else if (
qsl("debugmode").startsWith(str) || qsl("debugmode").startsWith(str) ||
qsl("testmode").startsWith(str) || qsl("testmode").startsWith(str) ||
qsl("loadlang").startsWith(str) || qsl("loadlang").startsWith(str) ||
qsl("clearstickers").startsWith(str) ||
qsl("moderate").startsWith(str) || qsl("moderate").startsWith(str) ||
qsl("debugfiles").startsWith(str) || qsl("debugfiles").startsWith(str) ||
qsl("workmode").startsWith(str) || qsl("workmode").startsWith(str) ||
@ -1267,24 +1261,6 @@ void SettingsInner::onShowSessions() {
Ui::showLayer(box); Ui::showLayer(box);
} }
void SettingsInner::onClearStickers() {
auto &recent(cGetRecentStickers());
if (!recent.isEmpty()) {
recent.clear();
Local::writeUserSettings();
}
auto &sets(Global::RefStickerSets());
auto it = sets.find(Stickers::CustomSetId);
if (it != sets.cend()) {
sets.erase(it);
Local::writeStickers();
}
if (auto m = App::main()) {
emit m->stickersUpdated();
}
Ui::hideLayer();
}
void SettingsInner::onSwitchModerateMode() { void SettingsInner::onSwitchModerateMode() {
Global::SetModerateModeEnabled(!Global::ModerateModeEnabled()); Global::SetModerateModeEnabled(!Global::ModerateModeEnabled());
Local::writeUserSettings(); Local::writeUserSettings();

View file

@ -187,7 +187,6 @@ public slots:
void onUpdateLocalStorage(); void onUpdateLocalStorage();
private slots: private slots:
void onClearStickers();
void onSwitchModerateMode(); void onSwitchModerateMode();
void onAskQuestion(); void onAskQuestion();

View file

@ -889,13 +889,13 @@ bool StickerData::setInstalled() const {
switch (set.type()) { switch (set.type()) {
case mtpc_inputStickerSetID: { case mtpc_inputStickerSetID: {
auto it = Global::StickerSets().constFind(set.c_inputStickerSetID().vid.v); auto it = Global::StickerSets().constFind(set.c_inputStickerSetID().vid.v);
return (it != Global::StickerSets().cend()) && !(it->flags & MTPDstickerSet::Flag::f_disabled); return (it != Global::StickerSets().cend()) && !(it->flags & MTPDstickerSet::Flag::f_archived) && (it->flags & MTPDstickerSet::Flag::f_installed);
} break; } break;
case mtpc_inputStickerSetShortName: { case mtpc_inputStickerSetShortName: {
QString name = qs(set.c_inputStickerSetShortName().vshort_name).toLower(); QString name = qs(set.c_inputStickerSetShortName().vshort_name).toLower();
for (auto it = Global::StickerSets().cbegin(), e = Global::StickerSets().cend(); it != e; ++it) { for (auto it = Global::StickerSets().cbegin(), e = Global::StickerSets().cend(); it != e; ++it) {
if (it->shortName.toLower() == name) { if (it->shortName.toLower() == name) {
return !(it->flags & MTPDstickerSet::Flag::f_disabled); return !(it->flags & MTPDstickerSet::Flag::f_archived) && (it->flags & MTPDstickerSet::Flag::f_installed);
} }
} }
} break; } break;
@ -1095,10 +1095,11 @@ VoiceData::~VoiceData() {
DocumentAdditionalData::~DocumentAdditionalData() { DocumentAdditionalData::~DocumentAdditionalData() {
} }
DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, const QString &url, const QVector<MTPDocumentAttribute> &attributes) DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QString &url, const QVector<MTPDocumentAttribute> &attributes)
: id(id) : id(id)
, _dc(dc) , _dc(dc)
, _access(accessHash) , _access(accessHash)
, _version(version)
, _url(url) { , _url(url) {
setattributes(attributes); setattributes(attributes);
if (_dc && _access) { if (_dc && _access) {
@ -1107,15 +1108,15 @@ DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, const QSt
} }
DocumentData *DocumentData::create(DocumentId id) { DocumentData *DocumentData::create(DocumentId id) {
return new DocumentData(id, 0, 0, QString(), QVector<MTPDocumentAttribute>()); return new DocumentData(id, 0, 0, 0, QString(), QVector<MTPDocumentAttribute>());
} }
DocumentData *DocumentData::create(DocumentId id, int32 dc, uint64 accessHash, const QVector<MTPDocumentAttribute> &attributes) { DocumentData *DocumentData::create(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QVector<MTPDocumentAttribute> &attributes) {
return new DocumentData(id, dc, accessHash, QString(), attributes); return new DocumentData(id, dc, accessHash, version, QString(), attributes);
} }
DocumentData *DocumentData::create(DocumentId id, const QString &url, const QVector<MTPDocumentAttribute> &attributes) { DocumentData *DocumentData::create(DocumentId id, const QString &url, const QVector<MTPDocumentAttribute> &attributes) {
return new DocumentData(id, 0, 0, url, attributes); return new DocumentData(id, 0, 0, 0, url, attributes);
} }
void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) { void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) {
@ -1396,7 +1397,7 @@ void DocumentData::save(const QString &toFile, ActionOnLoad action, const FullMs
if (!_access && !_url.isEmpty()) { if (!_access && !_url.isEmpty()) {
_loader = new webFileLoader(_url, toFile, fromCloud, autoLoading); _loader = new webFileLoader(_url, toFile, fromCloud, autoLoading);
} else { } else {
_loader = new mtpFileLoader(_dc, id, _access, locationType(), toFile, size, (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), fromCloud, autoLoading); _loader = new mtpFileLoader(_dc, id, _access, _version, locationType(), toFile, size, (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), fromCloud, autoLoading);
} }
_loader->connect(_loader, SIGNAL(progress(FileLoader*)), App::main(), SLOT(documentLoadProgress(FileLoader*))); _loader->connect(_loader, SIGNAL(progress(FileLoader*)), App::main(), SLOT(documentLoadProgress(FileLoader*)));
_loader->connect(_loader, SIGNAL(failed(FileLoader*,bool)), App::main(), SLOT(documentLoadFailed(FileLoader*,bool))); _loader->connect(_loader, SIGNAL(failed(FileLoader*,bool)), App::main(), SLOT(documentLoadFailed(FileLoader*,bool)));
@ -1537,6 +1538,22 @@ void DocumentData::recountIsImage() {
_duration = fileIsImage(name, mime) ? 1 : -1; // hack _duration = fileIsImage(name, mime) ? 1 : -1; // hack
} }
bool DocumentData::setRemoteVersion(int32 version) {
if (_version == version) {
return false;
}
_version = version;
_location = FileLocation();
_data = QByteArray();
status = FileReady;
if (loading()) {
_loader->deleteLater();
_loader->stop();
_loader = nullptr;
}
return true;
}
void DocumentData::setRemoteLocation(int32 dc, uint64 access) { void DocumentData::setRemoteLocation(int32 dc, uint64 access) {
_dc = dc; _dc = dc;
_access = access; _access = access;

View file

@ -1068,7 +1068,7 @@ class Document;
class DocumentData { class DocumentData {
public: public:
static DocumentData *create(DocumentId id); static DocumentData *create(DocumentId id);
static DocumentData *create(DocumentId id, int32 dc, uint64 accessHash, const QVector<MTPDocumentAttribute> &attributes); static DocumentData *create(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QVector<MTPDocumentAttribute> &attributes);
static DocumentData *create(DocumentId id, const QString &url, const QVector<MTPDocumentAttribute> &attributes); static DocumentData *create(DocumentId id, const QString &url, const QVector<MTPDocumentAttribute> &attributes);
void setattributes(const QVector<MTPDocumentAttribute> &attributes); void setattributes(const QVector<MTPDocumentAttribute> &attributes);
@ -1159,6 +1159,7 @@ public:
_data = data; _data = data;
} }
bool setRemoteVersion(int32 version); // Returns true if version has changed.
void setRemoteLocation(int32 dc, uint64 access); void setRemoteLocation(int32 dc, uint64 access);
void setContentUrl(const QString &url); void setContentUrl(const QString &url);
bool hasRemoteLocation() const { bool hasRemoteLocation() const {
@ -1196,11 +1197,11 @@ public:
int32 md5[8]; int32 md5[8];
MediaKey mediaKey() const { MediaKey mediaKey() const {
return ::mediaKey(locationType(), _dc, id); return ::mediaKey(locationType(), _dc, id, _version);
} }
private: private:
DocumentData(DocumentId id, int32 dc, uint64 accessHash, const QString &url, const QVector<MTPDocumentAttribute> &attributes); DocumentData(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QString &url, const QVector<MTPDocumentAttribute> &attributes);
friend class Serialize::Document; friend class Serialize::Document;
@ -1208,9 +1209,10 @@ private:
return voice() ? AudioFileLocation : (isVideo() ? VideoFileLocation : DocumentFileLocation); return voice() ? AudioFileLocation : (isVideo() ? VideoFileLocation : DocumentFileLocation);
} }
// Two types of location: from MTProto by dc+access or from web by url // Two types of location: from MTProto by dc+access+version or from web by url
int32 _dc = 0; int32 _dc = 0;
uint64 _access = 0; uint64 _access = 0;
int32 _version = 0;
QString _url; QString _url;
FileLocation _location; FileLocation _location;

View file

@ -349,6 +349,7 @@ void BoxButton::setText(const QString &text) {
_fullText = text; _fullText = text;
_textWidth = _st.font->width(_text); _textWidth = _st.font->width(_text);
resizeToText(); resizeToText();
update();
} }
void BoxButton::resizeToText() { void BoxButton::resizeToText() {

View file

@ -487,8 +487,13 @@ typedef QPair<uint64, uint64> MediaKey;
inline uint64 mediaMix32To64(int32 a, int32 b) { inline uint64 mediaMix32To64(int32 a, int32 b) {
return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b)); return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b));
} }
inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id) { // Old method, should not be used anymore.
return MediaKey(mediaMix32To64(type, dc), id); //inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id) {
// return MediaKey(mediaMix32To64(type, dc), id);
//}
// New method when version was introduced, type is not relevant anymore (all files are Documents).
inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id, int32 version) {
return (version > 0) ? MediaKey(mediaMix32To64(version, dc), id) : MediaKey(mediaMix32To64(type, dc), id);
} }
inline StorageKey mediaKey(const MTPDfileLocation &location) { inline StorageKey mediaKey(const MTPDfileLocation &location) {
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v); return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);

View file

@ -291,7 +291,7 @@ inline bool chIsSpace(QChar ch, bool rich = false) {
return ch.isSpace() || (ch < 32 && !(rich && ch == TextCommand)) || (ch == QChar::ParagraphSeparator) || (ch == QChar::LineSeparator) || (ch == QChar::ObjectReplacementCharacter) || (ch == QChar::CarriageReturn) || (ch == QChar::Tabulation); return ch.isSpace() || (ch < 32 && !(rich && ch == TextCommand)) || (ch == QChar::ParagraphSeparator) || (ch == QChar::LineSeparator) || (ch == QChar::ObjectReplacementCharacter) || (ch == QChar::CarriageReturn) || (ch == QChar::Tabulation);
} }
inline bool chIsDiac(QChar ch) { // diac and variation selectors inline bool chIsDiac(QChar ch) { // diac and variation selectors
return (ch.category() == QChar::Mark_NonSpacing) || (ch.unicode() == 1652); return (ch.category() == QChar::Mark_NonSpacing) || (ch == 1652) || (ch >= 64606 && ch <= 64611);
} }
inline bool chIsBad(QChar ch) { inline bool chIsBad(QChar ch) {
return (ch == 0) || (ch >= 8232 && ch < 8237) || (ch >= 65024 && ch < 65040 && ch != 65039) || (ch >= 127 && ch < 160 && ch != 156) || (cPlatform() == dbipMac && ch >= 0x0B00 && ch <= 0x0B7F && chIsDiac(ch) && cIsElCapitan()); // tmp hack see https://bugreports.qt.io/browse/QTBUG-48910 return (ch == 0) || (ch >= 8232 && ch < 8237) || (ch >= 65024 && ch < 65040 && ch != 65039) || (ch >= 127 && ch < 160 && ch != 156) || (cPlatform() == dbipMac && ch >= 0x0B00 && ch <= 0x0B7F && chIsDiac(ch) && cIsElCapitan()); // tmp hack see https://bugreports.qt.io/browse/QTBUG-48910

View file

@ -228,7 +228,7 @@ void TopBarWidget::showAll() {
} }
} }
if (h && !o && _clearSelection->isHidden()) { if (h && !o && _clearSelection->isHidden()) {
if (Adaptive::OneColumn()) { if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) {
_info->setPeer(h); _info->setPeer(h);
_info->show(); _info->show();
} else { } else {

View file

@ -1240,6 +1240,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="GeneratedFiles\styles\style_basic.cpp" /> <ClCompile Include="GeneratedFiles\styles\style_basic.cpp" />
<ClCompile Include="GeneratedFiles\styles\style_basic_types.cpp" /> <ClCompile Include="GeneratedFiles\styles\style_basic_types.cpp" />
<ClCompile Include="GeneratedFiles\styles\style_boxes.cpp" />
<ClCompile Include="GeneratedFiles\styles\style_dialogs.cpp" /> <ClCompile Include="GeneratedFiles\styles\style_dialogs.cpp" />
<ClCompile Include="GeneratedFiles\styles\style_history.cpp" /> <ClCompile Include="GeneratedFiles\styles\style_history.cpp" />
<ClCompile Include="GeneratedFiles\styles\style_mediaview.cpp" /> <ClCompile Include="GeneratedFiles\styles\style_mediaview.cpp" />
@ -1528,6 +1529,7 @@
<ClInclude Include="GeneratedFiles\numbers.h" /> <ClInclude Include="GeneratedFiles\numbers.h" />
<ClInclude Include="GeneratedFiles\styles\style_basic.h" /> <ClInclude Include="GeneratedFiles\styles\style_basic.h" />
<ClInclude Include="GeneratedFiles\styles\style_basic_types.h" /> <ClInclude Include="GeneratedFiles\styles\style_basic_types.h" />
<ClInclude Include="GeneratedFiles\styles\style_boxes.h" />
<ClInclude Include="GeneratedFiles\styles\style_dialogs.h" /> <ClInclude Include="GeneratedFiles\styles\style_dialogs.h" />
<ClInclude Include="GeneratedFiles\styles\style_history.h" /> <ClInclude Include="GeneratedFiles\styles\style_history.h" />
<ClInclude Include="GeneratedFiles\styles\style_mediaview.h" /> <ClInclude Include="GeneratedFiles\styles\style_mediaview.h" />
@ -3030,6 +3032,7 @@
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling style %(Identity)...</Message> <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling style %(Identity)...</Message>
</CustomBuild> </CustomBuild>
<CodegenStyleItem Include="Resources\basic_types.style" /> <CodegenStyleItem Include="Resources\basic_types.style" />
<CodegenStyleItem Include="SourceFiles\boxes\boxes.style" />
<CodegenStyleItem Include="SourceFiles\dialogs\dialogs.style" /> <CodegenStyleItem Include="SourceFiles\dialogs\dialogs.style" />
<CodegenStyleItem Include="SourceFiles\history\history.style" /> <CodegenStyleItem Include="SourceFiles\history\history.style" />
<CodegenStyleItem Include="SourceFiles\overview\overview.style" /> <CodegenStyleItem Include="SourceFiles\overview\overview.style" />

View file

@ -1446,6 +1446,9 @@
<ClCompile Include="GeneratedFiles\Release\moc_media_clip_volume_controller.cpp"> <ClCompile Include="GeneratedFiles\Release\moc_media_clip_volume_controller.cpp">
<Filter>GeneratedFiles\Release</Filter> <Filter>GeneratedFiles\Release</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="GeneratedFiles\styles\style_boxes.cpp">
<Filter>GeneratedFiles\styles</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="SourceFiles\stdafx.h"> <ClInclude Include="SourceFiles\stdafx.h">
@ -1727,6 +1730,9 @@
<ClInclude Include="SourceFiles\ui\buttons\icon_button.h"> <ClInclude Include="SourceFiles\ui\buttons\icon_button.h">
<Filter>SourceFiles\ui\buttons</Filter> <Filter>SourceFiles\ui\buttons</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="GeneratedFiles\styles\style_boxes.h">
<Filter>GeneratedFiles\styles</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CustomBuild Include="SourceFiles\application.h"> <CustomBuild Include="SourceFiles\application.h">
@ -2122,10 +2128,13 @@
<CodegenStyleItem Include="SourceFiles\media\view\mediaview.style"> <CodegenStyleItem Include="SourceFiles\media\view\mediaview.style">
<Filter>SourceFiles\media\view</Filter> <Filter>SourceFiles\media\view</Filter>
</CodegenStyleItem> </CodegenStyleItem>
<CodegenStyleItem Include="SourceFiles\boxes\boxes.style">
<Filter>SourceFiles\boxes</Filter>
</CodegenStyleItem>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="Resources\winrc\Telegram.rc"> <ResourceCompile Include="Resources\winrc\Telegram.rc">
<Filter>Resources\winrc</Filter> <Filter>Resources\winrc</Filter>
</ResourceCompile> </ResourceCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -2531,7 +2531,7 @@
SDKROOT = macosx; SDKROOT = macosx;
SYMROOT = ./../Mac; SYMROOT = ./../Mac;
TDESKTOP_MAJOR_VERSION = 0.9; TDESKTOP_MAJOR_VERSION = 0.9;
TDESKTOP_VERSION = 0.9.60; TDESKTOP_VERSION = 0.9.61;
}; };
name = Release; name = Release;
}; };
@ -2672,7 +2672,7 @@
SDKROOT = macosx; SDKROOT = macosx;
SYMROOT = ./../Mac; SYMROOT = ./../Mac;
TDESKTOP_MAJOR_VERSION = 0.9; TDESKTOP_MAJOR_VERSION = 0.9;
TDESKTOP_VERSION = 0.9.60; TDESKTOP_VERSION = 0.9.61;
}; };
name = Debug; name = Debug;
}; };

View file

@ -1,6 +1,6 @@
AppVersion 9060 AppVersion 9061
AppVersionStrMajor 0.9 AppVersionStrMajor 0.9
AppVersionStrSmall 0.9.60 AppVersionStrSmall 0.9.61
AppVersionStr 0.9.60 AppVersionStr 0.9.61
AlphaChannel 1 AlphaChannel 0
BetaVersion 0 BetaVersion 0