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
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 176 KiB |
Before Width: | Height: | Size: 239 KiB After Width: | Height: | Size: 238 KiB |
|
@ -1868,6 +1868,9 @@ stickersSettings: sprite(140px, 124px, 21px, 22px);
|
|||
savedGifsOver: sprite(329px, 286px, 21px, 22px);
|
||||
savedGifsActive: sprite(350px, 286px, 21px, 22px);
|
||||
|
||||
stickersSettingsUnreadSize: 17px;
|
||||
stickersSettingsUnreadPosition: point(4px, 5px);
|
||||
|
||||
emojiPanCategories: #f7f7f7;
|
||||
|
||||
rbEmoji: flatCheckbox {
|
||||
|
@ -2141,7 +2144,9 @@ mvCaptionRadius: 2px;
|
|||
mvCaptionBg: #11111180;
|
||||
mvCaptionFont: font(fsize);
|
||||
|
||||
medviewSaveMsgCheck: sprite(311px, 309px, 22px, 18px);
|
||||
medviewSaveMsgCheck: icon {
|
||||
{ "mediaview_save_check", #ffffff }
|
||||
};
|
||||
medviewSaveMsgFont: font(16px);
|
||||
medviewSaveMsgPadding: margins(55px, 19px, 29px, 20px);
|
||||
medviewSaveMsgCheckPos: point(23px, 21px);
|
||||
|
|
After Width: | Height: | Size: 454 B |
After Width: | Height: | Size: 882 B |
After Width: | Height: | Size: 173 B |
After Width: | Height: | Size: 120 B |
|
@ -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_join" = "Join";
|
||||
|
||||
"lng_group_invite_members" = "{count:_not_used_|# member|# members}, among them:";
|
||||
|
||||
"lng_group_invite_link" = "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.";
|
||||
|
@ -680,15 +682,20 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
"lng_stickers_add_pack" = "Add stickers";
|
||||
"lng_stickers_share_pack" = "Share Stickers";
|
||||
"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_default_set" = "Great Minds";
|
||||
"lng_stickers_you_have" = "Manage and reorder sticker packs";
|
||||
"lng_stickers_packs" = "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_return" = "Undo";
|
||||
"lng_stickers_restore" = "Restore";
|
||||
"lng_stickers_add" = "Add";
|
||||
"lng_stickers_count" = "{count:Loading...|# sticker|# stickers}";
|
||||
|
||||
"lng_in_dlg_photo" = "Photo";
|
||||
|
|
|
@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,9,60,0
|
||||
PRODUCTVERSION 0,9,60,0
|
||||
FILEVERSION 0,9,61,0
|
||||
PRODUCTVERSION 0,9,61,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -51,10 +51,10 @@ BEGIN
|
|||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileVersion", "0.9.60.0"
|
||||
VALUE "FileVersion", "0.9.61.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "0.9.60.0"
|
||||
VALUE "ProductVersion", "0.9.61.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,9,60,0
|
||||
PRODUCTVERSION 0,9,60,0
|
||||
FILEVERSION 0,9,61,0
|
||||
PRODUCTVERSION 0,9,61,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -43,10 +43,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileDescription", "Telegram Updater"
|
||||
VALUE "FileVersion", "0.9.60.0"
|
||||
VALUE "FileVersion", "0.9.61.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "0.9.60.0"
|
||||
VALUE "ProductVersion", "0.9.61.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -923,12 +923,12 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
|
|||
_stickerSetRequests.remove(setId);
|
||||
|
||||
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;
|
||||
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);
|
||||
if (it == sets.cend()) return;
|
||||
|
||||
|
@ -936,7 +936,9 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
|
|||
it->hash = s.vhash.v;
|
||||
it->shortName = qs(s.vshort_name);
|
||||
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);
|
||||
auto custom = sets.find(Stickers::CustomSetId);
|
||||
|
@ -1002,7 +1004,14 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
|
|||
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();
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "data/data_abstract_structure.h"
|
||||
#include "history/history_service_layout.h"
|
||||
#include "media/media_audio.h"
|
||||
#include "inline_bots/inline_bot_layout_item.h"
|
||||
#include "application.h"
|
||||
#include "fileuploader.h"
|
||||
#include "mainwidget.h"
|
||||
|
@ -382,397 +383,413 @@ namespace {
|
|||
return (online > now);
|
||||
}
|
||||
|
||||
UserData *feedUsers(const MTPVector<MTPUser> &users) {
|
||||
UserData *result = nullptr;
|
||||
for_const (auto &user, users.c_vector().v) {
|
||||
UserData *data = nullptr;
|
||||
bool wasContact = false, minimal = false;
|
||||
const MTPUserStatus *status = 0, emptyStatus = MTP_userStatusEmpty();
|
||||
UserData *feedUser(const MTPUser &user) {
|
||||
UserData *data = nullptr;
|
||||
bool wasContact = false, minimal = false;
|
||||
const MTPUserStatus *status = 0, emptyStatus = MTP_userStatusEmpty();
|
||||
|
||||
Notify::PeerUpdate update;
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
Notify::PeerUpdate update;
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
|
||||
switch (user.type()) {
|
||||
case mtpc_userEmpty: {
|
||||
const auto &d(user.c_userEmpty());
|
||||
switch (user.type()) {
|
||||
case mtpc_userEmpty: {
|
||||
auto &d(user.c_userEmpty());
|
||||
|
||||
PeerId peer(peerFromUser(d.vid.v));
|
||||
data = App::user(peer);
|
||||
auto canShareThisContact = data->canShareThisContactFast();
|
||||
wasContact = data->isContact();
|
||||
PeerId peer(peerFromUser(d.vid.v));
|
||||
data = App::user(peer);
|
||||
auto canShareThisContact = data->canShareThisContactFast();
|
||||
wasContact = data->isContact();
|
||||
|
||||
data->input = MTP_inputPeerUser(d.vid, MTP_long(0));
|
||||
data->inputUser = MTP_inputUser(d.vid, MTP_long(0));
|
||||
data->input = MTP_inputPeerUser(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->setPhoto(MTP_userProfilePhotoEmpty());
|
||||
data->access = UserNoAccess;
|
||||
data->flags = 0;
|
||||
data->setBotInfoVersion(-1);
|
||||
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;
|
||||
if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact;
|
||||
} break;
|
||||
case mtpc_user: {
|
||||
const auto &d(user.c_user());
|
||||
minimal = d.is_min();
|
||||
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());
|
||||
|
||||
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());
|
||||
}
|
||||
bool phoneChanged = (data->phone() != phone);
|
||||
if (phoneChanged) {
|
||||
data->setPhone(phone);
|
||||
update.flags |= UpdateFlag::UserPhoneChanged;
|
||||
}
|
||||
if (d.is_deleted()) {
|
||||
if (!data->phone().isEmpty()) {
|
||||
data->setPhone(QString());
|
||||
update.flags |= UpdateFlag::UserPhoneChanged;
|
||||
}
|
||||
data->setName(lang(lng_deleted), QString(), QString(), QString());
|
||||
data->setPhoto(MTP_userProfilePhotoEmpty());
|
||||
data->access = UserNoAccess;
|
||||
status = &emptyStatus;
|
||||
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 {
|
||||
// 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;
|
||||
|
||||
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;
|
||||
data->setPhoto(MTP_userProfilePhotoEmpty());
|
||||
}
|
||||
if (!minimal) {
|
||||
if (d.has_bot_info_version()) {
|
||||
data->setBotInfoVersion(d.vbot_info_version.v);
|
||||
data->botInfo->readsAllHistory = d.is_bot_chat_history();
|
||||
if (data->botInfo->cantJoinGroups != d.is_bot_nochats()) {
|
||||
data->botInfo->cantJoinGroups = d.is_bot_nochats();
|
||||
update.flags |= UpdateFlag::BotCanAddToGroups;
|
||||
}
|
||||
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 (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();
|
||||
if (d.has_access_hash()) data->access = d.vaccess_hash.v;
|
||||
status = d.has_status() ? &d.vstatus : &emptyStatus;
|
||||
}
|
||||
if (!minimal) {
|
||||
if (d.has_bot_info_version()) {
|
||||
data->setBotInfoVersion(d.vbot_info_version.v);
|
||||
data->botInfo->readsAllHistory = d.is_bot_chat_history();
|
||||
if (data->botInfo->cantJoinGroups != d.is_bot_nochats()) {
|
||||
data->botInfo->cantJoinGroups = d.is_bot_nochats();
|
||||
update.flags |= UpdateFlag::BotCanAddToGroups;
|
||||
}
|
||||
data->botInfo->inlinePlaceholder = d.has_bot_inline_placeholder() ? '_' + qs(d.vbot_inline_placeholder) : QString();
|
||||
} else {
|
||||
data->setBotInfoVersion(-1);
|
||||
}
|
||||
|
||||
if (canShareThisContact != data->canShareThisContactFast()) update.flags |= UpdateFlag::UserCanShareContact;
|
||||
if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact;
|
||||
} break;
|
||||
}
|
||||
|
||||
if (!data) continue;
|
||||
|
||||
if (minimal) {
|
||||
if (data->loadedStatus == PeerData::NotLoaded) {
|
||||
data->loadedStatus = PeerData::MinimalLoaded;
|
||||
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();
|
||||
}
|
||||
} 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);
|
||||
if (d.is_self() && ::self != data) {
|
||||
::self = data;
|
||||
if (App::wnd()) App::wnd()->updateGlobalMenu();
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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 *result = nullptr;
|
||||
for_const (auto &chat, chats.c_vector().v) {
|
||||
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) {
|
||||
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 (auto feededChat = feedChat(chat)) {
|
||||
result = feededChat;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -1452,7 +1469,7 @@ namespace {
|
|||
switch (document.type()) {
|
||||
case mtpc_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;
|
||||
case mtpc_documentEmpty: return App::document(document.c_documentEmpty().vid.v);
|
||||
}
|
||||
|
@ -1465,14 +1482,14 @@ namespace {
|
|||
return feedDocument(document.c_document(), convert);
|
||||
} break;
|
||||
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;
|
||||
}
|
||||
return App::document(0);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -1629,11 +1646,13 @@ namespace {
|
|||
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;
|
||||
if (convert) {
|
||||
MediaKey oldKey = convert->mediaKey();
|
||||
if (convert->id != document) {
|
||||
bool idChanged = (convert->id != document);
|
||||
if (idChanged) {
|
||||
DocumentsData::iterator i = ::documentsData.find(convert->id);
|
||||
if (i != ::documentsData.cend() && i.value() == convert) {
|
||||
::documentsData.erase(i);
|
||||
|
@ -1645,10 +1664,11 @@ namespace {
|
|||
}
|
||||
if (date) {
|
||||
convert->setattributes(attributes);
|
||||
versionChanged = convert->setRemoteVersion(version);
|
||||
convert->setRemoteLocation(dc, access);
|
||||
convert->date = date;
|
||||
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);
|
||||
}
|
||||
convert->size = size;
|
||||
|
@ -1658,7 +1678,7 @@ namespace {
|
|||
}
|
||||
|
||||
MediaKey newKey = convert->mediaKey();
|
||||
if (newKey != oldKey) {
|
||||
if (idChanged) {
|
||||
if (convert->voice()) {
|
||||
Local::copyAudio(oldKey, newKey);
|
||||
} else if (convert->sticker() || convert->isAnimation()) {
|
||||
|
@ -1677,7 +1697,7 @@ namespace {
|
|||
if (convert) {
|
||||
result = convert;
|
||||
} else {
|
||||
result = DocumentData::create(document, dc, access, attributes);
|
||||
result = DocumentData::create(document, dc, access, version, attributes);
|
||||
result->date = date;
|
||||
result->mime = mime;
|
||||
result->thumb = thumb;
|
||||
|
@ -1692,12 +1712,13 @@ namespace {
|
|||
result = i.value();
|
||||
if (result != convert && date) {
|
||||
result->setattributes(attributes);
|
||||
versionChanged = result->setRemoteVersion(version);
|
||||
if (!result->isValid()) {
|
||||
result->setRemoteLocation(dc, access);
|
||||
}
|
||||
result->date = date;
|
||||
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->size = size;
|
||||
|
@ -1710,6 +1731,30 @@ namespace {
|
|||
if (sentSticker && App::main()) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1977,6 +2022,11 @@ namespace {
|
|||
Global::SetStickerSets(Stickers::Sets());
|
||||
Global::SetStickerSetsOrder(Stickers::Order());
|
||||
Global::SetLastStickersUpdate(0);
|
||||
Global::SetLastRecentStickersUpdate(0);
|
||||
Global::SetFeaturedStickerSetsOrder(Stickers::Order());
|
||||
Global::SetFeaturedStickerSetsUnreadCount(0);
|
||||
Global::SetLastFeaturedStickersUpdate(0);
|
||||
Global::SetArchivedStickerSetsOrder(Stickers::Order());
|
||||
cSetSavedGifs(SavedGifs());
|
||||
cSetLastSavedGifsUpdate(0);
|
||||
cSetReportSpamStatuses(ReportSpamStatuses());
|
||||
|
|
|
@ -65,7 +65,9 @@ namespace App {
|
|||
bool onlineColorUse(UserData *user, TimeId now);
|
||||
bool onlineColorUse(TimeId online, TimeId now);
|
||||
|
||||
UserData *feedUser(const MTPUser &user);
|
||||
UserData *feedUsers(const MTPVector<MTPUser> &users); // returns last user
|
||||
PeerData *feedChat(const MTPChat &chat);
|
||||
PeerData *feedChats(const MTPVector<MTPChat> &chats); // returns last chat
|
||||
|
||||
void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos, bool emitPeerUpdated = true);
|
||||
|
@ -149,7 +151,7 @@ namespace App {
|
|||
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);
|
||||
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 *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);
|
||||
|
|
|
@ -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 }
|
||||
};
|
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "apiwrap.h"
|
||||
#include "application.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
TextParseOptions _confirmBoxTextOptions = {
|
||||
TextParseLinks | TextParseMultiline | TextParseRichText, // flags
|
||||
|
@ -520,3 +521,86 @@ void KickMemberBox::onConfirm() {
|
|||
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();
|
||||
}
|
||||
|
|
|
@ -266,3 +266,26 @@ private:
|
|||
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;
|
||||
|
||||
};
|
||||
|
|
|
@ -22,6 +22,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "abstractbox.h"
|
||||
|
||||
class ConfirmBox;
|
||||
|
||||
class StickerSetInner : public TWidget, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -62,24 +64,26 @@ private:
|
|||
void gotSet(const MTPmessages_StickerSet &set);
|
||||
bool failedSet(const RPCError &error);
|
||||
|
||||
void installDone(const MTPBool &result);
|
||||
bool installFailed(const RPCError &error);
|
||||
void installDone(const MTPmessages_StickerSetInstallResult &result);
|
||||
bool installFail(const RPCError &error);
|
||||
|
||||
StickerPack _pack;
|
||||
StickersByEmojiMap _emoji;
|
||||
bool _loaded;
|
||||
uint64 _setId, _setAccess;
|
||||
bool _loaded = false;
|
||||
uint64 _setId = 0;
|
||||
uint64 _setAccess = 0;
|
||||
QString _title, _setTitle, _setShortName;
|
||||
int32 _setCount, _setHash;
|
||||
MTPDstickerSet::Flags _setFlags;
|
||||
int32 _setCount = 0;
|
||||
int32 _setHash = 0;
|
||||
MTPDstickerSet::Flags _setFlags = 0;
|
||||
|
||||
int32 _bottom;
|
||||
int32 _bottom = 0;
|
||||
MTPInputStickerSet _input;
|
||||
|
||||
mtpRequestId _installRequest;
|
||||
mtpRequestId _installRequest = 0;
|
||||
|
||||
QTimer _previewTimer;
|
||||
int32 _previewShown;
|
||||
int32 _previewShown = -1;
|
||||
};
|
||||
|
||||
class StickerSetBox : public ScrollableBox, public RPCSender {
|
||||
|
@ -93,7 +97,6 @@ public:
|
|||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
public slots:
|
||||
|
||||
void onStickersUpdated();
|
||||
void onAddStickers();
|
||||
void onShareStickers();
|
||||
|
@ -101,122 +104,49 @@ public slots:
|
|||
|
||||
void onScroll();
|
||||
|
||||
signals:
|
||||
private slots:
|
||||
void onInstalled(uint64 id);
|
||||
|
||||
signals:
|
||||
void installed(uint64 id);
|
||||
|
||||
protected:
|
||||
|
||||
void hideAll();
|
||||
void showAll();
|
||||
|
||||
private:
|
||||
|
||||
StickerSetInner _inner;
|
||||
ScrollableBoxShadow _shadow;
|
||||
BoxButton _add, _share, _cancel, _done;
|
||||
QString _title;
|
||||
|
||||
};
|
||||
|
||||
class StickersInner : public TWidget {
|
||||
Q_OBJECT
|
||||
|
||||
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;
|
||||
};
|
||||
namespace internal {
|
||||
class StickersInner;
|
||||
} // namespace internal
|
||||
|
||||
class StickersBox : public ItemListBox, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class Section {
|
||||
Installed,
|
||||
Featured,
|
||||
Archived,
|
||||
ArchivedPart,
|
||||
};
|
||||
StickersBox(Section section = Section::Installed);
|
||||
StickersBox(const Stickers::Order &archivedIds);
|
||||
|
||||
StickersBox();
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
|
||||
void closePressed();
|
||||
|
||||
public slots:
|
||||
~StickersBox();
|
||||
|
||||
public slots:
|
||||
void onStickersUpdated();
|
||||
|
||||
void onCheckDraggingScroll(int localY);
|
||||
|
@ -225,35 +155,184 @@ public slots:
|
|||
|
||||
void onSave();
|
||||
|
||||
protected:
|
||||
private slots:
|
||||
void onScroll();
|
||||
|
||||
protected:
|
||||
void hideAll();
|
||||
void showAll();
|
||||
|
||||
private:
|
||||
|
||||
void setup();
|
||||
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);
|
||||
void reorderDone(const MTPBool &result);
|
||||
bool reorderFail(const RPCError &result);
|
||||
void saveOrder();
|
||||
|
||||
StickersInner _inner;
|
||||
BoxButton _save, _cancel;
|
||||
void checkLoadMoreArchived();
|
||||
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;
|
||||
mtpRequestId _reorderRequest;
|
||||
PlainShadow _topShadow;
|
||||
ScrollableBoxShadow _bottomShadow;
|
||||
mtpRequestId _reorderRequest = 0;
|
||||
ChildWidget<PlainShadow> _topShadow = { nullptr };
|
||||
ChildWidget<ScrollableBoxShadow> _bottomShadow = { nullptr };
|
||||
|
||||
QTimer _scrollTimer;
|
||||
int32 _scrollDelta;
|
||||
int32 _scrollDelta = 0;
|
||||
|
||||
int32 _aboutWidth;
|
||||
int _aboutWidth = 0;
|
||||
Text _about;
|
||||
int32 _aboutHeight;
|
||||
int _aboutHeight = 0;
|
||||
|
||||
mtpRequestId _archivedRequestId = 0;
|
||||
bool _allArchivedLoaded = 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
|
||||
|
|
|
@ -141,7 +141,10 @@ private:
|
|||
void reallocate(int newCapacity) {
|
||||
auto newPlainData = operator new[](newCapacity * sizeof(T));
|
||||
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);
|
||||
_capacity = newCapacity;
|
||||
|
|
|
@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
#define BETA_VERSION_MACRO (0ULL)
|
||||
|
||||
constexpr int AppVersion = 9060;
|
||||
constexpr str_const AppVersionStr = "0.9.60";
|
||||
constexpr bool AppAlphaVersion = true;
|
||||
constexpr int AppVersion = 9061;
|
||||
constexpr str_const AppVersionStr = "0.9.61";
|
||||
constexpr bool AppAlphaVersion = false;
|
||||
constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;
|
||||
|
|
|
@ -29,7 +29,6 @@ dialogsUnreadBgActive: #ffffff;
|
|||
dialogsUnreadBgMutedActive: #d3e2ee;
|
||||
dialogsUnreadFont: font(12px bold);
|
||||
dialogsUnreadHeight: 19px;
|
||||
dialogsUnreadTop: 1px;
|
||||
dialogsUnreadPadding: 5px;
|
||||
|
||||
dialogsBg: windowBg;
|
||||
|
@ -86,8 +85,8 @@ dialogsTextStyleActive: textStyle(dialogsTextStyle) {
|
|||
linkFgDown: dialogsTextFgActive;
|
||||
}
|
||||
dialogsTextStyleDraftActive: textStyle(dialogsTextStyle) {
|
||||
linkFg: #ffd6d6;
|
||||
linkFgDown: #ffd6d6;
|
||||
linkFg: #c6e1f7;
|
||||
linkFgDown: #c6e1f7;
|
||||
}
|
||||
|
||||
dialogsNewChatIcon: icon {
|
||||
|
|
|
@ -222,7 +222,7 @@ void paintUnreadCount(Painter &p, const QString &text, int x, int y, const Unrea
|
|||
|
||||
p.setFont(st.font);
|
||||
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) {
|
||||
|
@ -258,7 +258,7 @@ void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool sele
|
|||
auto counter = QString::number(unreadCount);
|
||||
auto mutedCounter = history->mute();
|
||||
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;
|
||||
|
||||
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;
|
||||
bool mutedHidden = (current == Dialogs::Mode::Important);
|
||||
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);
|
||||
|
||||
if (mutedHidden) {
|
||||
|
|
|
@ -38,6 +38,8 @@ void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool o
|
|||
enum UnreadBadgeSize {
|
||||
UnreadBadgeInDialogs = 0,
|
||||
UnreadBadgeInHistoryToDown,
|
||||
UnreadBadgeInStickersPanel,
|
||||
UnreadBadgeInStickersBox,
|
||||
|
||||
UnreadBadgeSizesCount
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "boxes/stickersetbox.h"
|
||||
#include "inline_bots/inline_bot_result.h"
|
||||
#include "inline_bots/inline_bot_layout_item.h"
|
||||
#include "dialogs/dialogs_layout.h"
|
||||
#include "historywidget.h"
|
||||
#include "localstorage.h"
|
||||
#include "lang.h"
|
||||
|
@ -713,7 +714,7 @@ void EmojiColorPicker::drawVariant(Painter &p, int variant) {
|
|||
}
|
||||
|
||||
EmojiPanInner::EmojiPanInner() : TWidget()
|
||||
, _maxHeight(int(st::emojiPanMaxHeight))
|
||||
, _maxHeight(int(st::emojiPanMaxHeight) - st::rbEmoji.height)
|
||||
, _a_selected(animation(this, &EmojiPanInner::step_selected))
|
||||
, _top(0)
|
||||
, _selected(-1)
|
||||
|
@ -1229,7 +1230,7 @@ StickerPanInner::StickerPanInner() : TWidget()
|
|||
, _pressedSel(-1)
|
||||
, _settings(this, lang(lng_stickers_you_have))
|
||||
, _previewShown(false) {
|
||||
setMaxHeight(st::emojiPanMaxHeight);
|
||||
setMaxHeight(st::emojiPanMaxHeight - st::rbEmoji.height);
|
||||
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
|
@ -1508,7 +1509,7 @@ void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
Stickers::Sets &sets(Global::RefStickerSets());
|
||||
auto &sets = Global::RefStickerSets();
|
||||
auto it = sets.find(Stickers::CustomSetId);
|
||||
if (it != sets.cend()) {
|
||||
for (int32 i = 0, l = it->stickers.size(); i < l; ++i) {
|
||||
|
@ -1517,7 +1518,7 @@ void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
|
|||
if (it->stickers.isEmpty()) {
|
||||
sets.erase(it);
|
||||
}
|
||||
Local::writeStickers();
|
||||
Local::writeInstalledStickers();
|
||||
refresh = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1628,8 +1629,8 @@ void StickerPanInner::hideFinish(bool completely) {
|
|||
void StickerPanInner::refreshStickers() {
|
||||
clearSelection(true);
|
||||
|
||||
const Stickers::Sets &sets(Global::StickerSets());
|
||||
_sets.clear(); _sets.reserve(sets.size() + 1);
|
||||
_sets.clear();
|
||||
_sets.reserve(Global::StickerSetsOrder().size() + 1);
|
||||
|
||||
refreshRecentStickers(false);
|
||||
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) {
|
||||
const Stickers::Sets &sets(Global::StickerSets());
|
||||
auto &sets = Global::StickerSets();
|
||||
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;
|
||||
pack.reserve(it->stickers.size());
|
||||
|
@ -2110,37 +2111,49 @@ void StickerPanInner::refreshRecent() {
|
|||
void StickerPanInner::refreshRecentStickers(bool performResize) {
|
||||
_custom.clear();
|
||||
clearSelection(true);
|
||||
auto customIt = Global::StickerSets().constFind(Stickers::CustomSetId);
|
||||
if (cGetRecentStickers().isEmpty() && (customIt == Global::StickerSets().cend() || customIt->stickers.isEmpty())) {
|
||||
auto &sets = Global::StickerSets();
|
||||
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) {
|
||||
_sets.pop_front();
|
||||
}
|
||||
} else {
|
||||
StickerPack recent;
|
||||
int32 customCnt = (customIt == Global::StickerSets().cend() ? 0 : customIt->stickers.size());
|
||||
QMap<DocumentData*, bool> recentOnly;
|
||||
recent.reserve(cGetRecentStickers().size() + customCnt);
|
||||
_custom.reserve(cGetRecentStickers().size() + customCnt);
|
||||
for (int32 i = 0, l = cGetRecentStickers().size(); i < l; ++i) {
|
||||
DocumentData *s = cGetRecentStickers().at(i).first;
|
||||
recent.push_back(s);
|
||||
recentOnly.insert(s, true);
|
||||
StickerPack recentPack;
|
||||
int customCnt = (customIt == sets.cend()) ? 0 : customIt->stickers.size();
|
||||
int cloudCnt = (cloudIt == sets.cend()) ? 0 : cloudIt->stickers.size();
|
||||
recentPack.reserve(cloudCnt + recent.size() + customCnt);
|
||||
_custom.reserve(cloudCnt + recent.size() + customCnt);
|
||||
if (cloudCnt > 0) {
|
||||
for_const (auto sticker, cloudIt->stickers) {
|
||||
recentPack.push_back(sticker);
|
||||
_custom.push_back(false);
|
||||
}
|
||||
}
|
||||
for_const (auto &recentSticker, recent) {
|
||||
auto sticker = recentSticker.first;
|
||||
recentPack.push_back(sticker);
|
||||
_custom.push_back(false);
|
||||
}
|
||||
for (int32 i = 0; i < customCnt; ++i) {
|
||||
DocumentData *s = customIt->stickers.at(i);
|
||||
if (recentOnly.contains(s)) {
|
||||
_custom[recent.indexOf(s)] = true;
|
||||
} else {
|
||||
recent.push_back(s);
|
||||
_custom.push_back(true);
|
||||
if (customCnt > 0) {
|
||||
for_const (auto &sticker, customIt->stickers) {
|
||||
auto index = recentPack.indexOf(sticker);
|
||||
if (index >= cloudCnt) {
|
||||
_custom[index] = true; // mark stickers from recent as custom
|
||||
} else {
|
||||
recentPack.push_back(sticker);
|
||||
_custom.push_back(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {
|
||||
_sets[0].pack = recent;
|
||||
_sets[0].hovers.resize(recent.size() * 2);
|
||||
_sets[0].pack = recentPack;
|
||||
_sets[0].hovers.resize(recentPack.size() * 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2829,6 +2842,20 @@ void EmojiPan::onSaveConfigDelayed(int32 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) {
|
||||
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);
|
||||
if (_stickersShown && s_inner.showSectionIcons()) {
|
||||
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()) {
|
||||
int32 x = _iconsLeft, i = 0, selxrel = _iconsLeft + _iconSelX.current(), selx = selxrel - _iconsX.current();
|
||||
|
@ -3093,6 +3120,7 @@ void EmojiPan::refreshStickers() {
|
|||
if (!_stickersShown) {
|
||||
s_inner.preloadImages();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void EmojiPan::refreshSavedGifs() {
|
||||
|
@ -3228,7 +3256,7 @@ void EmojiPan::step_icons(uint64 ms, bool timer) {
|
|||
}
|
||||
|
||||
if (_iconsStartAnim) {
|
||||
float64 dt = (ms - _iconsStartAnim) / st::stickerIconMove;
|
||||
float64 dt = (ms - _iconsStartAnim) / float64(st::stickerIconMove);
|
||||
if (dt >= 1) {
|
||||
_iconsStartAnim = 0;
|
||||
_iconsX.finish();
|
||||
|
@ -3584,7 +3612,7 @@ void EmojiPan::onSwitch() {
|
|||
} else {
|
||||
if (cShowingSavedGifs() && cSavedGifs().isEmpty()) {
|
||||
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);
|
||||
} else {
|
||||
s_inner.updateShowingSavedGifs();
|
||||
|
@ -3623,8 +3651,9 @@ void EmojiPan::onSwitch() {
|
|||
}
|
||||
|
||||
void EmojiPan::onRemoveSet(quint64 setId) {
|
||||
auto it = Global::StickerSets().constFind(setId);
|
||||
if (it != Global::StickerSets().cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) {
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) {
|
||||
_removingSetId = it->id;
|
||||
ConfirmBox *box = new ConfirmBox(lng_stickers_remove_pack(lt_sticker_pack, it->title), lang(lng_box_remove));
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onRemoveSetSure()));
|
||||
|
@ -3635,8 +3664,9 @@ void EmojiPan::onRemoveSet(quint64 setId) {
|
|||
|
||||
void EmojiPan::onRemoveSetSure() {
|
||||
Ui::hideLayer();
|
||||
auto it = Global::RefStickerSets().find(_removingSetId);
|
||||
if (it != Global::RefStickerSets().cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) {
|
||||
auto &sets = Global::RefStickerSets();
|
||||
auto it = sets.find(_removingSetId);
|
||||
if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) {
|
||||
if (it->id && it->access) {
|
||||
MTP::send(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access))));
|
||||
} else if (!it->shortName.isEmpty()) {
|
||||
|
@ -3652,11 +3682,14 @@ void EmojiPan::onRemoveSetSure() {
|
|||
++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);
|
||||
if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex);
|
||||
refreshStickers();
|
||||
Local::writeStickers();
|
||||
Local::writeInstalledStickers();
|
||||
if (writeRecent) Local::writeUserSettings();
|
||||
}
|
||||
_removingSetId = 0;
|
||||
|
|
|
@ -656,6 +656,7 @@ signals:
|
|||
void updateStickers();
|
||||
|
||||
private:
|
||||
void paintStickerSettingsIcon(Painter &p) const;
|
||||
|
||||
void validateSelectedIcon(bool animated = false);
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
Q_DECLARE_METATYPE(ClickHandlerPtr);
|
||||
Q_DECLARE_METATYPE(Qt::MouseButton);
|
||||
Q_DECLARE_METATYPE(Ui::ShowWay);
|
||||
|
||||
namespace App {
|
||||
|
||||
|
@ -253,13 +254,14 @@ void showPeerOverview(const PeerId &peer, MediaOverviewType type) {
|
|||
}
|
||||
}
|
||||
|
||||
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back) {
|
||||
if (MainWidget *m = App::main()) m->ui_showPeerHistory(peer, msgId, back);
|
||||
void showPeerHistory(const PeerId &peer, MsgId msgId, ShowWay way) {
|
||||
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()) {
|
||||
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 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 internal {
|
||||
|
||||
|
@ -557,6 +598,7 @@ struct Data {
|
|||
int32 PushChatLimit = 2;
|
||||
int32 SavedGifsLimit = 200;
|
||||
int32 EditTimeLimit = 172800;
|
||||
int32 StickersRecentLimit = 30;
|
||||
|
||||
HiddenPinnedMessagesMap HiddenPinnedMessages;
|
||||
|
||||
|
@ -565,6 +607,11 @@ struct Data {
|
|||
Stickers::Sets StickerSets;
|
||||
Stickers::Order StickerSetsOrder;
|
||||
uint64 LastStickersUpdate = 0;
|
||||
uint64 LastRecentStickersUpdate = 0;
|
||||
Stickers::Order FeaturedStickerSetsOrder;
|
||||
int FeaturedStickerSetsUnreadCount = 0;
|
||||
uint64 LastFeaturedStickersUpdate = 0;
|
||||
Stickers::Order ArchivedStickerSetsOrder;
|
||||
|
||||
MTP::DcOptions DcOptions;
|
||||
|
||||
|
@ -628,6 +675,7 @@ DefineVar(Global, int32, PushChatPeriod);
|
|||
DefineVar(Global, int32, PushChatLimit);
|
||||
DefineVar(Global, int32, SavedGifsLimit);
|
||||
DefineVar(Global, int32, EditTimeLimit);
|
||||
DefineVar(Global, int32, StickersRecentLimit);
|
||||
|
||||
DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages);
|
||||
|
||||
|
@ -636,6 +684,11 @@ DefineRefVar(Global, PendingItemsMap, PendingRepaintItems);
|
|||
DefineVar(Global, Stickers::Sets, StickerSets);
|
||||
DefineVar(Global, Stickers::Order, StickerSetsOrder);
|
||||
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);
|
||||
|
||||
|
|
|
@ -83,22 +83,27 @@ inline void showPeerOverview(const History *history, MediaOverviewType type) {
|
|||
showPeerOverview(history->peer->id, type);
|
||||
}
|
||||
|
||||
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back = false);
|
||||
inline void showPeerHistory(const PeerData *peer, MsgId msgId, bool back = false) {
|
||||
showPeerHistory(peer->id, msgId, back);
|
||||
enum class ShowWay {
|
||||
ClearStack,
|
||||
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) {
|
||||
showPeerHistory(history->peer->id, msgId, back);
|
||||
inline void showPeerHistory(const History *history, MsgId msgId, ShowWay way = ShowWay::ClearStack) {
|
||||
showPeerHistory(history->peer->id, msgId, way);
|
||||
}
|
||||
inline void showPeerHistoryAtItem(const HistoryItem *item) {
|
||||
showPeerHistory(item->history()->peer->id, item->id);
|
||||
inline void showPeerHistoryAtItem(const HistoryItem *item, ShowWay way = ShowWay::ClearStack) {
|
||||
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() {
|
||||
showPeerHistory(PeerId(0), 0);
|
||||
showPeerHistory(PeerId(0), 0, ShowWay::ClearStack);
|
||||
}
|
||||
inline void showChatsListAsync() {
|
||||
showPeerHistoryAsync(PeerId(0), 0);
|
||||
showPeerHistoryAsync(PeerId(0), 0, ShowWay::ClearStack);
|
||||
}
|
||||
PeerData *getPeerForMouseAction();
|
||||
|
||||
|
@ -178,10 +183,19 @@ enum Flags {
|
|||
namespace Stickers {
|
||||
|
||||
static const uint64 DefaultSetId = 0; // for backward compatibility
|
||||
static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL, RecentSetId = 0xFFFFFFFFFFFFFFFEULL;
|
||||
static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel
|
||||
static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL;
|
||||
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 {
|
||||
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;
|
||||
QString title, shortName;
|
||||
|
@ -193,6 +207,15 @@ struct Set {
|
|||
using Sets = QMap<uint64, Set>;
|
||||
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 Global {
|
||||
|
@ -236,6 +259,7 @@ DeclareVar(int32, PushChatPeriod);
|
|||
DeclareVar(int32, PushChatLimit);
|
||||
DeclareVar(int32, SavedGifsLimit);
|
||||
DeclareVar(int32, EditTimeLimit);
|
||||
DeclareVar(int32, StickersRecentLimit);
|
||||
|
||||
typedef QMap<PeerId, MsgId> HiddenPinnedMessagesMap;
|
||||
DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages);
|
||||
|
@ -246,6 +270,11 @@ DeclareRefVar(PendingItemsMap, PendingRepaintItems);
|
|||
DeclareVar(Stickers::Sets, StickerSets);
|
||||
DeclareVar(Stickers::Order, StickerSetsOrder);
|
||||
DeclareVar(uint64, LastStickersUpdate);
|
||||
DeclareVar(uint64, LastRecentStickersUpdate);
|
||||
DeclareVar(Stickers::Order, FeaturedStickerSetsOrder);
|
||||
DeclareVar(int, FeaturedStickerSetsUnreadCount);
|
||||
DeclareVar(uint64, LastFeaturedStickersUpdate);
|
||||
DeclareVar(Stickers::Order, ArchivedStickerSetsOrder);
|
||||
|
||||
DeclareVar(MTP::DcOptions, DcOptions);
|
||||
|
||||
|
|
|
@ -2869,7 +2869,9 @@ bool HistoryItem::unread() const {
|
|||
|
||||
if (id > 0) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -4079,10 +4081,10 @@ void HistoryDocument::draw(Painter &p, const QRect &r, TextSelection selection,
|
|||
bottom = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
|
||||
|
||||
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);
|
||||
if (selected) {
|
||||
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlaySmallCorners);
|
||||
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayLargeCorners);
|
||||
}
|
||||
|
||||
if (radial || (!loaded && !_data->loading())) {
|
||||
|
@ -5170,7 +5172,7 @@ int HistorySticker::additionalWidth(const HistoryMessageVia *via, const HistoryM
|
|||
}
|
||||
|
||||
void SendMessageClickHandler::onClickImpl() const {
|
||||
Ui::showPeerHistory(peer()->id, ShowAtUnreadMsgId);
|
||||
Ui::showPeerHistory(peer()->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward);
|
||||
}
|
||||
|
||||
void AddContactClickHandler::onClickImpl() const {
|
||||
|
|
|
@ -153,15 +153,15 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
StickerPack srows;
|
||||
if (_emoji) {
|
||||
QMap<uint64, uint64> setsToRequest;
|
||||
Stickers::Sets &sets(Global::RefStickerSets());
|
||||
const Stickers::Order &order(Global::StickerSetsOrder());
|
||||
auto &sets = Global::RefStickerSets();
|
||||
auto &order = Global::StickerSetsOrder();
|
||||
for (int i = 0, l = order.size(); i < l; ++i) {
|
||||
auto it = sets.find(order.at(i));
|
||||
if (it != sets.cend()) {
|
||||
if (it->emoji.isEmpty()) {
|
||||
setsToRequest.insert(it->id, it->access);
|
||||
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));
|
||||
if (i != it->emoji.cend()) {
|
||||
srows += *i;
|
||||
|
@ -196,14 +196,14 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
}
|
||||
return true;
|
||||
};
|
||||
auto filterNotPassedByName = [this](UserData *user) -> bool {
|
||||
auto filterNotPassedByName = [this, &filterNotPassedByUsername](UserData *user) -> bool {
|
||||
for_const (auto &namePart, user->names) {
|
||||
if (namePart.startsWith(_filter, Qt::CaseInsensitive)) {
|
||||
bool exactUsername = (user->username.compare(_filter, Qt::CaseInsensitive) == 0);
|
||||
return exactUsername;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return filterNotPassedByUsername(user);
|
||||
};
|
||||
|
||||
bool listAllSuggestions = _filter.isEmpty();
|
||||
|
|
|
@ -29,6 +29,8 @@ historyToDownArrow: icon {
|
|||
{ "history_down_arrow", #b9b9b9, point(14px, 19px) },
|
||||
};
|
||||
historyToDownPaddingTop: 10px;
|
||||
historyToDownBadgeFont: semiboldFont;
|
||||
historyToDownBadgeSize: 22px;
|
||||
|
||||
membersInnerScroll: flatScroll(solidScroll) {
|
||||
deltat: 3px;
|
||||
|
@ -43,8 +45,6 @@ membersInnerDropdown: InnerDropdown(defaultInnerDropdown) {
|
|||
scrollMargin: margins(0px, 5px, 0px, 5px);
|
||||
scrollPadding: margins(0px, 3px, 8px, 3px);
|
||||
}
|
||||
historyToDownBadgeFont: semiboldFont;
|
||||
historyToDownBadgeSize: 22px;
|
||||
|
||||
historyServiceMsgRadius: 12px;
|
||||
historyServiceMsgInvertedRadius: 6px;
|
||||
|
|
|
@ -33,6 +33,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "data/data_drafts.h"
|
||||
#include "history/history_service_layout.h"
|
||||
#include "profile/profile_members_widget.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "lang.h"
|
||||
#include "application.h"
|
||||
#include "mainwidget.h"
|
||||
|
@ -3523,12 +3524,23 @@ void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) {
|
|||
}
|
||||
|
||||
void HistoryWidget::updateStickers() {
|
||||
if (!Global::LastStickersUpdate() || getms(true) >= Global::LastStickersUpdate() + StickersUpdateTimeout) {
|
||||
auto now = getms(true);
|
||||
if (!Global::LastStickersUpdate() || now >= Global::LastStickersUpdate() + StickersUpdateTimeout) {
|
||||
if (!_stickersUpdateRequest) {
|
||||
_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) {
|
||||
_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);
|
||||
|
||||
Stickers::Order &setsOrder(Global::RefStickerSetsOrder());
|
||||
auto &setsOrder = Global::RefStickerSetsOrder();
|
||||
setsOrder.clear();
|
||||
|
||||
Stickers::Sets &sets(Global::RefStickerSets());
|
||||
auto &sets = Global::RefStickerSets();
|
||||
QMap<uint64, uint64> setsToRequest;
|
||||
for (auto i = sets.begin(), e = sets.end(); i != e; ++i) {
|
||||
i->access = 0; // mark for removing
|
||||
for (auto &set : sets) {
|
||||
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) {
|
||||
if (d_sets.at(i).type() == mtpc_stickerSet) {
|
||||
const auto &set(d_sets.at(i).c_stickerSet());
|
||||
auto it = sets.find(set.vid.v);
|
||||
QString 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);
|
||||
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);
|
||||
for_const (auto &setData, d_sets) {
|
||||
if (setData.type() == mtpc_stickerSet) {
|
||||
auto set = Stickers::feedSet(setData.c_stickerSet());
|
||||
if (!(set->flags & MTPDstickerSet::Flag::f_archived) || (set->flags & MTPDstickerSet::Flag::f_official)) {
|
||||
setsOrder.push_back(set->id);
|
||||
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
setsToRequest.insert(set->id, set->access);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3691,9 +3690,11 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
|
|||
bool writeRecent = false;
|
||||
RecentStickerPack &recent(cGetRecentStickers());
|
||||
for (Stickers::Sets::iterator it = sets.begin(), e = sets.end(); it != e;) {
|
||||
if (it->id == Stickers::CustomSetId || it->access != 0) {
|
||||
++it;
|
||||
} else {
|
||||
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) { // remove not mine sets from recent stickers
|
||||
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0) {
|
||||
i = recent.erase(i);
|
||||
|
@ -3702,6 +3703,10 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
|
|||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (installed || featured || special || archived) {
|
||||
++it;
|
||||
} else {
|
||||
it = sets.erase(it);
|
||||
}
|
||||
}
|
||||
|
@ -3717,7 +3722,7 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
|
|||
App::api()->requestStickerSets();
|
||||
}
|
||||
|
||||
Local::writeStickers();
|
||||
Local::writeInstalledStickers();
|
||||
if (writeRecent) Local::writeUserSettings();
|
||||
|
||||
if (App::main()) emit App::main()->stickersUpdated();
|
||||
|
@ -3733,6 +3738,193 @@ bool HistoryWidget::stickersFailed(const RPCError &error) {
|
|||
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) {
|
||||
cSetLastSavedGifsUpdate(getms(true));
|
||||
_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")) {
|
||||
PeerData *was = _peer;
|
||||
Ui::showChatsList();
|
||||
App::main()->showBackFromStack();
|
||||
Ui::showLayer(new InformBox(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible)));
|
||||
return true;
|
||||
}
|
||||
|
@ -4587,7 +4779,7 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId
|
|||
_preloadDownRequest = 0;
|
||||
} else if (_firstLoadRequest == requestId) {
|
||||
_firstLoadRequest = 0;
|
||||
Ui::showChatsList();
|
||||
App::main()->showBackFromStack();
|
||||
} else if (_delayedShowAtRequest == requestId) {
|
||||
_delayedShowAtRequest = 0;
|
||||
}
|
||||
|
@ -5605,6 +5797,8 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC
|
|||
toast.text = qs(answerData.vmessage);
|
||||
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;
|
||||
|
||||
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;
|
||||
QRect rectForName(st::topBarForwardPadding.left() + increaseLeft, st::topBarForwardPadding.top(), width() - decreaseWidth - st::topBarForwardPadding.left() - st::topBarForwardPadding.right(), st::msgNameFont->height);
|
||||
p.setFont(st::dialogsTextFont);
|
||||
|
@ -6055,7 +6249,7 @@ void HistoryWidget::paintTopBar(Painter &p, float64 over, int32 decreaseWidth) {
|
|||
p.setPen(st::dialogsNameFg);
|
||||
_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.drawSprite(QPoint((st::topBarForwardPadding.right() - st::topBarBackwardImg.pxWidth()) / 2, (st::topBarHeight - st::topBarBackwardImg.pxHeight()) / 2), st::topBarBackwardImg);
|
||||
} else {
|
||||
|
@ -6065,7 +6259,7 @@ void HistoryWidget::paintTopBar(Painter &p, float64 over, int32 decreaseWidth) {
|
|||
}
|
||||
|
||||
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 membersTextTop = st::topBarHeight - st::topBarForwardPadding.bottom() - st::dialogsTextFont->height;
|
||||
int membersTextWidth = _titlePeerTextWidth;
|
||||
|
@ -6111,8 +6305,8 @@ void HistoryWidget::onMembersDropdownHidden() {
|
|||
}
|
||||
|
||||
void HistoryWidget::topBarClick() {
|
||||
if (Adaptive::OneColumn()) {
|
||||
Ui::showChatsList();
|
||||
if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) {
|
||||
App::main()->showBackFromStack();
|
||||
} else {
|
||||
if (_history) Ui::showPeerProfile(_peer);
|
||||
}
|
||||
|
@ -6664,10 +6858,10 @@ void HistoryWidget::onReportSpamClear() {
|
|||
if (_clearPeer->isUser()) {
|
||||
App::main()->deleteConversation(_clearPeer);
|
||||
} 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));
|
||||
} else if (_clearPeer->isChannel()) {
|
||||
Ui::showChatsList();
|
||||
App::main()->showBackFromStack();
|
||||
if (_clearPeer->migrateFrom()) {
|
||||
App::main()->deleteConversation(_clearPeer->migrateFrom());
|
||||
}
|
||||
|
@ -7195,7 +7389,7 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) {
|
|||
if (e->key() == Qt::Key_Escape) {
|
||||
e->ignore();
|
||||
} else if (e->key() == Qt::Key_Back) {
|
||||
Ui::showChatsList();
|
||||
App::main()->showBackFromStack();
|
||||
emit cancelled();
|
||||
} else if (e->key() == Qt::Key_PageDown) {
|
||||
_scroll.keyPressEvent(e);
|
||||
|
@ -7973,7 +8167,7 @@ void HistoryWidget::onCancel() {
|
|||
} else if (!_fieldAutocomplete->isHidden()) {
|
||||
_fieldAutocomplete->hideStart();
|
||||
} else {
|
||||
Ui::showChatsList();
|
||||
App::main()->showBackFromStack();
|
||||
emit cancelled();
|
||||
}
|
||||
}
|
||||
|
@ -8011,7 +8205,7 @@ void HistoryWidget::peerUpdated(PeerData *data) {
|
|||
}
|
||||
QString restriction = _peer->restrictionReason();
|
||||
if (!restriction.isEmpty()) {
|
||||
Ui::showChatsList();
|
||||
App::main()->showBackFromStack();
|
||||
Ui::showLayer(new InformBox(restriction));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1005,6 +1005,14 @@ private:
|
|||
void stickersGot(const MTPmessages_AllStickers &stickers);
|
||||
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;
|
||||
void savedGifsGot(const MTPmessages_SavedGifs &gifs);
|
||||
bool savedGifsFailed(const RPCError &error);
|
||||
|
|
|
@ -352,7 +352,7 @@ void Result::createDocument() {
|
|||
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->setContentUrl(_content_url);
|
||||
|
|
|
@ -414,9 +414,9 @@ void FileLoadTask::process() {
|
|||
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.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 {
|
||||
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) {
|
||||
_type = PrepareDocument;
|
||||
}
|
||||
|
|
|
@ -479,11 +479,12 @@ namespace {
|
|||
lskBackground = 0x08, // no data
|
||||
lskUserSettings = 0x09, // no data
|
||||
lskRecentHashtagsAndBots = 0x0a, // no data
|
||||
lskStickers = 0x0b, // no data
|
||||
lskStickersOld = 0x0b, // no data
|
||||
lskSavedPeers = 0x0c, // no data
|
||||
lskReportSpamStatuses = 0x0d, // no data
|
||||
lskSavedGifsOld = 0x0e, // no data
|
||||
lskSavedGifs = 0x0f, // no data
|
||||
lskStickersKeys = 0x10, // no data
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -542,6 +543,7 @@ namespace {
|
|||
dbiDialogsMode = 0x40,
|
||||
dbiModerateMode = 0x41,
|
||||
dbiVideoVolume = 0x42,
|
||||
dbiStickersRecentLimit = 0x43,
|
||||
|
||||
dbiEncryptedWithSalt = 333,
|
||||
dbiEncrypted = 444,
|
||||
|
@ -571,7 +573,9 @@ namespace {
|
|||
uint64 _storageWebFilesSize = 0;
|
||||
FileKey _locationsKey = 0, _reportSpamStatusesKey = 0;
|
||||
|
||||
FileKey _recentStickersKeyOld = 0, _stickersKey = 0, _savedGifsKey = 0;
|
||||
FileKey _recentStickersKeyOld = 0;
|
||||
FileKey _installedStickersKey = 0, _featuredStickersKey = 0, _recentStickersKey = 0, _archivedStickersKey = 0;
|
||||
FileKey _savedGifsKey = 0;
|
||||
|
||||
FileKey _backgroundKey = 0;
|
||||
bool _backgroundWasRead = false;
|
||||
|
@ -835,6 +839,14 @@ namespace {
|
|||
Global::SetSavedGifsLimit(limit);
|
||||
} break;
|
||||
|
||||
case dbiStickersRecentLimit: {
|
||||
qint32 limit;
|
||||
stream >> limit;
|
||||
if (!_checkStreamStatus(stream)) return false;
|
||||
|
||||
Global::SetStickersRecentLimit(limit);
|
||||
} break;
|
||||
|
||||
case dbiMegagroupSizeMax: {
|
||||
qint32 maxSize;
|
||||
stream >> maxSize;
|
||||
|
@ -1725,7 +1737,9 @@ namespace {
|
|||
StorageMap imagesMap, stickerImagesMap, audiosMap;
|
||||
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
|
||||
quint64 locationsKey = 0, reportSpamStatusesKey = 0;
|
||||
quint64 recentStickersKeyOld = 0, stickersKey = 0, savedGifsKey = 0;
|
||||
quint64 recentStickersKeyOld = 0;
|
||||
quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, archivedStickersKey = 0;
|
||||
quint64 savedGifsKey = 0;
|
||||
quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsAndBotsKey = 0, savedPeersKey = 0;
|
||||
while (!map.stream.atEnd()) {
|
||||
quint32 keyType;
|
||||
|
@ -1806,8 +1820,11 @@ namespace {
|
|||
case lskRecentHashtagsAndBots: {
|
||||
map.stream >> recentHashtagsAndBotsKey;
|
||||
} break;
|
||||
case lskStickers: {
|
||||
map.stream >> stickersKey;
|
||||
case lskStickersOld: {
|
||||
map.stream >> installedStickersKey;
|
||||
} break;
|
||||
case lskStickersKeys: {
|
||||
map.stream >> installedStickersKey >> featuredStickersKey >> recentStickersKey >> archivedStickersKey;
|
||||
} break;
|
||||
case lskSavedGifsOld: {
|
||||
quint64 key;
|
||||
|
@ -1842,7 +1859,10 @@ namespace {
|
|||
_locationsKey = locationsKey;
|
||||
_reportSpamStatusesKey = reportSpamStatusesKey;
|
||||
_recentStickersKeyOld = recentStickersKeyOld;
|
||||
_stickersKey = stickersKey;
|
||||
_installedStickersKey = installedStickersKey;
|
||||
_featuredStickersKey = featuredStickersKey;
|
||||
_recentStickersKey = recentStickersKey;
|
||||
_archivedStickersKey = archivedStickersKey;
|
||||
_savedGifsKey = savedGifsKey;
|
||||
_savedPeersKey = savedPeersKey;
|
||||
_backgroundKey = backgroundKey;
|
||||
|
@ -1915,7 +1935,9 @@ namespace {
|
|||
if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_reportSpamStatusesKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_recentStickersKeyOld) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_stickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) {
|
||||
mapSize += sizeof(quint32) + 4 * sizeof(quint64);
|
||||
}
|
||||
if (_savedGifsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
|
@ -1961,8 +1983,9 @@ namespace {
|
|||
if (_recentStickersKeyOld) {
|
||||
mapData.stream << quint32(lskRecentStickersOld) << quint64(_recentStickersKeyOld);
|
||||
}
|
||||
if (_stickersKey) {
|
||||
mapData.stream << quint32(lskStickers) << quint64(_stickersKey);
|
||||
if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) {
|
||||
mapData.stream << quint32(lskStickersKeys);
|
||||
mapData.stream << quint64(_installedStickersKey) << quint64(_featuredStickersKey) << quint64(_recentStickersKey) << quint64(_archivedStickersKey);
|
||||
}
|
||||
if (_savedGifsKey) {
|
||||
mapData.stream << quint32(lskSavedGifs) << quint64(_savedGifsKey);
|
||||
|
@ -2185,12 +2208,13 @@ namespace Local {
|
|||
size += Serialize::stringSize(proxy.host) + sizeof(qint32) + Serialize::stringSize(proxy.user) + Serialize::stringSize(proxy.password);
|
||||
}
|
||||
|
||||
size += sizeof(quint32) + sizeof(qint32) * 6;
|
||||
size += sizeof(quint32) + sizeof(qint32) * 7;
|
||||
|
||||
EncryptedDescriptor data(size);
|
||||
data.stream << quint32(dbiChatSizeMax) << qint32(Global::ChatSizeMax());
|
||||
data.stream << quint32(dbiMegagroupSizeMax) << qint32(Global::MegagroupSizeMax());
|
||||
data.stream << quint32(dbiSavedGifsLimit) << qint32(Global::SavedGifsLimit());
|
||||
data.stream << quint32(dbiStickersRecentLimit) << qint32(Global::StickersRecentLimit());
|
||||
data.stream << quint32(dbiAutoStart) << qint32(cAutoStart());
|
||||
data.stream << quint32(dbiStartMinimized) << qint32(cStartMinimized());
|
||||
data.stream << quint32(dbiSendToMenu) << qint32(cSendToMenu());
|
||||
|
@ -2247,7 +2271,9 @@ namespace Local {
|
|||
_webFilesMap.clear();
|
||||
_storageWebFilesSize = 0;
|
||||
_locationsKey = _reportSpamStatusesKey = 0;
|
||||
_recentStickersKeyOld = _stickersKey = _savedGifsKey = 0;
|
||||
_recentStickersKeyOld = 0;
|
||||
_installedStickersKey = _featuredStickersKey = _recentStickersKey = _archivedStickersKey = 0;
|
||||
_savedGifsKey = 0;
|
||||
_backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0;
|
||||
_oldMapVersion = _oldSettingsVersion = 0;
|
||||
_mapChanged = true;
|
||||
|
@ -3017,26 +3043,23 @@ namespace Local {
|
|||
}
|
||||
}
|
||||
|
||||
void _writeStickerSet(QDataStream &stream, uint64 setId) {
|
||||
auto it = Global::StickerSets().constFind(setId);
|
||||
if (it == Global::StickerSets().cend()) return;
|
||||
|
||||
bool notLoaded = (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded);
|
||||
void _writeStickerSet(QDataStream &stream, const Stickers::Set &set) {
|
||||
bool notLoaded = (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded);
|
||||
if (notLoaded) {
|
||||
stream << quint64(it->id) << quint64(it->access) << it->title << it->shortName << qint32(-it->count) << qint32(it->hash) << qint32(it->flags);
|
||||
stream << quint64(set.id) << quint64(set.access) << set.title << set.shortName << qint32(-set.count) << qint32(set.hash) << qint32(set.flags);
|
||||
return;
|
||||
} else {
|
||||
if (it->stickers.isEmpty()) return;
|
||||
if (set.stickers.isEmpty()) return;
|
||||
}
|
||||
|
||||
stream << quint64(it->id) << quint64(it->access) << it->title << it->shortName << qint32(it->stickers.size()) << qint32(it->hash) << qint32(it->flags);
|
||||
for (StickerPack::const_iterator j = it->stickers.cbegin(), e = it->stickers.cend(); j != e; ++j) {
|
||||
stream << quint64(set.id) << quint64(set.access) << set.title << set.shortName << qint32(set.stickers.size()) << qint32(set.hash) << qint32(set.flags);
|
||||
for (StickerPack::const_iterator j = set.stickers.cbegin(), e = set.stickers.cend(); j != e; ++j) {
|
||||
Serialize::Document::writeToStream(stream, *j);
|
||||
}
|
||||
|
||||
if (AppVersion > 9018) {
|
||||
stream << qint32(it->emoji.size());
|
||||
for (StickersByEmojiMap::const_iterator j = it->emoji.cbegin(), e = it->emoji.cend(); j != e; ++j) {
|
||||
stream << qint32(set.emoji.size());
|
||||
for (StickersByEmojiMap::const_iterator j = set.emoji.cbegin(), e = set.emoji.cend(); j != e; ++j) {
|
||||
stream << emojiString(j.key()) << qint32(j->size());
|
||||
for (int32 k = 0, l = j->size(); k < l; ++k) {
|
||||
stream << quint64(j->at(k)->id);
|
||||
|
@ -3045,61 +3068,274 @@ namespace Local {
|
|||
}
|
||||
}
|
||||
|
||||
void writeStickers() {
|
||||
// In generic method _writeStickerSets() we look through all the sets and call a
|
||||
// callback on each set to see, if we write it, skip it or abort the whole write.
|
||||
enum class StickerSetCheckResult {
|
||||
Write,
|
||||
Skip,
|
||||
Abort,
|
||||
};
|
||||
|
||||
// CheckSet is a functor on Stickers::Set, which returns a StickerSetCheckResult.
|
||||
template <typename CheckSet>
|
||||
void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::Order &order) {
|
||||
if (!_working()) return;
|
||||
|
||||
const Stickers::Sets &sets(Global::StickerSets());
|
||||
auto &sets = Global::StickerSets();
|
||||
if (sets.isEmpty()) {
|
||||
if (_stickersKey) {
|
||||
clearKey(_stickersKey);
|
||||
_stickersKey = 0;
|
||||
if (stickersKey) {
|
||||
clearKey(stickersKey);
|
||||
stickersKey = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
_writeMap();
|
||||
} else {
|
||||
int32 setsCount = 0;
|
||||
QByteArray hashToWrite;
|
||||
quint32 size = sizeof(quint32) + Serialize::bytearraySize(hashToWrite);
|
||||
for (auto i = sets.cbegin(); i != sets.cend(); ++i) {
|
||||
bool notLoaded = (i->flags & MTPDstickerSet_ClientFlag::f_not_loaded);
|
||||
if (notLoaded) {
|
||||
if (!(i->flags & MTPDstickerSet::Flag::f_disabled) || (i->flags & MTPDstickerSet::Flag::f_official)) { // waiting to receive
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (i->stickers.isEmpty()) continue;
|
||||
}
|
||||
|
||||
// id + access + title + shortName + stickersCount + hash + flags
|
||||
size += sizeof(quint64) * 2 + Serialize::stringSize(i->title) + Serialize::stringSize(i->shortName) + sizeof(quint32) + sizeof(qint32) * 2;
|
||||
for (StickerPack::const_iterator j = i->stickers.cbegin(), e = i->stickers.cend(); j != e; ++j) {
|
||||
size += Serialize::Document::sizeInStream(*j);
|
||||
}
|
||||
|
||||
if (AppVersion > 9018) {
|
||||
size += sizeof(qint32); // emojiCount
|
||||
for (StickersByEmojiMap::const_iterator j = i->emoji.cbegin(), e = i->emoji.cend(); j != e; ++j) {
|
||||
size += Serialize::stringSize(emojiString(j.key())) + sizeof(qint32) + (j->size() * sizeof(quint64));
|
||||
}
|
||||
}
|
||||
|
||||
++setsCount;
|
||||
}
|
||||
|
||||
if (!_stickersKey) {
|
||||
_stickersKey = genKey();
|
||||
_mapChanged = true;
|
||||
_writeMap(WriteMapFast);
|
||||
}
|
||||
EncryptedDescriptor data(size);
|
||||
data.stream << quint32(setsCount) << hashToWrite;
|
||||
_writeStickerSet(data.stream, Stickers::CustomSetId);
|
||||
for (auto i = Global::StickerSetsOrder().cbegin(), e = Global::StickerSetsOrder().cend(); i != e; ++i) {
|
||||
_writeStickerSet(data.stream, *i);
|
||||
}
|
||||
FileWriteDescriptor file(_stickersKey);
|
||||
file.writeEncrypted(data);
|
||||
return;
|
||||
}
|
||||
int32 setsCount = 0;
|
||||
QByteArray hashToWrite;
|
||||
quint32 size = sizeof(quint32) + Serialize::bytearraySize(hashToWrite);
|
||||
for_const (auto &set, sets) {
|
||||
auto result = checkSet(set);
|
||||
if (result == StickerSetCheckResult::Abort) {
|
||||
return;
|
||||
} else if (result == StickerSetCheckResult::Skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// id + access + title + shortName + stickersCount + hash + flags
|
||||
size += sizeof(quint64) * 2 + Serialize::stringSize(set.title) + Serialize::stringSize(set.shortName) + sizeof(quint32) + sizeof(qint32) * 2;
|
||||
for_const (auto &sticker, set.stickers) {
|
||||
size += Serialize::Document::sizeInStream(sticker);
|
||||
}
|
||||
|
||||
size += sizeof(qint32); // emojiCount
|
||||
for (auto j = set.emoji.cbegin(), e = set.emoji.cend(); j != e; ++j) {
|
||||
size += Serialize::stringSize(emojiString(j.key())) + sizeof(qint32) + (j->size() * sizeof(quint64));
|
||||
}
|
||||
|
||||
++setsCount;
|
||||
}
|
||||
if (!setsCount && order.isEmpty()) {
|
||||
if (stickersKey) {
|
||||
clearKey(stickersKey);
|
||||
stickersKey = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
_writeMap();
|
||||
return;
|
||||
}
|
||||
size += sizeof(qint32) + (order.size() * sizeof(quint64));
|
||||
|
||||
if (!stickersKey) {
|
||||
stickersKey = genKey();
|
||||
_mapChanged = true;
|
||||
_writeMap(WriteMapFast);
|
||||
}
|
||||
EncryptedDescriptor data(size);
|
||||
data.stream << quint32(setsCount) << hashToWrite;
|
||||
for_const (auto &set, sets) {
|
||||
auto result = checkSet(set);
|
||||
if (result == StickerSetCheckResult::Abort) {
|
||||
return;
|
||||
} else if (result == StickerSetCheckResult::Skip) {
|
||||
continue;
|
||||
}
|
||||
_writeStickerSet(data.stream, set);
|
||||
}
|
||||
data.stream << order;
|
||||
|
||||
FileWriteDescriptor file(stickersKey);
|
||||
file.writeEncrypted(data);
|
||||
}
|
||||
|
||||
void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, MTPDstickerSet::Flags readingFlags = 0) {
|
||||
FileReadDescriptor stickers;
|
||||
if (!readEncryptedFile(stickers, stickersKey)) {
|
||||
clearKey(stickersKey);
|
||||
stickersKey = 0;
|
||||
_writeMap();
|
||||
return;
|
||||
}
|
||||
|
||||
bool readingInstalled = (readingFlags == qFlags(MTPDstickerSet::Flag::f_installed));
|
||||
|
||||
auto &sets = Global::RefStickerSets();
|
||||
if (outOrder) outOrder->clear();
|
||||
|
||||
quint32 cnt;
|
||||
QByteArray hash;
|
||||
stickers.stream >> cnt >> hash; // ignore hash, it is counted
|
||||
if (readingInstalled && stickers.version < 8019) { // bad data in old caches
|
||||
cnt += 2; // try to read at least something
|
||||
}
|
||||
for (uint32 i = 0; i < cnt; ++i) {
|
||||
quint64 setId = 0, setAccess = 0;
|
||||
QString setTitle, setShortName;
|
||||
qint32 scnt = 0;
|
||||
stickers.stream >> setId >> setAccess >> setTitle >> setShortName >> scnt;
|
||||
|
||||
qint32 setHash = 0, setFlags = 0;
|
||||
if (stickers.version > 8033) {
|
||||
stickers.stream >> setHash >> setFlags;
|
||||
if (setFlags & qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old)) {
|
||||
setFlags &= ~qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old);
|
||||
setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_not_loaded);
|
||||
}
|
||||
}
|
||||
if (readingInstalled && stickers.version < 9061) {
|
||||
setFlags |= qFlags(MTPDstickerSet::Flag::f_installed);
|
||||
}
|
||||
|
||||
if (setId == Stickers::DefaultSetId) {
|
||||
setTitle = lang(lng_stickers_default_set);
|
||||
setFlags |= qFlags(MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special);
|
||||
if (readingInstalled && outOrder && stickers.version < 9061) {
|
||||
outOrder->push_front(setId);
|
||||
}
|
||||
} else if (setId == Stickers::CustomSetId) {
|
||||
setTitle = lang(lng_custom_stickers);
|
||||
setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_special);
|
||||
} else if (setId == Stickers::CloudRecentSetId) {
|
||||
setTitle = lang(lng_emoji_category0); // Frequently used
|
||||
setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_special);
|
||||
} else if (setId) {
|
||||
if (readingInstalled && outOrder && stickers.version < 9061) {
|
||||
outOrder->push_back(setId);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.cend()) {
|
||||
// We will set this flags from order lists when reading those stickers.
|
||||
setFlags &= ~(MTPDstickerSet::Flag::f_installed | MTPDstickerSet_ClientFlag::f_featured);
|
||||
it = sets.insert(setId, Stickers::Set(setId, setAccess, setTitle, setShortName, 0, setHash, MTPDstickerSet::Flags(setFlags)));
|
||||
}
|
||||
auto &set = it.value();
|
||||
|
||||
if (scnt < 0) { // disabled not loaded set
|
||||
if (!set.count || set.stickers.isEmpty()) {
|
||||
set.count = -scnt;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool fillStickers = set.stickers.isEmpty();
|
||||
if (fillStickers) {
|
||||
set.stickers.reserve(scnt);
|
||||
set.count = 0;
|
||||
}
|
||||
|
||||
Serialize::Document::StickerSetInfo info(setId, setAccess, setShortName);
|
||||
OrderedSet<DocumentId> read;
|
||||
for (int32 j = 0; j < scnt; ++j) {
|
||||
auto document = Serialize::Document::readStickerFromStream(stickers.version, stickers.stream, info);
|
||||
if (!document || !document->sticker()) continue;
|
||||
|
||||
if (read.contains(document->id)) continue;
|
||||
read.insert(document->id);
|
||||
|
||||
if (fillStickers) {
|
||||
set.stickers.push_back(document);
|
||||
++set.count;
|
||||
}
|
||||
}
|
||||
|
||||
if (stickers.version > 9018) {
|
||||
qint32 emojiCount;
|
||||
stickers.stream >> emojiCount;
|
||||
for (int32 j = 0; j < emojiCount; ++j) {
|
||||
QString emojiString;
|
||||
qint32 stickersCount;
|
||||
stickers.stream >> emojiString >> stickersCount;
|
||||
StickerPack pack;
|
||||
pack.reserve(stickersCount);
|
||||
for (int32 k = 0; k < stickersCount; ++k) {
|
||||
quint64 id;
|
||||
stickers.stream >> id;
|
||||
DocumentData *doc = App::document(id);
|
||||
if (!doc || !doc->sticker()) continue;
|
||||
|
||||
pack.push_back(doc);
|
||||
}
|
||||
if (fillStickers) {
|
||||
if (auto e = emojiGetNoColor(emojiFromText(emojiString))) {
|
||||
set.emoji.insert(e, pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read orders of installed and featured stickers.
|
||||
if (outOrder && stickers.version >= 9061) {
|
||||
stickers.stream >> *outOrder;
|
||||
}
|
||||
|
||||
// Set flags that we dropped above from the order.
|
||||
if (readingFlags && outOrder) {
|
||||
for_const (auto setId, *outOrder) {
|
||||
auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
it->flags |= readingFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void writeInstalledStickers() {
|
||||
_writeStickerSets(_installedStickersKey, [](const Stickers::Set &set) {
|
||||
if (set.id == Stickers::CloudRecentSetId) { // separate file for recent
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
|
||||
if (set.stickers.isEmpty()) { // all other special are "installed"
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
} else if (!(set.flags & MTPDstickerSet::Flag::f_installed) || (set.flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded) { // waiting to receive
|
||||
return StickerSetCheckResult::Abort;
|
||||
} else if (set.stickers.isEmpty()) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
return StickerSetCheckResult::Write;
|
||||
}, Global::StickerSetsOrder());
|
||||
}
|
||||
|
||||
void writeFeaturedStickers() {
|
||||
_writeStickerSets(_featuredStickersKey, [](const Stickers::Set &set) {
|
||||
if (set.id == Stickers::CloudRecentSetId) { // separate file for recent
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (!(set.flags & MTPDstickerSet_ClientFlag::f_featured)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded) { // waiting to receive
|
||||
return StickerSetCheckResult::Abort;
|
||||
} else if (set.stickers.isEmpty()) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
return StickerSetCheckResult::Write;
|
||||
}, Global::FeaturedStickerSetsOrder());
|
||||
}
|
||||
|
||||
void writeRecentStickers() {
|
||||
_writeStickerSets(_recentStickersKey, [](const Stickers::Set &set) {
|
||||
if (set.id != Stickers::CloudRecentSetId || set.stickers.isEmpty()) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
return StickerSetCheckResult::Write;
|
||||
}, Stickers::Order());
|
||||
}
|
||||
|
||||
void writeArchivedStickers() {
|
||||
_writeStickerSets(_archivedStickersKey, [](const Stickers::Set &set) {
|
||||
if (!(set.flags & MTPDstickerSet::Flag::f_archived) || set.stickers.isEmpty()) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
return StickerSetCheckResult::Write;
|
||||
}, Global::ArchivedStickerSetsOrder());
|
||||
}
|
||||
|
||||
void importOldRecentStickers() {
|
||||
|
@ -3113,17 +3349,17 @@ namespace Local {
|
|||
return;
|
||||
}
|
||||
|
||||
Stickers::Sets &sets(Global::RefStickerSets());
|
||||
auto &sets = Global::RefStickerSets();
|
||||
sets.clear();
|
||||
|
||||
Stickers::Order &order(Global::RefStickerSetsOrder());
|
||||
auto &order = Global::RefStickerSetsOrder();
|
||||
order.clear();
|
||||
|
||||
RecentStickerPack &recent(cRefRecentStickers());
|
||||
auto &recent = cRefRecentStickers();
|
||||
recent.clear();
|
||||
|
||||
Stickers::Set &def(sets.insert(Stickers::DefaultSetId, Stickers::Set(Stickers::DefaultSetId, 0, lang(lng_stickers_default_set), QString(), 0, 0, MTPDstickerSet::Flag::f_official)).value());
|
||||
Stickers::Set &custom(sets.insert(Stickers::CustomSetId, Stickers::Set(Stickers::CustomSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, 0)).value());
|
||||
auto &def = sets.insert(Stickers::DefaultSetId, Stickers::Set(Stickers::DefaultSetId, 0, lang(lng_stickers_default_set), QString(), 0, 0, MTPDstickerSet::Flag::f_official | MTPDstickerSet::Flag::f_installed | MTPDstickerSet_ClientFlag::f_special)).value();
|
||||
auto &custom = sets.insert(Stickers::CustomSetId, Stickers::Set(Stickers::CustomSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, MTPDstickerSet::Flag::f_installed | MTPDstickerSet_ClientFlag::f_special)).value();
|
||||
|
||||
QMap<uint64, bool> read;
|
||||
while (!stickers.stream.atEnd()) {
|
||||
|
@ -3149,7 +3385,7 @@ namespace Local {
|
|||
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));
|
||||
}
|
||||
|
||||
DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, ImagePtr(), dc, size, StorageImageLocation());
|
||||
DocumentData *doc = App::documentSet(id, 0, access, 0, date, attributes, mime, ImagePtr(), dc, size, StorageImageLocation());
|
||||
if (!doc->sticker()) continue;
|
||||
|
||||
if (value > 0) {
|
||||
|
@ -3159,7 +3395,9 @@ namespace Local {
|
|||
custom.stickers.push_back(doc);
|
||||
++custom.count;
|
||||
}
|
||||
if (recent.size() < StickerPanPerRow * StickerPanRowsPerPage && qAbs(value) > 1) recent.push_back(qMakePair(doc, qAbs(value)));
|
||||
if (recent.size() < Global::StickersRecentLimit() && qAbs(value) > 1) {
|
||||
recent.push_back(qMakePair(doc, qAbs(value)));
|
||||
}
|
||||
}
|
||||
if (def.stickers.isEmpty()) {
|
||||
sets.remove(Stickers::DefaultSetId);
|
||||
|
@ -3168,7 +3406,7 @@ namespace Local {
|
|||
}
|
||||
if (custom.stickers.isEmpty()) sets.remove(Stickers::CustomSetId);
|
||||
|
||||
writeStickers();
|
||||
writeInstalledStickers();
|
||||
writeUserSettings();
|
||||
|
||||
clearKey(_recentStickersKeyOld);
|
||||
|
@ -3176,130 +3414,95 @@ namespace Local {
|
|||
_writeMap();
|
||||
}
|
||||
|
||||
void readStickers() {
|
||||
if (!_stickersKey) {
|
||||
void readInstalledStickers() {
|
||||
if (!_installedStickersKey) {
|
||||
return importOldRecentStickers();
|
||||
}
|
||||
|
||||
FileReadDescriptor stickers;
|
||||
if (!readEncryptedFile(stickers, _stickersKey)) {
|
||||
clearKey(_stickersKey);
|
||||
_stickersKey = 0;
|
||||
_writeMap();
|
||||
return;
|
||||
Global::RefStickerSets().clear();
|
||||
_readStickerSets(_installedStickersKey, &Global::RefStickerSetsOrder(), qFlags(MTPDstickerSet::Flag::f_installed));
|
||||
}
|
||||
|
||||
void readFeaturedStickers() {
|
||||
_readStickerSets(_featuredStickersKey, &Global::RefFeaturedStickerSetsOrder(), qFlags(MTPDstickerSet_ClientFlag::f_featured));
|
||||
|
||||
auto &sets = Global::StickerSets();
|
||||
int unreadCount = 0;
|
||||
for_const (auto setId, Global::FeaturedStickerSetsOrder()) {
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend() && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) {
|
||||
++unreadCount;
|
||||
}
|
||||
}
|
||||
Global::SetFeaturedStickerSetsUnreadCount(unreadCount);
|
||||
}
|
||||
|
||||
Stickers::Sets &sets(Global::RefStickerSets());
|
||||
sets.clear();
|
||||
void readRecentStickers() {
|
||||
_readStickerSets(_recentStickersKey);
|
||||
}
|
||||
|
||||
Stickers::Order &order(Global::RefStickerSetsOrder());
|
||||
order.clear();
|
||||
|
||||
quint32 cnt;
|
||||
QByteArray hash;
|
||||
stickers.stream >> cnt >> hash; // ignore hash, it is counted
|
||||
if (stickers.version < 8019) { // bad data in old caches
|
||||
cnt += 2; // try to read at least something
|
||||
}
|
||||
for (uint32 i = 0; i < cnt; ++i) {
|
||||
quint64 setId = 0, setAccess = 0;
|
||||
QString setTitle, setShortName;
|
||||
qint32 scnt = 0;
|
||||
stickers.stream >> setId >> setAccess >> setTitle >> setShortName >> scnt;
|
||||
|
||||
qint32 setHash = 0, setFlags = 0;
|
||||
if (stickers.version > 8033) {
|
||||
stickers.stream >> setHash >> setFlags;
|
||||
if (setFlags & qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old)) {
|
||||
setFlags &= ~qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old);
|
||||
setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_not_loaded);
|
||||
}
|
||||
}
|
||||
|
||||
if (setId == Stickers::DefaultSetId) {
|
||||
setTitle = lang(lng_stickers_default_set);
|
||||
setFlags |= qFlags(MTPDstickerSet::Flag::f_official);
|
||||
order.push_front(setId);
|
||||
} else if (setId == Stickers::CustomSetId) {
|
||||
setTitle = lang(lng_custom_stickers);
|
||||
} else if (setId) {
|
||||
order.push_back(setId);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
Stickers::Set &set(sets.insert(setId, Stickers::Set(setId, setAccess, setTitle, setShortName, 0, setHash, MTPDstickerSet::Flags(setFlags))).value());
|
||||
if (scnt < 0) { // disabled not loaded set
|
||||
set.count = -scnt;
|
||||
continue;
|
||||
}
|
||||
|
||||
set.stickers.reserve(scnt);
|
||||
|
||||
Serialize::Document::StickerSetInfo info(setId, setAccess, setShortName);
|
||||
OrderedSet<DocumentId> read;
|
||||
for (int32 j = 0; j < scnt; ++j) {
|
||||
auto document = Serialize::Document::readStickerFromStream(stickers.stream, info);
|
||||
if (!document || !document->sticker()) continue;
|
||||
|
||||
if (read.contains(document->id)) continue;
|
||||
read.insert(document->id);
|
||||
|
||||
set.stickers.push_back(document);
|
||||
++set.count;
|
||||
}
|
||||
|
||||
if (stickers.version > 9018) {
|
||||
qint32 emojiCount;
|
||||
stickers.stream >> emojiCount;
|
||||
for (int32 j = 0; j < emojiCount; ++j) {
|
||||
QString emojiString;
|
||||
qint32 stickersCount;
|
||||
stickers.stream >> emojiString >> stickersCount;
|
||||
StickerPack pack;
|
||||
pack.reserve(stickersCount);
|
||||
for (int32 k = 0; k < stickersCount; ++k) {
|
||||
quint64 id;
|
||||
stickers.stream >> id;
|
||||
DocumentData *doc = App::document(id);
|
||||
if (!doc || !doc->sticker()) continue;
|
||||
|
||||
pack.push_back(doc);
|
||||
}
|
||||
if (EmojiPtr e = emojiGetNoColor(emojiFromText(emojiString))) {
|
||||
set.emoji.insert(e, pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
void readArchivedStickers() {
|
||||
static bool archivedStickersRead = false;
|
||||
if (!archivedStickersRead) {
|
||||
_readStickerSets(_archivedStickersKey, &Global::RefArchivedStickerSetsOrder());
|
||||
archivedStickersRead = true;
|
||||
}
|
||||
}
|
||||
|
||||
int32 countStickersHash(bool checkOfficial) {
|
||||
int32 countStickersHash(bool checkOutdatedInfo) {
|
||||
uint32 acc = 0;
|
||||
bool foundOfficial = false, foundBad = false;;
|
||||
const Stickers::Sets &sets(Global::StickerSets());
|
||||
const Stickers::Order &order(Global::StickerSetsOrder());
|
||||
bool foundOutdated = false;
|
||||
auto &sets = Global::StickerSets();
|
||||
auto &order = Global::StickerSetsOrder();
|
||||
for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) {
|
||||
auto j = sets.constFind(*i);
|
||||
if (j != sets.cend()) {
|
||||
if (j->id == 0) {
|
||||
foundBad = true;
|
||||
} else if (j->flags & MTPDstickerSet::Flag::f_official) {
|
||||
foundOfficial = true;
|
||||
}
|
||||
if (!(j->flags & MTPDstickerSet::Flag::f_disabled)) {
|
||||
if (j->id == Stickers::DefaultSetId) {
|
||||
foundOutdated = true;
|
||||
} else if (!(j->flags & MTPDstickerSet_ClientFlag::f_special)
|
||||
&& !(j->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
acc = (acc * 20261) + j->hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (!checkOfficial || (!foundBad && foundOfficial)) ? int32(acc & 0x7FFFFFFF) : 0;
|
||||
return (!checkOutdatedInfo || !foundOutdated) ? int32(acc & 0x7FFFFFFF) : 0;
|
||||
}
|
||||
|
||||
int32 countRecentStickersHash() {
|
||||
uint32 acc = 0;
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.constFind(Stickers::CloudRecentSetId);
|
||||
if (it != sets.cend()) {
|
||||
for_const (auto doc, it->stickers) {
|
||||
auto docId = doc->id;
|
||||
acc = (acc * 20261) + uint32(docId >> 32);
|
||||
acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
return int32(acc & 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
int32 countFeaturedStickersHash() {
|
||||
uint32 acc = 0;
|
||||
auto &sets = Global::StickerSets();
|
||||
auto &featured = Global::FeaturedStickerSetsOrder();
|
||||
for_const (auto setId, featured) {
|
||||
acc = (acc * 20261) + uint32(setId >> 32);
|
||||
acc = (acc * 20261) + uint32(setId & 0xFFFFFFFF);
|
||||
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend() && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) {
|
||||
acc = (acc * 20261) + 1U;
|
||||
}
|
||||
}
|
||||
return int32(acc & 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
int32 countSavedGifsHash() {
|
||||
uint32 acc = 0;
|
||||
const SavedGifs &saved(cSavedGifs());
|
||||
for (SavedGifs::const_iterator i = saved.cbegin(), e = saved.cend(); i != e; ++i) {
|
||||
uint64 docId = (*i)->id;
|
||||
|
||||
auto &saved = cSavedGifs();
|
||||
for_const (auto doc, saved) {
|
||||
auto docId = doc->id;
|
||||
acc = (acc * 20261) + uint32(docId >> 32);
|
||||
acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF);
|
||||
}
|
||||
|
@ -3357,7 +3560,7 @@ namespace Local {
|
|||
saved.reserve(cnt);
|
||||
OrderedSet<DocumentId> read;
|
||||
for (uint32 i = 0; i < cnt; ++i) {
|
||||
DocumentData *document = Serialize::Document::readFromStream(gifs.stream);
|
||||
DocumentData *document = Serialize::Document::readFromStream(gifs.version, gifs.stream);
|
||||
if (!document || !document->isAnimation()) continue;
|
||||
|
||||
if (read.contains(document->id)) continue;
|
||||
|
@ -3862,8 +4065,8 @@ namespace Local {
|
|||
_recentStickersKeyOld = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
if (_stickersKey) {
|
||||
_stickersKey = 0;
|
||||
if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) {
|
||||
_installedStickersKey = _featuredStickersKey = _recentStickersKey = _archivedStickersKey = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
if (_recentHashtagsAndBotsKey) {
|
||||
|
|
|
@ -153,9 +153,17 @@ namespace Local {
|
|||
|
||||
void cancelTask(TaskId id);
|
||||
|
||||
void writeStickers();
|
||||
void readStickers();
|
||||
int32 countStickersHash(bool checkOfficial = false);
|
||||
void writeInstalledStickers();
|
||||
void writeFeaturedStickers();
|
||||
void writeRecentStickers();
|
||||
void writeArchivedStickers();
|
||||
void readInstalledStickers();
|
||||
void readFeaturedStickers();
|
||||
void readRecentStickers();
|
||||
void readArchivedStickers();
|
||||
int32 countStickersHash(bool checkOutdatedInfo = false);
|
||||
int32 countRecentStickersHash();
|
||||
int32 countFeaturedStickersHash();
|
||||
|
||||
void writeSavedGifs();
|
||||
void readSavedGifs();
|
||||
|
|
|
@ -298,11 +298,6 @@ void MainWidget::finishForwarding(History *history, bool silent) {
|
|||
FullMsgId newId(peerToChannel(history->peer->id), clientMsgId());
|
||||
HistoryMessage *msg = static_cast<HistoryMessage*>(_toForward.cbegin().value());
|
||||
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);
|
||||
}
|
||||
if (forwardFrom != i.value()->history()->peer) {
|
||||
|
@ -1519,8 +1514,8 @@ void MainWidget::onSharePhoneWithBot(PeerData *recipient) {
|
|||
onShareContact(recipient->id, App::self());
|
||||
}
|
||||
|
||||
void MainWidget::ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId) {
|
||||
Ui::showPeerHistory(peerId, showAtMsgId);
|
||||
void MainWidget::ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId, Ui::ShowWay way) {
|
||||
Ui::showPeerHistory(peerId, showAtMsgId, way);
|
||||
}
|
||||
|
||||
void MainWidget::ui_autoplayMediaInlineAsync(qint32 channelId, qint32 msgId) {
|
||||
|
@ -1995,7 +1990,7 @@ void MainWidget::ctrlEnterSubmitUpdated() {
|
|||
_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 (peer->migrateTo()) {
|
||||
peer = peer->migrateTo();
|
||||
|
@ -2009,8 +2004,37 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac
|
|||
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();
|
||||
|
@ -2022,10 +2046,12 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
if (_history->peer() && _history->peer()->id != peerId) clearBotStartToken(_history->peer());
|
||||
if (_history->peer() && _history->peer()->id != peerId) {
|
||||
clearBotStartToken(_history->peer());
|
||||
}
|
||||
_history->showHistory(peerId, showAtMsgId);
|
||||
|
||||
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 = nullptr;
|
||||
}
|
||||
clearBotStartToken(_peerInStack);
|
||||
dlgUpdated();
|
||||
_peerInStack = 0;
|
||||
_msgIdInStack = 0;
|
||||
_stack.clear();
|
||||
}
|
||||
if (onlyDialogs) {
|
||||
_topBar->hide();
|
||||
|
@ -2090,6 +2111,7 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool bac
|
|||
}
|
||||
_dialogs->update();
|
||||
}
|
||||
topBar()->showAll();
|
||||
App::wnd()->getTitle()->updateBackButton();
|
||||
}
|
||||
|
||||
|
@ -2146,6 +2168,21 @@ bool MainWidget::mediaTypeSwitch() {
|
|||
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) {
|
||||
if (peer->migrateTo()) {
|
||||
peer = peer->migrateTo();
|
||||
|
@ -2166,17 +2203,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
|
|||
animationParams = prepareOverviewAnimation();
|
||||
}
|
||||
if (!back) {
|
||||
if (_overview) {
|
||||
_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()));
|
||||
}
|
||||
saveSectionInStack();
|
||||
}
|
||||
if (_overview) {
|
||||
_overview->hide();
|
||||
|
@ -2201,7 +2228,9 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
|
|||
_overview->fastShow();
|
||||
}
|
||||
_history->animStop();
|
||||
if (back) clearBotStartToken(_history->peer());
|
||||
if (back) {
|
||||
clearBotStartToken(_history->peer());
|
||||
}
|
||||
_history->showHistory(0, 0);
|
||||
_history->hide();
|
||||
if (Adaptive::OneColumn()) _dialogs->hide();
|
||||
|
@ -2217,17 +2246,7 @@ void MainWidget::showWideSection(const Window::SectionMemento &memento) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (_overview) {
|
||||
_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()));
|
||||
}
|
||||
saveSectionInStack();
|
||||
showWideSectionAnimated(&memento, false);
|
||||
}
|
||||
|
||||
|
@ -2320,6 +2339,10 @@ void MainWidget::showWideSectionAnimated(const Window::SectionMemento *memento,
|
|||
App::wnd()->getTitle()->updateBackButton();
|
||||
}
|
||||
|
||||
bool MainWidget::stackIsEmpty() const {
|
||||
return _stack.isEmpty();
|
||||
}
|
||||
|
||||
void MainWidget::showBackFromStack() {
|
||||
if (selectingPeer()) return;
|
||||
if (_stack.isEmpty()) {
|
||||
|
@ -2327,34 +2350,33 @@ void MainWidget::showBackFromStack() {
|
|||
if (App::wnd()) QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus()));
|
||||
return;
|
||||
}
|
||||
StackItem *item = _stack.back();
|
||||
auto item = std_::move(_stack.back());
|
||||
_stack.pop_back();
|
||||
if (auto currentHistoryPeer = _history->peer()) {
|
||||
clearBotStartToken(currentHistoryPeer);
|
||||
}
|
||||
if (item->type() == HistoryStackItem) {
|
||||
dlgUpdated();
|
||||
_peerInStack = 0;
|
||||
_peerInStack = nullptr;
|
||||
_msgIdInStack = 0;
|
||||
for (int32 i = _stack.size(); i > 0;) {
|
||||
if (_stack.at(--i)->type() == HistoryStackItem) {
|
||||
_peerInStack = static_cast<StackItemHistory*>(_stack.at(i))->peer;
|
||||
_msgIdInStack = static_cast<StackItemHistory*>(_stack.at(i))->msgId;
|
||||
_peerInStack = static_cast<StackItemHistory*>(_stack.at(i).get())->peer;
|
||||
_msgIdInStack = static_cast<StackItemHistory*>(_stack.at(i).get())->msgId;
|
||||
dlgUpdated();
|
||||
break;
|
||||
}
|
||||
}
|
||||
StackItemHistory *histItem = static_cast<StackItemHistory*>(item);
|
||||
Ui::showPeerHistory(histItem->peer->id, App::main()->activeMsgId(), true);
|
||||
StackItemHistory *histItem = static_cast<StackItemHistory*>(item.get());
|
||||
Ui::showPeerHistory(histItem->peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Backward);
|
||||
_history->setReplyReturns(histItem->peer->id, histItem->replyReturns);
|
||||
} else if (item->type() == SectionStackItem) {
|
||||
StackItemSection *sectionItem = static_cast<StackItemSection*>(item);
|
||||
StackItemSection *sectionItem = static_cast<StackItemSection*>(item.get());
|
||||
showWideSectionAnimated(sectionItem->memento(), true);
|
||||
} 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);
|
||||
}
|
||||
delete item;
|
||||
}
|
||||
|
||||
void MainWidget::orderWidgets() {
|
||||
|
@ -3251,7 +3273,9 @@ void MainWidget::start(const MTPUser &user) {
|
|||
}
|
||||
_started = true;
|
||||
App::wnd()->sendServiceHistoryRequest();
|
||||
Local::readStickers();
|
||||
Local::readInstalledStickers();
|
||||
Local::readFeaturedStickers();
|
||||
Local::readRecentStickers();
|
||||
Local::readSavedGifs();
|
||||
_history->start();
|
||||
}
|
||||
|
@ -3322,7 +3346,7 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr
|
|||
Ui::showLayer(new ContactsBox(peer->asUser()));
|
||||
} else if (peer->isUser() && peer->asUser()->botInfo) {
|
||||
// Always open bot chats, even from mention links.
|
||||
Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId);
|
||||
Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward);
|
||||
} else {
|
||||
Ui::showPeerProfile(peer);
|
||||
}
|
||||
|
@ -3337,7 +3361,7 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr
|
|||
_history->resizeEvent(0);
|
||||
}
|
||||
}
|
||||
Ui::showPeerHistoryAsync(peer->id, msgId);
|
||||
Ui::showPeerHistoryAsync(peer->id, msgId, Ui::ShowWay::Forward);
|
||||
}
|
||||
} else {
|
||||
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) {
|
||||
emit stickersUpdated();
|
||||
_history->stickersInstalled(setId);
|
||||
}
|
||||
|
||||
|
@ -3405,7 +3428,7 @@ void MainWidget::usernameResolveDone(QPair<MsgId, QString> msgIdAndStartToken, c
|
|||
Ui::showLayer(new ContactsBox(peer->asUser()));
|
||||
} else if (peer->isUser() && peer->asUser()->botInfo) {
|
||||
// Always open bot chats, even from mention links.
|
||||
Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId);
|
||||
Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward);
|
||||
} else {
|
||||
Ui::showPeerProfile(peer);
|
||||
}
|
||||
|
@ -3436,11 +3459,21 @@ bool MainWidget::usernameResolveFail(QString name, const RPCError &error) {
|
|||
void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) {
|
||||
switch (invite.type()) {
|
||||
case mtpc_chatInvite: {
|
||||
const 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));
|
||||
auto &d(invite.c_chatInvite());
|
||||
|
||||
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;
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onInviteImport()));
|
||||
Ui::showLayer(box);
|
||||
Ui::showLayer(box.release());
|
||||
} break;
|
||||
|
||||
case mtpc_chatInviteAlready: {
|
||||
|
@ -3618,72 +3651,65 @@ void MainWidget::updateNotifySetting(PeerData *peer, NotifySettingStatus notify,
|
|||
|
||||
void MainWidget::incrementSticker(DocumentData *sticker) {
|
||||
if (!sticker || !sticker->sticker()) return;
|
||||
if (sticker->sticker()->set.type() == mtpc_inputStickerSetEmpty) return;
|
||||
|
||||
RecentStickerPack &recent(cGetRecentStickers());
|
||||
RecentStickerPack::iterator i = recent.begin(), e = recent.end();
|
||||
for (; i != e; ++i) {
|
||||
bool writeRecentStickers = false;
|
||||
auto &sets = Global::RefStickerSets();
|
||||
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) {
|
||||
i->second = recent.begin()->second; // throw to the first place
|
||||
//++i->second;
|
||||
//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));
|
||||
}
|
||||
writeOldRecent = true;
|
||||
recent.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == e) {
|
||||
while (recent.size() >= StickerPanPerRow * StickerPanRowsPerPage) recent.pop_back();
|
||||
recent.push_front(qMakePair(sticker, recent.isEmpty() ? 1 : recent.begin()->second));
|
||||
//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));
|
||||
//}
|
||||
while (!recent.isEmpty() && it->stickers.size() + recent.size() > Global::StickersRecentLimit()) {
|
||||
writeOldRecent = true;
|
||||
recent.pop_back();
|
||||
}
|
||||
|
||||
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;
|
||||
if (writeOldRecent) {
|
||||
Local::writeUserSettings();
|
||||
}
|
||||
Stickers::Sets &sets(Global::RefStickerSets());
|
||||
for (auto i = sets.cbegin(); i != sets.cend(); ++i) {
|
||||
if (i->id == Stickers::CustomSetId || i->id == Stickers::DefaultSetId || (setId && i->id == setId) || (!setName.isEmpty() && i->shortName.toLower().trimmed() == setName)) {
|
||||
for (int32 j = 0, l = i->stickers.size(); j < l; ++j) {
|
||||
if (i->stickers.at(j) == sticker) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove that sticker from custom stickers, now it is in cloud recent stickers.
|
||||
bool writeInstalledStickers = false;
|
||||
auto custom = sets.find(Stickers::CustomSetId);
|
||||
if (custom != sets.cend()) {
|
||||
int removeIndex = custom->stickers.indexOf(sticker);
|
||||
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 (it == sets.cend()) {
|
||||
it = sets.insert(Stickers::CustomSetId, Stickers::Set(Stickers::CustomSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, 0));
|
||||
}
|
||||
it->stickers.push_back(sticker);
|
||||
++it->count;
|
||||
Local::writeStickers();
|
||||
|
||||
if (writeInstalledStickers) {
|
||||
Local::writeInstalledStickers();
|
||||
}
|
||||
if (writeRecentStickers) {
|
||||
Local::writeRecentStickers();
|
||||
}
|
||||
_history->updateRecentStickers();
|
||||
}
|
||||
|
@ -4625,16 +4651,23 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
|
||||
////// Cloud sticker sets
|
||||
case mtpc_updateNewStickerSet: {
|
||||
const auto &d(update.c_updateNewStickerSet());
|
||||
auto &d = update.c_updateNewStickerSet();
|
||||
bool writeArchived = false;
|
||||
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) {
|
||||
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);
|
||||
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);
|
||||
|
@ -4647,12 +4680,12 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
it->stickers.push_back(doc);
|
||||
}
|
||||
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) {
|
||||
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)))) {
|
||||
const auto &stickers(pack.vdocuments.c_vector().v);
|
||||
auto &stickers = pack.vdocuments.c_vector().v;
|
||||
StickerPack p;
|
||||
p.reserve(stickers.size());
|
||||
for (int32 j = 0, c = stickers.size(); j < c; ++j) {
|
||||
|
@ -4684,16 +4717,17 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
sets.erase(custom);
|
||||
}
|
||||
}
|
||||
Local::writeStickers();
|
||||
Local::writeInstalledStickers();
|
||||
if (writeArchived) Local::writeArchivedStickers();
|
||||
emit stickersUpdated();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateStickerSetsOrder: {
|
||||
const auto &d(update.c_updateStickerSetsOrder());
|
||||
const auto &order(d.vorder.c_vector().v);
|
||||
const auto &sets(Global::StickerSets());
|
||||
auto &d = update.c_updateStickerSetsOrder();
|
||||
auto &order = d.vorder.c_vector().v;
|
||||
auto &sets = Global::StickerSets();
|
||||
Stickers::Order result;
|
||||
for (int32 i = 0, l = order.size(); i < l; ++i) {
|
||||
if (sets.constFind(order.at(i).v) == sets.cend()) {
|
||||
|
@ -4706,7 +4740,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
App::main()->updateStickers();
|
||||
} else {
|
||||
Global::SetStickerSetsOrder(result);
|
||||
Local::writeStickers();
|
||||
Local::writeInstalledStickers();
|
||||
emit stickersUpdated();
|
||||
}
|
||||
} break;
|
||||
|
@ -4716,6 +4750,24 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
App::main()->updateStickers();
|
||||
} 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
|
||||
case mtpc_updateSavedGifs: {
|
||||
cSetLastSavedGifsUpdate(0);
|
||||
|
|
|
@ -108,27 +108,6 @@ public:
|
|||
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 {
|
||||
SilentNotifiesDontChange,
|
||||
SilentNotifiesSetSilent,
|
||||
|
@ -224,6 +203,7 @@ public:
|
|||
bool mediaTypeSwitch();
|
||||
void showWideSection(const Window::SectionMemento &memento);
|
||||
void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1);
|
||||
bool stackIsEmpty() const;
|
||||
void showBackFromStack();
|
||||
void orderWidgets();
|
||||
QRect historyRect() const;
|
||||
|
@ -404,7 +384,7 @@ public:
|
|||
void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
|
||||
bool ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout);
|
||||
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();
|
||||
|
||||
void notify_botCommandsChanged(UserData *bot);
|
||||
|
@ -492,7 +472,7 @@ public slots:
|
|||
|
||||
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);
|
||||
|
||||
private slots:
|
||||
|
@ -518,6 +498,8 @@ private:
|
|||
Window::SectionSlideParams prepareOverviewAnimation();
|
||||
Window::SectionSlideParams prepareDialogsAnimation();
|
||||
|
||||
void saveSectionInStack();
|
||||
|
||||
bool _started = false;
|
||||
|
||||
uint64 failedObjId = 0;
|
||||
|
@ -597,7 +579,7 @@ private:
|
|||
ChildWidget<Window::TopBarWidget> _topBar;
|
||||
ConfirmBox *_forwardConfirm = nullptr; // for single column layout
|
||||
ChildWidget<HistoryHider> _hider = { nullptr };
|
||||
StackItems _stack;
|
||||
std_::vector_of_moveable<std_::unique_ptr<StackItem>> _stack;
|
||||
PeerData *_peerInStack = nullptr;
|
||||
MsgId _msgIdInStack = 0;
|
||||
|
||||
|
|
|
@ -1556,7 +1556,7 @@ void MediaView::paintEvent(QPaintEvent *e) {
|
|||
if (_saveMsgOpacity.current() > 0) {
|
||||
p.setOpacity(_saveMsgOpacity.current());
|
||||
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);
|
||||
textstyleSet(&st::medviewSaveAsTextStyle);
|
||||
|
|
|
@ -1060,8 +1060,17 @@ enum class MTPDstickerSet_ClientFlag : int32 {
|
|||
// sticker set is not yet loaded
|
||||
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
|
||||
MIN_FIELD = (1 << 30),
|
||||
MIN_FIELD = (1 << 27),
|
||||
};
|
||||
DEFINE_MTP_CLIENT_FLAGS(MTPDstickerSet)
|
||||
|
||||
|
|
|
@ -170,6 +170,7 @@ namespace {
|
|||
Global::SetPushChatLimit(data.vpush_chat_limit.v); // ?
|
||||
Global::SetSavedGifsLimit(data.vsaved_gifs_limit.v);
|
||||
Global::SetEditTimeLimit(data.vedit_time_limit.v); // ?
|
||||
Global::SetStickersRecentLimit(data.vstickers_recent_limit.v);
|
||||
|
||||
configLoadedOnce = true;
|
||||
Local::writeSettings();
|
||||
|
|
|
@ -351,13 +351,8 @@ void FileLoader::startLoading(bool loadFirst, bool prior) {
|
|||
|
||||
mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading)
|
||||
: FileLoader(QString(), size, UnknownFileLocation, LoadToCacheAsWell, fromCloud, autoLoading)
|
||||
, _lastComplete(false)
|
||||
, _skippedBytes(0)
|
||||
, _nextRequestOffset(0)
|
||||
, _dc(location->dc())
|
||||
, _location(location)
|
||||
, _id(0)
|
||||
, _access(0) {
|
||||
, _location(location) {
|
||||
LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0));
|
||||
if (i == queues.cend()) {
|
||||
i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries));
|
||||
|
@ -365,15 +360,12 @@ mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, L
|
|||
_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)
|
||||
, _lastComplete(false)
|
||||
, _skippedBytes(0)
|
||||
, _nextRequestOffset(0)
|
||||
, _dc(dc)
|
||||
, _location(0)
|
||||
, _id(id)
|
||||
, _access(access) {
|
||||
, _access(access)
|
||||
, _version(version) {
|
||||
LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0));
|
||||
if (i == queues.cend()) {
|
||||
i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries));
|
||||
|
@ -422,7 +414,7 @@ bool mtpFileLoader::loadPart() {
|
|||
switch (_locationType) {
|
||||
case VideoFileLocation:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +524,7 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
|
|||
|
||||
if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
|
||||
if (_locationType != UnknownFileLocation) { // audio, video, document
|
||||
MediaKey mkey = mediaKey(_locationType, _dc, _id);
|
||||
MediaKey mkey = mediaKey(_locationType, _dc, _id, _version);
|
||||
if (!_fname.isEmpty()) {
|
||||
Local::writeFileLocation(mkey, FileLocation(mtpToStorageType(_type), _fname));
|
||||
}
|
||||
|
@ -594,7 +586,7 @@ bool mtpFileLoader::tryLoadLocal() {
|
|||
_localTaskId = Local::startImageLoad(storageKey(*_location), this);
|
||||
} else {
|
||||
if (_toCache == LoadToCacheAsWell) {
|
||||
MediaKey mkey = mediaKey(_locationType, _dc, _id);
|
||||
MediaKey mkey = mediaKey(_locationType, _dc, _id, _version);
|
||||
if (_locationType == DocumentFileLocation) {
|
||||
_localTaskId = Local::startStickerImageLoad(mkey, this);
|
||||
} else if (_locationType == AudioFileLocation) {
|
||||
|
|
|
@ -28,6 +28,8 @@ namespace MTP {
|
|||
|
||||
enum LocationType {
|
||||
UnknownFileLocation = 0,
|
||||
// 1, 2, etc are used as "version" value in mediaKey() method.
|
||||
|
||||
DocumentFileLocation = 0x4e45abe9, // mtpc_inputDocumentFileLocation
|
||||
AudioFileLocation = 0x74dc404d, // mtpc_inputAudioFileLocation
|
||||
VideoFileLocation = 0x3d0364ec, // mtpc_inputVideoFileLocation
|
||||
|
@ -221,9 +223,8 @@ class mtpFileLoader : public FileLoader, public RPCSender {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
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;
|
||||
|
||||
|
@ -245,7 +246,6 @@ public:
|
|||
~mtpFileLoader();
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool tryLoadLocal();
|
||||
virtual void cancelRequests();
|
||||
|
||||
|
@ -256,15 +256,16 @@ protected:
|
|||
void partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req);
|
||||
bool partFailed(const RPCError &error);
|
||||
|
||||
bool _lastComplete;
|
||||
int32 _skippedBytes;
|
||||
int32 _nextRequestOffset;
|
||||
bool _lastComplete = false;
|
||||
int32 _skippedBytes = 0;
|
||||
int32 _nextRequestOffset = 0;
|
||||
|
||||
int32 _dc;
|
||||
const StorageImageLocation *_location;
|
||||
const StorageImageLocation *_location = nullptr;
|
||||
|
||||
uint64 _id; // for other locations
|
||||
uint64 _access;
|
||||
uint64 _id = 0; // for other locations
|
||||
uint64 _access = 0;
|
||||
int32 _version = 0;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto;
|
|||
|
||||
inputFileLocation#14637196 volume_id:long local_id:int secret: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;
|
||||
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;
|
||||
updateReadChannelOutbox#25d6c9c7 channel_id:int max_id:int = 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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -454,7 +456,7 @@ inputDocumentEmpty#72f0eaae = InputDocument;
|
|||
inputDocument#18798952 id:long access_hash:long = InputDocument;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -547,13 +549,13 @@ chatInviteEmpty#69df3769 = ExportedChatInvite;
|
|||
chatInviteExported#fc2e05bc link:string = ExportedChatInvite;
|
||||
|
||||
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;
|
||||
inputStickerSetID#9de7a269 id:long access_hash:long = 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;
|
||||
|
||||
|
@ -670,7 +672,7 @@ auth.sentCodeTypeSms#c000bba2 length:int = auth.SentCodeType;
|
|||
auth.sentCodeTypeCall#5353e5a7 length:int = 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;
|
||||
|
||||
|
@ -696,6 +698,19 @@ contacts.topPeers#70b772a8 categories:Vector<TopPeerCategoryPeers> chats:Vector<
|
|||
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;
|
||||
|
||||
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---
|
||||
|
||||
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.importChatInvite#6c50051c hash:string = Updates;
|
||||
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.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>;
|
||||
|
@ -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.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.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.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.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.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.updatePinnedMessage#a72ded52 flags:# silent:flags.0?true channel:InputChannel id:int = Updates;
|
||||
|
||||
// LAYER 53
|
||||
// LAYER 54
|
||||
|
|
|
@ -828,6 +828,7 @@ void _serialize_inputDocumentFileLocation(MTPStringLogger &to, int32 stage, int3
|
|||
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 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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
if (stage) {
|
||||
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 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 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;
|
||||
}
|
||||
}
|
||||
|
@ -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 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 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;
|
||||
}
|
||||
}
|
||||
|
@ -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 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 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;
|
||||
}
|
||||
}
|
||||
|
@ -4386,7 +4400,7 @@ void _serialize_stickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &t
|
|||
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 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 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;
|
||||
|
@ -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 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 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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
if (stage) {
|
||||
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) {
|
||||
if (stage) {
|
||||
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 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 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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
if (stage) {
|
||||
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) {
|
||||
if (stage) {
|
||||
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) {
|
||||
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_updateReadChannelOutbox, _serialize_updateReadChannelOutbox);
|
||||
_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_differenceEmpty, _serialize_updates_differenceEmpty);
|
||||
_serializers.insert(mtpc_updates_difference, _serialize_updates_difference);
|
||||
|
@ -8680,6 +8855,14 @@ namespace {
|
|||
_serializers.insert(mtpc_contacts_topPeers, _serialize_contacts_topPeers);
|
||||
_serializers.insert(mtpc_draftMessageEmpty, _serialize_draftMessageEmpty);
|
||||
_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_DH_params, _serialize_req_DH_params);
|
||||
|
@ -8731,7 +8914,6 @@ namespace {
|
|||
_serializers.insert(mtpc_messages_discardEncryption, _serialize_messages_discardEncryption);
|
||||
_serializers.insert(mtpc_messages_setEncryptedTyping, _serialize_messages_setEncryptedTyping);
|
||||
_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_editChatAdmin, _serialize_messages_editChatAdmin);
|
||||
_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_setBotCallbackAnswer, _serialize_messages_setBotCallbackAnswer);
|
||||
_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_saveBigFilePart, _serialize_upload_saveBigFilePart);
|
||||
_serializers.insert(mtpc_help_saveAppLog, _serialize_help_saveAppLog);
|
||||
|
@ -8836,6 +9021,7 @@ namespace {
|
|||
_serializers.insert(mtpc_channels_exportInvite, _serialize_channels_exportInvite);
|
||||
_serializers.insert(mtpc_messages_checkChatInvite, _serialize_messages_checkChatInvite);
|
||||
_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_searchGifs, _serialize_messages_searchGifs);
|
||||
_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_getBotCallbackAnswer, _serialize_messages_getBotCallbackAnswer);
|
||||
_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_getDifference, _serialize_updates_getDifference);
|
||||
_serializers.insert(mtpc_updates_getChannelDifference, _serialize_updates_getChannelDifference);
|
||||
|
|
|
@ -467,7 +467,7 @@ void CoverWidget::onOnlineCountUpdated(int onlineCount) {
|
|||
}
|
||||
|
||||
void CoverWidget::onSendMessage() {
|
||||
Ui::showPeerHistory(_peer, ShowAtUnreadMsgId);
|
||||
Ui::showPeerHistory(_peer, ShowAtUnreadMsgId, Ui::ShowWay::Forward);
|
||||
}
|
||||
|
||||
void CoverWidget::onShareContact() {
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace Serialize {
|
|||
|
||||
void Document::writeToStream(QDataStream &stream, DocumentData *document) {
|
||||
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 << qint32(document->dimensions.width()) << qint32(document->dimensions.height());
|
||||
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;
|
||||
QString name, mime;
|
||||
qint32 date, dc, size, width, height, type;
|
||||
qint32 date, dc, size, width, height, type, version;
|
||||
stream >> id >> access >> date;
|
||||
if (streamAppVersion >= 9061) {
|
||||
stream >> version;
|
||||
} else {
|
||||
version = 0;
|
||||
}
|
||||
stream >> name >> mime >> dc >> size;
|
||||
stream >> width >> height;
|
||||
stream >> type;
|
||||
|
@ -87,7 +93,7 @@ DocumentData *Document::readFromStreamHelper(QDataStream &stream, const StickerS
|
|||
if (typeOfSet == StickerSetTypeEmpty) {
|
||||
attributes.push_back(MTP_documentAttributeSticker(MTP_string(alt), MTP_inputStickerSetEmpty()));
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
@ -122,22 +128,22 @@ DocumentData *Document::readFromStreamHelper(QDataStream &stream, const StickerS
|
|||
if (!dc && !access) {
|
||||
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) {
|
||||
return readFromStreamHelper(stream, &info);
|
||||
DocumentData *Document::readStickerFromStream(int streamAppVersion, QDataStream &stream, const StickerSetInfo &info) {
|
||||
return readFromStreamHelper(streamAppVersion, stream, &info);
|
||||
}
|
||||
|
||||
DocumentData *Document::readFromStream(QDataStream &stream) {
|
||||
return readFromStreamHelper(stream, nullptr);
|
||||
DocumentData *Document::readFromStream(int streamAppVersion, QDataStream &stream) {
|
||||
return readFromStreamHelper(streamAppVersion, stream, nullptr);
|
||||
}
|
||||
|
||||
int Document::sizeInStream(DocumentData *document) {
|
||||
int result = 0;
|
||||
|
||||
// id + access + date
|
||||
result += sizeof(quint64) + sizeof(quint64) + sizeof(qint32);
|
||||
// id + access + date + version
|
||||
result += sizeof(quint64) + sizeof(quint64) + sizeof(qint32) + sizeof(qint32);
|
||||
// + namelen + name + mimelen + mime + dc + size
|
||||
result += stringSize(document->name) + stringSize(document->mime) + sizeof(qint32) + sizeof(qint32);
|
||||
// + width + height
|
||||
|
|
|
@ -39,12 +39,12 @@ public:
|
|||
};
|
||||
|
||||
static void writeToStream(QDataStream &stream, DocumentData *document);
|
||||
static DocumentData *readStickerFromStream(QDataStream &stream, const StickerSetInfo &info);
|
||||
static DocumentData *readFromStream(QDataStream &stream);
|
||||
static DocumentData *readStickerFromStream(int streamAppVersion, QDataStream &stream, const StickerSetInfo &info);
|
||||
static DocumentData *readFromStream(int streamAppVersion, QDataStream &stream);
|
||||
static int sizeInStream(DocumentData *document);
|
||||
|
||||
private:
|
||||
static DocumentData *readFromStreamHelper(QDataStream &stream, const StickerSetInfo *info);
|
||||
static DocumentData *readFromStreamHelper(int streamAppVersion, QDataStream &stream, const StickerSetInfo *info);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -849,16 +849,10 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) {
|
|||
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onSwitchModerateMode()));
|
||||
Ui::showLayer(box.release());
|
||||
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 (
|
||||
qsl("debugmode").startsWith(str) ||
|
||||
qsl("testmode").startsWith(str) ||
|
||||
qsl("loadlang").startsWith(str) ||
|
||||
qsl("clearstickers").startsWith(str) ||
|
||||
qsl("moderate").startsWith(str) ||
|
||||
qsl("debugfiles").startsWith(str) ||
|
||||
qsl("workmode").startsWith(str) ||
|
||||
|
@ -1267,24 +1261,6 @@ void SettingsInner::onShowSessions() {
|
|||
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() {
|
||||
Global::SetModerateModeEnabled(!Global::ModerateModeEnabled());
|
||||
Local::writeUserSettings();
|
||||
|
|
|
@ -187,7 +187,6 @@ public slots:
|
|||
void onUpdateLocalStorage();
|
||||
|
||||
private slots:
|
||||
void onClearStickers();
|
||||
void onSwitchModerateMode();
|
||||
|
||||
void onAskQuestion();
|
||||
|
|
|
@ -889,13 +889,13 @@ bool StickerData::setInstalled() const {
|
|||
switch (set.type()) {
|
||||
case mtpc_inputStickerSetID: {
|
||||
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;
|
||||
case mtpc_inputStickerSetShortName: {
|
||||
QString name = qs(set.c_inputStickerSetShortName().vshort_name).toLower();
|
||||
for (auto it = Global::StickerSets().cbegin(), e = Global::StickerSets().cend(); it != e; ++it) {
|
||||
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;
|
||||
|
@ -1095,10 +1095,11 @@ VoiceData::~VoiceData() {
|
|||
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)
|
||||
, _dc(dc)
|
||||
, _access(accessHash)
|
||||
, _version(version)
|
||||
, _url(url) {
|
||||
setattributes(attributes);
|
||||
if (_dc && _access) {
|
||||
|
@ -1107,15 +1108,15 @@ DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, const QSt
|
|||
}
|
||||
|
||||
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) {
|
||||
return new DocumentData(id, dc, accessHash, QString(), attributes);
|
||||
DocumentData *DocumentData::create(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QVector<MTPDocumentAttribute> &attributes) {
|
||||
return new DocumentData(id, dc, accessHash, version, QString(), 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) {
|
||||
|
@ -1396,7 +1397,7 @@ void DocumentData::save(const QString &toFile, ActionOnLoad action, const FullMs
|
|||
if (!_access && !_url.isEmpty()) {
|
||||
_loader = new webFileLoader(_url, toFile, fromCloud, autoLoading);
|
||||
} 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(failed(FileLoader*,bool)), App::main(), SLOT(documentLoadFailed(FileLoader*,bool)));
|
||||
|
@ -1537,6 +1538,22 @@ void DocumentData::recountIsImage() {
|
|||
_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) {
|
||||
_dc = dc;
|
||||
_access = access;
|
||||
|
|
|
@ -1068,7 +1068,7 @@ class Document;
|
|||
class DocumentData {
|
||||
public:
|
||||
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);
|
||||
|
||||
void setattributes(const QVector<MTPDocumentAttribute> &attributes);
|
||||
|
@ -1159,6 +1159,7 @@ public:
|
|||
_data = data;
|
||||
}
|
||||
|
||||
bool setRemoteVersion(int32 version); // Returns true if version has changed.
|
||||
void setRemoteLocation(int32 dc, uint64 access);
|
||||
void setContentUrl(const QString &url);
|
||||
bool hasRemoteLocation() const {
|
||||
|
@ -1196,11 +1197,11 @@ public:
|
|||
int32 md5[8];
|
||||
|
||||
MediaKey mediaKey() const {
|
||||
return ::mediaKey(locationType(), _dc, id);
|
||||
return ::mediaKey(locationType(), _dc, id, _version);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -1208,9 +1209,10 @@ private:
|
|||
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;
|
||||
uint64 _access = 0;
|
||||
int32 _version = 0;
|
||||
QString _url;
|
||||
|
||||
FileLocation _location;
|
||||
|
|
|
@ -349,6 +349,7 @@ void BoxButton::setText(const QString &text) {
|
|||
_fullText = text;
|
||||
_textWidth = _st.font->width(_text);
|
||||
resizeToText();
|
||||
update();
|
||||
}
|
||||
|
||||
void BoxButton::resizeToText() {
|
||||
|
|
|
@ -487,8 +487,13 @@ typedef QPair<uint64, uint64> MediaKey;
|
|||
inline uint64 mediaMix32To64(int32 a, int32 b) {
|
||||
return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b));
|
||||
}
|
||||
inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id) {
|
||||
return MediaKey(mediaMix32To64(type, dc), id);
|
||||
// Old method, should not be used anymore.
|
||||
//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) {
|
||||
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
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) {
|
||||
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
|
||||
|
|
|
@ -228,7 +228,7 @@ void TopBarWidget::showAll() {
|
|||
}
|
||||
}
|
||||
if (h && !o && _clearSelection->isHidden()) {
|
||||
if (Adaptive::OneColumn()) {
|
||||
if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) {
|
||||
_info->setPeer(h);
|
||||
_info->show();
|
||||
} else {
|
||||
|
|
|
@ -1240,6 +1240,7 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\styles\style_basic.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_history.cpp" />
|
||||
<ClCompile Include="GeneratedFiles\styles\style_mediaview.cpp" />
|
||||
|
@ -1528,6 +1529,7 @@
|
|||
<ClInclude Include="GeneratedFiles\numbers.h" />
|
||||
<ClInclude Include="GeneratedFiles\styles\style_basic.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_history.h" />
|
||||
<ClInclude Include="GeneratedFiles\styles\style_mediaview.h" />
|
||||
|
@ -3030,6 +3032,7 @@
|
|||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling style %(Identity)...</Message>
|
||||
</CustomBuild>
|
||||
<CodegenStyleItem Include="Resources\basic_types.style" />
|
||||
<CodegenStyleItem Include="SourceFiles\boxes\boxes.style" />
|
||||
<CodegenStyleItem Include="SourceFiles\dialogs\dialogs.style" />
|
||||
<CodegenStyleItem Include="SourceFiles\history\history.style" />
|
||||
<CodegenStyleItem Include="SourceFiles\overview\overview.style" />
|
||||
|
|
|
@ -1446,6 +1446,9 @@
|
|||
<ClCompile Include="GeneratedFiles\Release\moc_media_clip_volume_controller.cpp">
|
||||
<Filter>GeneratedFiles\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\styles\style_boxes.cpp">
|
||||
<Filter>GeneratedFiles\styles</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SourceFiles\stdafx.h">
|
||||
|
@ -1727,6 +1730,9 @@
|
|||
<ClInclude Include="SourceFiles\ui\buttons\icon_button.h">
|
||||
<Filter>SourceFiles\ui\buttons</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GeneratedFiles\styles\style_boxes.h">
|
||||
<Filter>GeneratedFiles\styles</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="SourceFiles\application.h">
|
||||
|
@ -2122,10 +2128,13 @@
|
|||
<CodegenStyleItem Include="SourceFiles\media\view\mediaview.style">
|
||||
<Filter>SourceFiles\media\view</Filter>
|
||||
</CodegenStyleItem>
|
||||
<CodegenStyleItem Include="SourceFiles\boxes\boxes.style">
|
||||
<Filter>SourceFiles\boxes</Filter>
|
||||
</CodegenStyleItem>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Resources\winrc\Telegram.rc">
|
||||
<Filter>Resources\winrc</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -2531,7 +2531,7 @@
|
|||
SDKROOT = macosx;
|
||||
SYMROOT = ./../Mac;
|
||||
TDESKTOP_MAJOR_VERSION = 0.9;
|
||||
TDESKTOP_VERSION = 0.9.60;
|
||||
TDESKTOP_VERSION = 0.9.61;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
@ -2672,7 +2672,7 @@
|
|||
SDKROOT = macosx;
|
||||
SYMROOT = ./../Mac;
|
||||
TDESKTOP_MAJOR_VERSION = 0.9;
|
||||
TDESKTOP_VERSION = 0.9.60;
|
||||
TDESKTOP_VERSION = 0.9.61;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AppVersion 9060
|
||||
AppVersion 9061
|
||||
AppVersionStrMajor 0.9
|
||||
AppVersionStrSmall 0.9.60
|
||||
AppVersionStr 0.9.60
|
||||
AlphaChannel 1
|
||||
AppVersionStrSmall 0.9.61
|
||||
AppVersionStr 0.9.61
|
||||
AlphaChannel 0
|
||||
BetaVersion 0
|
||||
|
|