Common groups profile block done. Moved to layer 59.

Also profile block modules were renamed.
This commit is contained in:
John Preston 2016-10-24 00:03:10 +03:00
parent a3c406dd00
commit 7bb3b4d807
47 changed files with 4539 additions and 1041 deletions

View File

@ -434,6 +434,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_profile_create_public_link" = "Create public link";
"lng_profile_edit_public_link" = "Edit public link";
"lng_profile_manage_admins" = "Manage administrators";
"lng_profile_common_groups" = "{count:_not_used_|# group|# groups} in common";
"lng_profile_common_groups_section" = "Groups in common";
"lng_profile_participants_section" = "Members";
"lng_profile_info_section" = "Info";
"lng_profile_mobile_number" = "Mobile:";

View File

@ -325,7 +325,10 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
}
void ApiWrap::gotUserFull(PeerData *peer, const MTPUserFull &result, mtpRequestId req) {
const auto &d(result.c_userFull());
auto user = peer->asUser();
t_assert(user != nullptr);
auto &d = result.c_userFull();
App::feedUsers(MTP_vector<MTPUser>(1, d.vuser));
if (d.has_profile_photo()) {
App::feedPhoto(d.vprofile_photo);
@ -336,12 +339,13 @@ void ApiWrap::gotUserFull(PeerData *peer, const MTPUserFull &result, mtpRequestI
}
if (d.has_bot_info()) {
peer->asUser()->setBotInfo(d.vbot_info);
user->setBotInfo(d.vbot_info);
} else {
peer->asUser()->setBotInfoVersion(-1);
user->setBotInfoVersion(-1);
}
peer->asUser()->setBlockStatus(d.is_blocked() ? UserData::BlockStatus::Blocked : UserData::BlockStatus::NotBlocked);
peer->asUser()->setAbout(d.has_about() ? qs(d.vabout) : QString());
user->setBlockStatus(d.is_blocked() ? UserData::BlockStatus::Blocked : UserData::BlockStatus::NotBlocked);
user->setAbout(d.has_about() ? qs(d.vabout) : QString());
user->setCommonChatsCount(d.vcommon_chats_count.v);
if (req) {
QMap<PeerData*, mtpRequestId>::iterator i = _fullPeerRequests.find(peer);
@ -422,15 +426,15 @@ void ApiWrap::requestBots(ChannelData *peer) {
void ApiWrap::gotChat(PeerData *peer, const MTPmessages_Chats &result) {
_peerRequests.remove(peer);
if (result.type() == mtpc_messages_chats) {
const auto &v(result.c_messages_chats().vchats.c_vector().v);
if (auto chats = Api::getChatsFromMessagesChats(result)) {
auto &v = chats->c_vector().v;
bool badVersion = false;
if (peer->isChat()) {
badVersion = (!v.isEmpty() && v.at(0).type() == mtpc_chat && v.at(0).c_chat().vversion.v < peer->asChat()->version);
} else if (peer->isChannel()) {
badVersion = (!v.isEmpty() && v.at(0).type() == mtpc_channel && v.at(0).c_chat().vversion.v < peer->asChannel()->version);
}
PeerData *chat = App::feedChats(result.c_messages_chats().vchats);
auto chat = App::feedChats(*chats);
if (chat == peer) {
if (badVersion) {
if (peer->isChat()) {
@ -453,9 +457,8 @@ void ApiWrap::gotUser(PeerData *peer, const MTPVector<MTPUser> &result) {
}
void ApiWrap::gotChats(const MTPmessages_Chats &result) {
if (result.type() == mtpc_messages_chats) {
auto &d = result.c_messages_chats();
App::feedChats(d.vchats);
if (auto chats = Api::getChatsFromMessagesChats(result)) {
App::feedChats(*chats);
}
}

View File

@ -22,6 +22,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "core/single_timer.h"
namespace Api {
inline const MTPVector<MTPChat> *getChatsFromMessagesChats(const MTPmessages_Chats &chats) {
switch (chats.type()) {
case mtpc_messages_chats: return &chats.c_messages_chats().vchats;
case mtpc_messages_chatsSlice: return &chats.c_messages_chatsSlice().vchats;
}
return nullptr;
}
} // namespace Api
class ApiWrap : public QObject, public RPCSender {
Q_OBJECT

View File

@ -1513,6 +1513,7 @@ namespace {
return page;
} break;
case mtpc_webPagePending: return App::feedWebPage(webpage.c_webPagePending());
case mtpc_webPageNotModified: LOG(("API Error: webPageNotModified is unexpected in feedWebPage().")); break;
}
return nullptr;
}

View File

@ -1255,9 +1255,8 @@ void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selecte
}
void RevokePublicLinkBox::getPublicDone(const MTPmessages_Chats &result) {
if (result.type() == mtpc_messages_chats) {
auto &chats = result.c_messages_chats().vchats;
for_const (auto &chat, chats.c_vector().v) {
if (auto chats = Api::getChatsFromMessagesChats(result)) {
for_const (auto &chat, chats->c_vector().v) {
if (auto peer = App::feedChat(chat)) {
if (!peer->isChannel() || peer->userName().isEmpty()) continue;

View File

@ -999,8 +999,8 @@ void shareGameScoreByHash(const QString &hash) {
auto requestChannelIds = MTP_vector<MTPInputChannel>(1, MTP_inputChannel(MTP_int(channelId), MTP_long(channelAccessHash)));
auto requestChannel = MTPchannels_GetChannels(requestChannelIds);
MTP::send(requestChannel, rpcDone([channelId, resolveMessageAndShareScore](const MTPmessages_Chats &result) {
if (result.type() == mtpc_messages_chats) {
App::feedChats(result.c_messages_chats().vchats);
if (auto chats = Api::getChatsFromMessagesChats(result)) {
App::feedChats(*chats);
}
if (auto channel = App::channelLoaded(channelId)) {
resolveMessageAndShareScore(channel);

View File

@ -393,18 +393,23 @@ public:
namespace internal {
template <typename FunctionType>
struct lambda_type_helper;
template <typename FunctionType>
struct lambda_type_resolver;
template <typename Lambda, typename R, typename ...Args>
struct lambda_type_helper<R(Lambda::*)(Args...) const> {
using type = lambda<R(Args...)>;
};
template <typename Lambda, typename R, typename ...Args>
struct lambda_type_resolver<R(Lambda::*)(Args...) const> {
using type = lambda<R(Args...)>;
};
template <typename FunctionType>
struct lambda_type_helper {
using type = typename lambda_type_resolver<decltype(&FunctionType::operator())>::type;
};
} // namespace internal
template <typename FunctionType>
using lambda_type = typename internal::lambda_type_helper<decltype(&FunctionType::operator())>::type;
using lambda_type = typename internal::lambda_type_helper<FunctionType>::type;
// Guard lambda call by one or many QObject* weak pointers.
@ -489,6 +494,11 @@ struct lambda_guard_type_helper {
template <typename ...PointersAndLambda>
using lambda_guard_t = typename lambda_guard_type_helper<PointersAndLambda...>::type;
template <int N, typename Lambda>
struct lambda_type_helper<lambda_guard<N, Lambda>> {
using type = typename lambda_type_helper<Lambda>::type;
};
} // namespace internal
template <typename ...PointersAndLambda>

View File

@ -190,12 +190,6 @@ bool History::updateSendActionNeedsAnimating(UserData *user, const MTPSendMessag
if (action.type() == mtpc_sendMessageCancelAction) {
unregSendAction(user);
return false;
} else if (action.type() == mtpc_sendMessageGameStopAction) {
auto it = _sendActions.find(user);
if (it != _sendActions.end() && it->type == Type::PlayGame) {
unregSendAction(user);
}
return false;
}
auto ms = getms();
@ -251,12 +245,6 @@ bool History::paintSendAction(Painter &p, int x, int y, int availableWidth, int
availableWidth -= animationWidth;
p.setPen(color);
_sendActionText.drawElided(p, x, y, availableWidth);
// App::histories().sendActionAnimationUpdated().notify({
// this,
// animationWidth,
// st::normalFont->height,
// false
// });
return true;
}
return false;
@ -393,8 +381,11 @@ void ChannelHistory::getRangeDifference() {
void ChannelHistory::getRangeDifferenceNext(int32 pts) {
if (!App::main() || _rangeDifferenceToId < _rangeDifferenceFromId) return;
int32 limit = _rangeDifferenceToId + 1 - _rangeDifferenceFromId;
_rangeDifferenceRequestId = MTP::send(MTPupdates_GetChannelDifference(peer->asChannel()->inputChannel, MTP_channelMessagesFilter(MTP_flags(MTPDchannelMessagesFilter::Flags(0)), MTP_vector<MTPMessageRange>(1, MTP_messageRange(MTP_int(_rangeDifferenceFromId), MTP_int(_rangeDifferenceToId)))), MTP_int(pts), MTP_int(limit)), App::main()->rpcDone(&MainWidget::gotRangeDifference, peer->asChannel()));
int limit = _rangeDifferenceToId + 1 - _rangeDifferenceFromId;
auto filter = MTP_channelMessagesFilter(MTP_flags(MTPDchannelMessagesFilter::Flags(0)), MTP_vector<MTPMessageRange>(1, MTP_messageRange(MTP_int(_rangeDifferenceFromId), MTP_int(_rangeDifferenceToId))));
MTPupdates_GetChannelDifference::Flags flags = MTPupdates_GetChannelDifference::Flag::f_force;
_rangeDifferenceRequestId = MTP::send(MTPupdates_GetChannelDifference(MTP_flags(flags), peer->asChannel()->inputChannel, filter, MTP_int(pts), MTP_int(limit)), App::main()->rpcDone(&MainWidget::gotRangeDifference, peer->asChannel()));
}
HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) {
@ -788,6 +779,7 @@ HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction,
case mtpc_webPage:
case mtpc_webPageEmpty:
case mtpc_webPagePending: break;
case mtpc_webPageNotModified:
default: badMedia = 1; break;
}
break;

View File

@ -83,10 +83,10 @@ public:
}
struct SendActionAnimationUpdate {
History *history = nullptr;
int width = 0;
int height = 0;
bool textUpdated = 0;
History *history;
int width;
int height;
bool textUpdated;
};
base::Observable<SendActionAnimationUpdate> &sendActionAnimationUpdated() {
return _sendActionAnimationUpdated;

View File

@ -687,6 +687,7 @@ void HistoryMessage::initMedia(const MTPMessageMedia *media) {
case mtpc_webPage: {
_media.reset(new HistoryWebPage(this, App::feedWebPage(d.c_webPage())));
} break;
case mtpc_webPageNotModified: LOG(("API Error: webPageNotModified is unexpected in message media.")); break;
}
} break;
case mtpc_messageMediaGame: {

View File

@ -39,7 +39,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_service_layout.h"
#include "history/history_media_types.h"
#include "history/history_drag_area.h"
#include "profile/profile_members_widget.h"
#include "profile/profile_block_group_members.h"
#include "core/click_handler_types.h"
#include "stickers/emoji_pan.h"
#include "lang.h"
@ -6266,7 +6266,7 @@ void HistoryWidget::setMembersShowAreaActive(bool active) {
void HistoryWidget::onMembersDropdownShow() {
if (!_membersDropdown) {
_membersDropdown.create(this, st::membersInnerDropdown);
_membersDropdown->setOwnedWidget(new Profile::MembersWidget(_membersDropdown, _peer, Profile::MembersWidget::TitleVisibility::Hidden));
_membersDropdown->setOwnedWidget(new Profile::GroupMembersWidget(_membersDropdown, _peer, Profile::GroupMembersWidget::TitleVisibility::Hidden));
_membersDropdown->resizeToWidth(st::membersInnerWidth);
_membersDropdown->setMaxHeight(countMembersDropdownHeightMax());

View File

@ -3291,12 +3291,12 @@ void MainWidget::gotState(const MTPupdates_State &state) {
updateOnline();
}
void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
void MainWidget::gotDifference(const MTPupdates_Difference &difference) {
_failDifferenceTimeout = 1;
switch (diff.type()) {
switch (difference.type()) {
case mtpc_updates_differenceEmpty: {
const auto &d(diff.c_updates_differenceEmpty());
auto &d = difference.c_updates_differenceEmpty();
updSetState(_ptsWaiter.current(), d.vdate.v, updQts, d.vseq.v);
_lastUpdateTime = getms(true);
@ -3305,10 +3305,10 @@ void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
_ptsWaiter.setRequesting(false);
} break;
case mtpc_updates_differenceSlice: {
const auto &d(diff.c_updates_differenceSlice());
auto &d = difference.c_updates_differenceSlice();
feedDifference(d.vusers, d.vchats, d.vnew_messages, d.vother_updates);
const auto &s(d.vintermediate_state.c_updates_state());
auto &s = d.vintermediate_state.c_updates_state();
updSetState(s.vpts.v, s.vdate.v, s.vqts.v, s.vseq.v);
_ptsWaiter.setRequesting(false);
@ -3317,11 +3317,15 @@ void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
getDifference();
} break;
case mtpc_updates_difference: {
const auto &d(diff.c_updates_difference());
auto &d = difference.c_updates_difference();
feedDifference(d.vusers, d.vchats, d.vnew_messages, d.vother_updates);
gotState(d.vstate);
} break;
case mtpc_updates_differenceTooLong: {
auto &d = difference.c_updates_differenceTooLong();
LOG(("API Error: updates.differenceTooLong is not supported by Telegram Desktop!"));
} break;
};
}
@ -3444,7 +3448,7 @@ void MainWidget::onGetDifferenceTimeByPts() {
wait = wait ? qMin(wait, i.value() - now) : (i.value() - now);
++i;
} else {
getChannelDifference(i.key(), GetChannelDifferenceFromPtsGap);
getChannelDifference(i.key(), ChannelDifferenceRequest::PtsGapOrShortPoll);
i = _channelGetDifferenceTimeByPts.erase(i);
}
}
@ -3473,7 +3477,7 @@ void MainWidget::onGetDifferenceTimeAfterFail() {
wait = wait ? qMin(wait, i.value() - now) : (i.value() - now);
++i;
} else {
getChannelDifference(i.key(), GetChannelDifferenceFromFail);
getChannelDifference(i.key(), ChannelDifferenceRequest::AfterFail);
i = _channelGetDifferenceTimeAfterFail.erase(i);
}
}
@ -3498,26 +3502,34 @@ void MainWidget::getDifference() {
_getDifferenceTimeAfterFail = 0;
_ptsWaiter.setRequesting(true);
MTP::send(MTPupdates_GetDifference(MTP_int(_ptsWaiter.current()), MTP_int(updDate), MTP_int(updQts)), rpcDone(&MainWidget::gotDifference), rpcFail(&MainWidget::failDifference));
MTPupdates_GetDifference::Flags flags = 0;
MTP::send(MTPupdates_GetDifference(MTP_flags(flags), MTP_int(_ptsWaiter.current()), MTPint(), MTP_int(updDate), MTP_int(updQts)), rpcDone(&MainWidget::gotDifference), rpcFail(&MainWidget::failDifference));
}
void MainWidget::getChannelDifference(ChannelData *channel, GetChannelDifferenceFrom from) {
void MainWidget::getChannelDifference(ChannelData *channel, ChannelDifferenceRequest from) {
if (this != App::main() || !channel) return;
if (from != GetChannelDifferenceFromPtsGap) {
if (from != ChannelDifferenceRequest::PtsGapOrShortPoll) {
_channelGetDifferenceTimeByPts.remove(channel);
}
if (!channel->ptsInited() || channel->ptsRequesting()) return;
if (from != GetChannelDifferenceFromFail) {
if (from != ChannelDifferenceRequest::AfterFail) {
_channelGetDifferenceTimeAfterFail.remove(channel);
}
channel->ptsSetRequesting(true);
auto filter = MTP_channelMessagesFilterEmpty();
MTP::send(MTPupdates_GetChannelDifference(channel->inputChannel, filter, MTP_int(channel->pts()), MTP_int(MTPChannelGetDifferenceLimit)), rpcDone(&MainWidget::gotChannelDifference, channel), rpcFail(&MainWidget::failChannelDifference, channel));
MTPupdates_GetChannelDifference::Flags flags = MTPupdates_GetChannelDifference::Flag::f_force;
if (from != ChannelDifferenceRequest::PtsGapOrShortPoll) {
if (!channel->ptsWaitingForSkipped()) {
flags = 0; // No force flag when requesting for short poll.
}
}
MTP::send(MTPupdates_GetChannelDifference(MTP_flags(flags), channel->inputChannel, filter, MTP_int(channel->pts()), MTP_int(MTPChannelGetDifferenceLimit)), rpcDone(&MainWidget::gotChannelDifference, channel), rpcFail(&MainWidget::failChannelDifference, channel));
}
void MainWidget::mtpPing() {
@ -4897,6 +4909,29 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
}
} break;
case mtpc_updateChannelWebPage: {
auto &d = update.c_updateChannelWebPage();
auto channel = App::channelLoaded(d.vchannel_id.v);
if (channel && !_handlingChannelDifference) {
if (channel->ptsRequesting()) { // skip global updates while getting channel difference
return;
} else if (!channel->ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
return;
}
}
// update before applying skipped
App::feedWebPage(d.vwebpage);
_history->updatePreview();
webPagesOrGamesUpdate();
if (channel && !_handlingChannelDifference) {
channel->ptsApplySkippedUpdates();
}
} break;
case mtpc_updateDeleteChannelMessages: {
auto &d = update.c_updateDeleteChannelMessages();
auto channel = App::channelLoaded(d.vchannel_id.v);

View File

@ -535,12 +535,12 @@ private:
SingleTimer _updateMutedTimer;
enum GetChannelDifferenceFrom {
GetChannelDifferenceFromUnknown,
GetChannelDifferenceFromPtsGap,
GetChannelDifferenceFromFail,
enum class ChannelDifferenceRequest {
Unknown,
PtsGapOrShortPoll,
AfterFail,
};
void getChannelDifference(ChannelData *channel, GetChannelDifferenceFrom from = GetChannelDifferenceFromUnknown);
void getChannelDifference(ChannelData *channel, ChannelDifferenceRequest from = ChannelDifferenceRequest::Unknown);
void gotDifference(const MTPupdates_Difference &diff);
bool failDifference(const RPCError &e);
void feedDifference(const MTPVector<MTPUser> &users, const MTPVector<MTPChat> &chats, const MTPVector<MTPMessage> &msgs, const MTPVector<MTPUpdate> &other);

View File

@ -300,7 +300,7 @@ inputReportReasonViolence#1e22c78d = ReportReason;
inputReportReasonPornography#2e59d922 = ReportReason;
inputReportReasonOther#e1746d0a text:string = ReportReason;
userFull#5932fc03 flags:# blocked:flags.0?true user:User about:flags.1?string link:contacts.Link profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo = UserFull;
userFull#f220f3f flags:# blocked:flags.0?true user:User about:flags.1?string link:contacts.Link profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo common_chats_count:int = UserFull;
contact#f911c994 user_id:int mutual:Bool = Contact;
@ -328,6 +328,7 @@ messages.messagesSlice#b446ae3 count:int messages:Vector<Message> chats:Vector<C
messages.channelMessages#99262e37 flags:# pts:int count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.chats#64ff9fd5 chats:Vector<Chat> = messages.Chats;
messages.chatsSlice#78f69146 count:int chats:Vector<Chat> users:Vector<User> = messages.Chats;
messages.chatFull#e5d7d19c full_chat:ChatFull chats:Vector<Chat> users:Vector<User> = messages.ChatFull;
@ -398,12 +399,14 @@ updateReadFeaturedStickers#571d2742 = Update;
updateRecentStickers#9a422c20 = Update;
updateConfig#a229dd06 = Update;
updatePtsChanged#3354678f = Update;
updateChannelWebPage#40771900 channel_id:int webpage:WebPage pts:int pts_count:int = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
updates.difference#f49ca0 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference;
updates.differenceSlice#a8fb1981 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> intermediate_state:updates.State = updates.Difference;
updates.differenceTooLong#4afe8f6d pts:int = updates.Difference;
updatesTooLong#e317af7e = Updates;
updateShortMessage#914fbf11 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true id:int user_id:int message:string pts:int pts_count:int date:int fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int entities:flags.7?Vector<MessageEntity> = Updates;
@ -480,7 +483,6 @@ sendMessageUploadDocumentAction#aa0cd9e4 progress:int = SendMessageAction;
sendMessageGeoLocationAction#176f8ba1 = SendMessageAction;
sendMessageChooseContactAction#628cbc6f = SendMessageAction;
sendMessageGamePlayAction#dd6a8f48 = SendMessageAction;
sendMessageGameStopAction#15c2c99a = SendMessageAction;
contacts.found#1aa1f784 results:Vector<Peer> chats:Vector<Chat> users:Vector<User> = contacts.Found;
@ -535,7 +537,8 @@ contactLinkContact#d502c2d0 = ContactLink;
webPageEmpty#eb1477e8 id:long = WebPage;
webPagePending#c586da1c id:long date:int = WebPage;
webPage#ca820ed7 flags:# id:long url:string display_url:string type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document = WebPage;
webPage#5f07b4bc flags:# id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page = WebPage;
webPageNotModified#85849473 = WebPage;
authorization#7bf2e6f6 hash:long flags:int device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
@ -667,7 +670,7 @@ botInlineMessageMediaContact#35edb4d4 flags:# phone_number:string first_name:str
botInlineResult#9bebaeb9 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:BotInlineMessage = BotInlineResult;
botInlineMediaResult#17db940b flags:# id:string type:string photo:flags.0?Photo document:flags.1?Document title:flags.2?string description:flags.3?string send_message:BotInlineMessage = BotInlineResult;
messages.botResults#256709a6 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM results:Vector<BotInlineResult> = messages.BotResults;
messages.botResults#ccd3563d flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM results:Vector<BotInlineResult> cache_time:int = messages.BotResults;
exportedMessageLink#1f486803 link:string = ExportedMessageLink;
@ -682,7 +685,7 @@ auth.sentCodeTypeSms#c000bba2 length:int = auth.SentCodeType;
auth.sentCodeTypeCall#5353e5a7 length:int = auth.SentCodeType;
auth.sentCodeTypeFlashCall#ab03c6d9 pattern:string = auth.SentCodeType;
messages.botCallbackAnswer#b10df1fb flags:# alert:flags.1?true has_url:flags.3?true message:flags.0?string url:flags.2?string = messages.BotCallbackAnswer;
messages.botCallbackAnswer#36585ea4 flags:# alert:flags.1?true has_url:flags.3?true message:flags.0?string url:flags.2?string cache_time:int = messages.BotCallbackAnswer;
messages.messageEditData#26b5dde6 flags:# caption:flags.0?true = messages.MessageEditData;
@ -736,6 +739,42 @@ highScore#58fffcd0 pos:int user_id:int score:int = HighScore;
messages.highScores#9a3bfd99 scores:Vector<HighScore> users:Vector<User> = messages.HighScores;
textEmpty#dc3d824f = RichText;
textPlain#744694e0 text:string = RichText;
textBold#6724abc4 text:RichText = RichText;
textItalic#d912a59c text:RichText = RichText;
textUnderline#c12622c4 text:RichText = RichText;
textStrike#9bf8bb95 text:RichText = RichText;
textFixed#6c3f19b9 text:RichText = RichText;
textUrl#3c2884c1 text:RichText url:string webpage_id:long = RichText;
textEmail#de5a0dd6 text:RichText email:string = RichText;
textConcat#7e6260d7 texts:Vector<RichText> = RichText;
pageBlockTitle#70abc3fd text:RichText = PageBlock;
pageBlockSubtitle#8ffa9a1f text:RichText = PageBlock;
pageBlockAuthorDate#3d5b64f2 author:string published_date:int = PageBlock;
pageBlockHeader#bfd064ec text:RichText = PageBlock;
pageBlockSubheader#f12bb6e1 text:RichText = PageBlock;
pageBlockParagraph#467a0766 text:RichText = PageBlock;
pageBlockPreformatted#c070d93e text:RichText language:string = PageBlock;
pageBlockFooter#48870999 text:RichText = PageBlock;
pageBlockDivider#db20b188 = PageBlock;
pageBlockList#3a58c7f4 ordered:Bool items:Vector<RichText> = PageBlock;
pageBlockBlockquote#263d7c26 text:RichText caption:RichText = PageBlock;
pageBlockPullquote#4f4456d3 text:RichText caption:RichText = PageBlock;
pageBlockPhoto#e9c69982 photo_id:long caption:RichText = PageBlock;
pageBlockVideo#d9d71866 flags:# autoplay:flags.1?true loop:flags.2?true video_id:long caption:RichText = PageBlock;
pageBlockCover#39f23300 cover:PageBlock = PageBlock;
pageBlockEmbed#36b0816 url:string w:int h:int caption:RichText = PageBlock;
pageBlockEmbedPost#7ff81db7 flags:# author:string date:int caption:RichText url:string webpage_id:long text:flags.1?RichText medias:flags.2?Vector<EmbedPostMedia> author_photo_id:flags.3?long = PageBlock;
pageBlockSlideshow#130c8963 items:Vector<PageBlock> caption:RichText = PageBlock;
embedPostPhoto#e31ee77 photo_id:long = EmbedPostMedia;
embedPostVideo#a07f2d66 video_id:long = EmbedPostMedia;
pagePart#8dee6c44 blocks:Vector<PageBlock> photos:Vector<Photo> videos:Vector<Document> = Page;
pageFull#d7a19d69 blocks:Vector<PageBlock> photos:Vector<Photo> videos:Vector<Document> = Page;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -867,7 +906,7 @@ 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#810a9fec flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes = messages.BotCallbackAnswer;
messages.setBotCallbackAnswer#c927d44b flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string = Bool;
messages.setBotCallbackAnswer#d58f130a flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string cache_time:int = 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;
@ -883,10 +922,13 @@ messages.setGameScore#8ef8ecc0 flags:# edit_message:flags.0?true peer:InputPeer
messages.setInlineGameScore#15ad9f64 flags:# edit_message:flags.0?true id:InputBotInlineMessageID user_id:InputUser score:int = Bool;
messages.getGameHighScores#e822649d peer:InputPeer id:int user_id:InputUser = messages.HighScores;
messages.getInlineGameHighScores#f635e1b id:InputBotInlineMessageID user_id:InputUser = messages.HighScores;
messages.getCommonChats#d0a48c4 user_id:InputUser max_id:int limit:int = messages.Chats;
messages.getAllChats#eba80ff0 except_ids:Vector<int> = messages.Chats;
messages.getWebPage#61203e2 id:long hash:int = WebPage;
updates.getState#edd4882a = updates.State;
updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference;
updates.getChannelDifference#bb32d7c0 channel:InputChannel filter:ChannelMessagesFilter pts:int limit:int = updates.ChannelDifference;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
updates.getChannelDifference#3173d78 flags:# force:flags.0?true channel:InputChannel filter:ChannelMessagesFilter pts:int limit:int = updates.ChannelDifference;
photos.updateProfilePhoto#f0bb5152 id:InputPhoto = UserProfilePhoto;
photos.uploadProfilePhoto#4f32c098 file:InputFile = photos.Photo;
@ -905,6 +947,7 @@ help.getInviteText#4d392343 = help.InviteText;
help.getSupport#9cdf08cd = help.Support;
help.getAppChangelog#b921197a = help.AppChangelog;
help.getTermsOfService#350170f3 = help.TermsOfService;
help.setBotUpdatesStatus#ec22cfcd pending_updates_count:int message:string = Bool;
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
@ -934,4 +977,4 @@ channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
channels.updatePinnedMessage#a72ded52 flags:# silent:flags.0?true channel:InputChannel id:int = Updates;
channels.getAdminedPublicChannels#8d8d82d7 = messages.Chats;
// LAYER 57
// LAYER 59

View File

@ -2062,6 +2062,7 @@ void _serialize_userFull(MTPStringLogger &to, int32 stage, int32 lev, Types &typ
case 5: to.add(" profile_photo: "); ++stages.back(); if (flag & MTPDuserFull::Flag::f_profile_photo) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 6: to.add(" notify_settings: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 7: to.add(" bot_info: "); ++stages.back(); if (flag & MTPDuserFull::Flag::f_bot_info) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
case 8: to.add(" common_chats_count: "); ++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;
}
}
@ -2294,6 +2295,21 @@ void _serialize_messages_chats(MTPStringLogger &to, int32 stage, int32 lev, Type
}
}
void _serialize_messages_chatsSlice(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_chatsSlice");
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(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" users: "); ++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_chatFull(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);
@ -3110,6 +3126,22 @@ void _serialize_updatePtsChanged(MTPStringLogger &to, int32 stage, int32 lev, Ty
to.add("{ updatePtsChanged }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_updateChannelWebPage(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("{ updateChannelWebPage");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" channel_id: "); ++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(" webpage: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" pts_count: "); ++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_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);
@ -3177,6 +3209,19 @@ void _serialize_updates_differenceSlice(MTPStringLogger &to, int32 stage, int32
}
}
void _serialize_updates_differenceTooLong(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("{ updates_differenceTooLong");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" pts: "); ++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_updatesTooLong(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ updatesTooLong }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
@ -3900,10 +3945,6 @@ void _serialize_sendMessageGamePlayAction(MTPStringLogger &to, int32 stage, int3
to.add("{ sendMessageGamePlayAction }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_sendMessageGameStopAction(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ sendMessageGameStopAction }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_contacts_found(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);
@ -4270,22 +4311,28 @@ void _serialize_webPage(MTPStringLogger &to, int32 stage, int32 lev, Types &type
case 1: 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 2: to.add(" url: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" display_url: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" type: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_type) { 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 5: to.add(" site_name: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_site_name) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
case 6: to.add(" title: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_title) { 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;
case 7: to.add(" description: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_description) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
case 8: to.add(" photo: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_photo) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 4 IN FIELD flags ]"); } break;
case 9: to.add(" embed_url: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_embed_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 5 IN FIELD flags ]"); } break;
case 10: to.add(" embed_type: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_embed_type) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 5 IN FIELD flags ]"); } break;
case 11: to.add(" embed_width: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_embed_width) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break;
case 12: to.add(" embed_height: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_embed_height) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break;
case 13: to.add(" duration: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_duration) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break;
case 14: to.add(" author: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_author) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 8 IN FIELD flags ]"); } break;
case 15: to.add(" document: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_document) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 9 IN FIELD flags ]"); } break;
case 4: 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 5: to.add(" type: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_type) { 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 6: to.add(" site_name: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_site_name) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
case 7: to.add(" title: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_title) { 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;
case 8: to.add(" description: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_description) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
case 9: to.add(" photo: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_photo) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 4 IN FIELD flags ]"); } break;
case 10: to.add(" embed_url: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_embed_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 5 IN FIELD flags ]"); } break;
case 11: to.add(" embed_type: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_embed_type) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 5 IN FIELD flags ]"); } break;
case 12: to.add(" embed_width: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_embed_width) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break;
case 13: to.add(" embed_height: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_embed_height) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break;
case 14: to.add(" duration: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_duration) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break;
case 15: to.add(" author: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_author) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 8 IN FIELD flags ]"); } break;
case 16: to.add(" document: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_document) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 9 IN FIELD flags ]"); } break;
case 17: to.add(" cached_page: "); ++stages.back(); if (flag & MTPDwebPage::Flag::f_cached_page) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 10 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_webPageNotModified(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ webPageNotModified }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_authorization(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);
@ -5647,6 +5694,7 @@ void _serialize_messages_botResults(MTPStringLogger &to, int32 stage, int32 lev,
case 3: to.add(" next_offset: "); ++stages.back(); if (flag & MTPDmessages_botResults::Flag::f_next_offset) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
case 4: to.add(" switch_pm: "); ++stages.back(); if (flag & MTPDmessages_botResults::Flag::f_switch_pm) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 5: to.add(" results: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" cache_time: "); ++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;
}
}
@ -5762,6 +5810,7 @@ void _serialize_messages_botCallbackAnswer(MTPStringLogger &to, int32 stage, int
case 2: to.add(" has_url: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_has_url) { to.add("YES [ BY BIT 3 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
case 3: 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 4: 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;
case 5: to.add(" cache_time: "); ++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;
}
}
@ -6137,6 +6186,437 @@ void _serialize_messages_highScores(MTPStringLogger &to, int32 stage, int32 lev,
}
}
void _serialize_textEmpty(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ textEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_textPlain(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("{ textPlain");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string+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_textBold(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("{ textBold");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_textItalic(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("{ textItalic");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_textUnderline(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("{ textUnderline");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_textStrike(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("{ textStrike");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_textFixed(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("{ textFixed");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_textUrl(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("{ textUrl");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" url: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" webpage_id: "); ++stages.back(); types.push_back(mtpc_long+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_textEmail(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("{ textEmail");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" email: "); ++stages.back(); types.push_back(mtpc_string+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_textConcat(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("{ textConcat");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" texts: "); ++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_pageBlockTitle(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("{ pageBlockTitle");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_pageBlockSubtitle(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("{ pageBlockSubtitle");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_pageBlockAuthorDate(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("{ pageBlockAuthorDate");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" author: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" published_date: "); ++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_pageBlockHeader(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("{ pageBlockHeader");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_pageBlockSubheader(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("{ pageBlockSubheader");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_pageBlockParagraph(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("{ pageBlockParagraph");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_pageBlockPreformatted(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("{ pageBlockPreformatted");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" language: "); ++stages.back(); types.push_back(mtpc_string+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_pageBlockFooter(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("{ pageBlockFooter");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++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_pageBlockDivider(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
to.add("{ pageBlockDivider }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
}
void _serialize_pageBlockList(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("{ pageBlockList");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" ordered: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" items: "); ++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_pageBlockBlockquote(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("{ pageBlockBlockquote");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" caption: "); ++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_pageBlockPullquote(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("{ pageBlockPullquote");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" caption: "); ++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_pageBlockPhoto(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("{ pageBlockPhoto");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" photo_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(" caption: "); ++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_pageBlockVideo(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
MTPDpageBlockVideo::Flags flag(iflag);
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ pageBlockVideo");
to.add("\n").addSpaces(lev);
}
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(" autoplay: "); ++stages.back(); if (flag & MTPDpageBlockVideo::Flag::f_autoplay) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
case 2: to.add(" loop: "); ++stages.back(); if (flag & MTPDpageBlockVideo::Flag::f_loop) { to.add("YES [ BY BIT 2 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 3: to.add(" video_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" caption: "); ++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_pageBlockCover(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("{ pageBlockCover");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: 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_pageBlockEmbed(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("{ pageBlockEmbed");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" url: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" w: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" h: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" caption: "); ++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_pageBlockEmbedPost(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
MTPDpageBlockEmbedPost::Flags flag(iflag);
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ pageBlockEmbedPost");
to.add("\n").addSpaces(lev);
}
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(" author: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" caption: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" url: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" webpage_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" text: "); ++stages.back(); if (flag & MTPDpageBlockEmbedPost::Flag::f_text) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
case 7: to.add(" medias: "); ++stages.back(); if (flag & MTPDpageBlockEmbedPost::Flag::f_medias) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 8: to.add(" author_photo_id: "); ++stages.back(); if (flag & MTPDpageBlockEmbedPost::Flag::f_author_photo_id) { types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
void _serialize_pageBlockSlideshow(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("{ pageBlockSlideshow");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" items: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" caption: "); ++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_embedPostPhoto(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("{ embedPostPhoto");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" photo_id: "); ++stages.back(); types.push_back(mtpc_long+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_embedPostVideo(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("{ embedPostVideo");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" video_id: "); ++stages.back(); types.push_back(mtpc_long+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_pagePart(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("{ pagePart");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" blocks: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" photos: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" videos: "); ++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_pageFull(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("{ pageFull");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" blocks: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" photos: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" videos: "); ++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_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);
@ -6747,6 +7227,7 @@ void _serialize_messages_setBotCallbackAnswer(MTPStringLogger &to, int32 stage,
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;
case 5: to.add(" cache_time: "); ++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;
}
}
@ -6881,6 +7362,20 @@ void _serialize_help_saveAppLog(MTPStringLogger &to, int32 stage, int32 lev, Typ
}
}
void _serialize_help_setBotUpdatesStatus(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("{ help_setBotUpdatesStatus");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" pending_updates_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(" message: "); ++stages.back(); types.push_back(mtpc_string+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_channels_readHistory(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);
@ -8175,6 +8670,34 @@ void _serialize_messages_getChats(MTPStringLogger &to, int32 stage, int32 lev, T
}
}
void _serialize_messages_getCommonChats(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_getCommonChats");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: 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_getAllChats(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_getAllChats");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" except_ids: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_int+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_channels_getChannels(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);
@ -8637,11 +9160,27 @@ void _serialize_messages_getInlineGameHighScores(MTPStringLogger &to, int32 stag
}
}
void _serialize_messages_getWebPage(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_getWebPage");
to.add("\n").addSpaces(lev);
}
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(" 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_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();
}
void _serialize_updates_getDifference(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
MTPupdates_getDifference::Flags flag(iflag);
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
@ -8649,14 +9188,18 @@ void _serialize_updates_getDifference(MTPStringLogger &to, int32 stage, int32 le
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" pts: "); ++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(" date: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" qts: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" pts_total_limit: "); ++stages.back(); if (flag & MTPupdates_getDifference::Flag::f_pts_total_limit) { types.push_back(mtpc_int+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(" date: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" qts: "); ++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_getChannelDifference(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
MTPupdates_getChannelDifference::Flags flag(iflag);
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
@ -8664,10 +9207,12 @@ void _serialize_updates_getChannelDifference(MTPStringLogger &to, int32 stage, i
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" channel: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" filter: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" force: "); ++stages.back(); if (flag & MTPupdates_getChannelDifference::Flag::f_force) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
case 2: to.add(" channel: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" filter: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" pts: "); ++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(" 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;
}
}
@ -9031,6 +9576,7 @@ namespace {
_serializers.insert(mtpc_messages_messagesSlice, _serialize_messages_messagesSlice);
_serializers.insert(mtpc_messages_channelMessages, _serialize_messages_channelMessages);
_serializers.insert(mtpc_messages_chats, _serialize_messages_chats);
_serializers.insert(mtpc_messages_chatsSlice, _serialize_messages_chatsSlice);
_serializers.insert(mtpc_messages_chatFull, _serialize_messages_chatFull);
_serializers.insert(mtpc_messages_affectedHistory, _serialize_messages_affectedHistory);
_serializers.insert(mtpc_inputMessagesFilterEmpty, _serialize_inputMessagesFilterEmpty);
@ -9097,10 +9643,12 @@ namespace {
_serializers.insert(mtpc_updateRecentStickers, _serialize_updateRecentStickers);
_serializers.insert(mtpc_updateConfig, _serialize_updateConfig);
_serializers.insert(mtpc_updatePtsChanged, _serialize_updatePtsChanged);
_serializers.insert(mtpc_updateChannelWebPage, _serialize_updateChannelWebPage);
_serializers.insert(mtpc_updates_state, _serialize_updates_state);
_serializers.insert(mtpc_updates_differenceEmpty, _serialize_updates_differenceEmpty);
_serializers.insert(mtpc_updates_difference, _serialize_updates_difference);
_serializers.insert(mtpc_updates_differenceSlice, _serialize_updates_differenceSlice);
_serializers.insert(mtpc_updates_differenceTooLong, _serialize_updates_differenceTooLong);
_serializers.insert(mtpc_updatesTooLong, _serialize_updatesTooLong);
_serializers.insert(mtpc_updateShortMessage, _serialize_updateShortMessage);
_serializers.insert(mtpc_updateShortChatMessage, _serialize_updateShortChatMessage);
@ -9156,7 +9704,6 @@ namespace {
_serializers.insert(mtpc_sendMessageGeoLocationAction, _serialize_sendMessageGeoLocationAction);
_serializers.insert(mtpc_sendMessageChooseContactAction, _serialize_sendMessageChooseContactAction);
_serializers.insert(mtpc_sendMessageGamePlayAction, _serialize_sendMessageGamePlayAction);
_serializers.insert(mtpc_sendMessageGameStopAction, _serialize_sendMessageGameStopAction);
_serializers.insert(mtpc_contacts_found, _serialize_contacts_found);
_serializers.insert(mtpc_inputPrivacyKeyStatusTimestamp, _serialize_inputPrivacyKeyStatusTimestamp);
_serializers.insert(mtpc_inputPrivacyKeyChatInvite, _serialize_inputPrivacyKeyChatInvite);
@ -9197,6 +9744,7 @@ namespace {
_serializers.insert(mtpc_webPageEmpty, _serialize_webPageEmpty);
_serializers.insert(mtpc_webPagePending, _serialize_webPagePending);
_serializers.insert(mtpc_webPage, _serialize_webPage);
_serializers.insert(mtpc_webPageNotModified, _serialize_webPageNotModified);
_serializers.insert(mtpc_authorization, _serialize_authorization);
_serializers.insert(mtpc_account_authorizations, _serialize_account_authorizations);
_serializers.insert(mtpc_account_noPassword, _serialize_account_noPassword);
@ -9333,6 +9881,38 @@ namespace {
_serializers.insert(mtpc_inputGameShortName, _serialize_inputGameShortName);
_serializers.insert(mtpc_highScore, _serialize_highScore);
_serializers.insert(mtpc_messages_highScores, _serialize_messages_highScores);
_serializers.insert(mtpc_textEmpty, _serialize_textEmpty);
_serializers.insert(mtpc_textPlain, _serialize_textPlain);
_serializers.insert(mtpc_textBold, _serialize_textBold);
_serializers.insert(mtpc_textItalic, _serialize_textItalic);
_serializers.insert(mtpc_textUnderline, _serialize_textUnderline);
_serializers.insert(mtpc_textStrike, _serialize_textStrike);
_serializers.insert(mtpc_textFixed, _serialize_textFixed);
_serializers.insert(mtpc_textUrl, _serialize_textUrl);
_serializers.insert(mtpc_textEmail, _serialize_textEmail);
_serializers.insert(mtpc_textConcat, _serialize_textConcat);
_serializers.insert(mtpc_pageBlockTitle, _serialize_pageBlockTitle);
_serializers.insert(mtpc_pageBlockSubtitle, _serialize_pageBlockSubtitle);
_serializers.insert(mtpc_pageBlockAuthorDate, _serialize_pageBlockAuthorDate);
_serializers.insert(mtpc_pageBlockHeader, _serialize_pageBlockHeader);
_serializers.insert(mtpc_pageBlockSubheader, _serialize_pageBlockSubheader);
_serializers.insert(mtpc_pageBlockParagraph, _serialize_pageBlockParagraph);
_serializers.insert(mtpc_pageBlockPreformatted, _serialize_pageBlockPreformatted);
_serializers.insert(mtpc_pageBlockFooter, _serialize_pageBlockFooter);
_serializers.insert(mtpc_pageBlockDivider, _serialize_pageBlockDivider);
_serializers.insert(mtpc_pageBlockList, _serialize_pageBlockList);
_serializers.insert(mtpc_pageBlockBlockquote, _serialize_pageBlockBlockquote);
_serializers.insert(mtpc_pageBlockPullquote, _serialize_pageBlockPullquote);
_serializers.insert(mtpc_pageBlockPhoto, _serialize_pageBlockPhoto);
_serializers.insert(mtpc_pageBlockVideo, _serialize_pageBlockVideo);
_serializers.insert(mtpc_pageBlockCover, _serialize_pageBlockCover);
_serializers.insert(mtpc_pageBlockEmbed, _serialize_pageBlockEmbed);
_serializers.insert(mtpc_pageBlockEmbedPost, _serialize_pageBlockEmbedPost);
_serializers.insert(mtpc_pageBlockSlideshow, _serialize_pageBlockSlideshow);
_serializers.insert(mtpc_embedPostPhoto, _serialize_embedPostPhoto);
_serializers.insert(mtpc_embedPostVideo, _serialize_embedPostVideo);
_serializers.insert(mtpc_pagePart, _serialize_pagePart);
_serializers.insert(mtpc_pageFull, _serialize_pageFull);
_serializers.insert(mtpc_req_pq, _serialize_req_pq);
_serializers.insert(mtpc_req_DH_params, _serialize_req_DH_params);
@ -9387,6 +9967,7 @@ namespace {
_serializers.insert(mtpc_upload_saveFilePart, _serialize_upload_saveFilePart);
_serializers.insert(mtpc_upload_saveBigFilePart, _serialize_upload_saveBigFilePart);
_serializers.insert(mtpc_help_saveAppLog, _serialize_help_saveAppLog);
_serializers.insert(mtpc_help_setBotUpdatesStatus, _serialize_help_setBotUpdatesStatus);
_serializers.insert(mtpc_channels_readHistory, _serialize_channels_readHistory);
_serializers.insert(mtpc_channels_reportSpam, _serialize_channels_reportSpam);
_serializers.insert(mtpc_channels_editAbout, _serialize_channels_editAbout);
@ -9478,6 +10059,8 @@ namespace {
_serializers.insert(mtpc_channels_updatePinnedMessage, _serialize_channels_updatePinnedMessage);
_serializers.insert(mtpc_messages_getPeerSettings, _serialize_messages_getPeerSettings);
_serializers.insert(mtpc_messages_getChats, _serialize_messages_getChats);
_serializers.insert(mtpc_messages_getCommonChats, _serialize_messages_getCommonChats);
_serializers.insert(mtpc_messages_getAllChats, _serialize_messages_getAllChats);
_serializers.insert(mtpc_channels_getChannels, _serialize_channels_getChannels);
_serializers.insert(mtpc_channels_getAdminedPublicChannels, _serialize_channels_getAdminedPublicChannels);
_serializers.insert(mtpc_messages_getFullChat, _serialize_messages_getFullChat);
@ -9511,6 +10094,7 @@ namespace {
_serializers.insert(mtpc_messages_getAttachedStickers, _serialize_messages_getAttachedStickers);
_serializers.insert(mtpc_messages_getGameHighScores, _serialize_messages_getGameHighScores);
_serializers.insert(mtpc_messages_getInlineGameHighScores, _serialize_messages_getInlineGameHighScores);
_serializers.insert(mtpc_messages_getWebPage, _serialize_messages_getWebPage);
_serializers.insert(mtpc_updates_getState, _serialize_updates_getState);
_serializers.insert(mtpc_updates_getDifference, _serialize_updates_getDifference);
_serializers.insert(mtpc_updates_getChannelDifference, _serialize_updates_getChannelDifference);

File diff suppressed because it is too large Load Diff

View File

@ -35,38 +35,39 @@ struct PeerUpdate {
enum class Flag {
// Common flags
NameChanged = 0x00000001U,
UsernameChanged = 0x00000002U,
PhotoChanged = 0x00000004U,
AboutChanged = 0x00000008U,
NotificationsEnabled = 0x00000010U,
SharedMediaChanged = 0x00000020U,
MigrationChanged = 0x00000040U,
NameChanged = 0x00000001U,
UsernameChanged = 0x00000002U,
PhotoChanged = 0x00000004U,
AboutChanged = 0x00000008U,
NotificationsEnabled = 0x00000010U,
SharedMediaChanged = 0x00000020U,
MigrationChanged = 0x00000040U,
// For chats and channels
InviteLinkChanged = 0x00000020U,
MembersChanged = 0x00000040U,
AdminsChanged = 0x00000080U,
InviteLinkChanged = 0x00000020U,
MembersChanged = 0x00000040U,
AdminsChanged = 0x00000080U,
// For users
UserCanShareContact = 0x00010000U,
UserIsContact = 0x00020000U,
UserPhoneChanged = 0x00040000U,
UserIsBlocked = 0x00080000U,
BotCommandsChanged = 0x00100000U,
UserOnlineChanged = 0x00200000U,
BotCanAddToGroups = 0x00400000U,
UserCanShareContact = 0x00010000U,
UserIsContact = 0x00020000U,
UserPhoneChanged = 0x00040000U,
UserIsBlocked = 0x00080000U,
BotCommandsChanged = 0x00100000U,
UserOnlineChanged = 0x00200000U,
BotCanAddToGroups = 0x00400000U,
UserCommonChatsChanged = 0x00800000U,
// For chats
ChatCanEdit = 0x00010000U,
ChatCanEdit = 0x00010000U,
// For channels
ChannelAmIn = 0x00010000U,
ChannelAmEditor = 0x00020000U,
ChannelCanEditPhoto = 0x00040000U,
ChannelCanAddMembers = 0x00080000U,
ChannelCanViewAdmins = 0x00100000U,
ChannelCanViewMembers = 0x00200000U,
ChannelAmIn = 0x00010000U,
ChannelAmEditor = 0x00020000U,
ChannelCanEditPhoto = 0x00040000U,
ChannelCanAddMembers = 0x00080000U,
ChannelCanViewAdmins = 0x00100000U,
ChannelCanViewMembers = 0x00200000U,
};
Q_DECLARE_FLAGS(Flags, Flag);
Flags flags = 0;

View File

@ -19,7 +19,7 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "profile/profile_actions_widget.h"
#include "profile/profile_block_actions.h"
#include "styles/style_profile.h"
#include "styles/style_boxes.h"

View File

@ -0,0 +1,145 @@
/*
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
*/
#include "stdafx.h"
#include "profile/profile_block_channel_members.h"
#include "styles/style_profile.h"
#include "ui/widgets/buttons.h"
#include "boxes/members_box.h"
#include "observer_peer.h"
#include "lang.h"
namespace Profile {
using UpdateFlag = Notify::PeerUpdate::Flag;
ChannelMembersWidget::ChannelMembersWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_participants_section)) {
auto observeEvents = UpdateFlag::ChannelCanViewAdmins
| UpdateFlag::ChannelCanViewMembers
| UpdateFlag::AdminsChanged
| UpdateFlag::MembersChanged;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
notifyPeerUpdated(update);
}));
refreshButtons();
}
void ChannelMembersWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.peer != peer()) {
return;
}
if (update.flags & (UpdateFlag::ChannelCanViewAdmins | UpdateFlag::AdminsChanged)) {
refreshAdmins();
}
if (update.flags & (UpdateFlag::ChannelCanViewMembers | UpdateFlag::MembersChanged)) {
refreshMembers();
}
refreshVisibility();
contentSizeUpdated();
}
void ChannelMembersWidget::addButton(const QString &text, ChildWidget<Ui::LeftOutlineButton> *button, const char *slot) {
if (text.isEmpty()) {
button->destroy();
} else if (*button) {
(*button)->setText(text);
} else {
(*button) = new Ui::LeftOutlineButton(this, text, st::defaultLeftOutlineButton);
(*button)->show();
connect(*button, SIGNAL(clicked()), this, slot);
}
}
void ChannelMembersWidget::refreshButtons() {
refreshAdmins();
refreshMembers();
refreshVisibility();
}
void ChannelMembersWidget::refreshAdmins() {
auto getAdminsText = [this]() -> QString {
if (auto channel = peer()->asChannel()) {
if (!channel->isMegagroup() && channel->canViewAdmins()) {
int adminsCount = qMax(channel->adminsCount(), 1);
return lng_channel_admins_link(lt_count, adminsCount);
}
}
return QString();
};
addButton(getAdminsText(), &_admins, SLOT(onAdmins()));
}
void ChannelMembersWidget::refreshMembers() {
auto getMembersText = [this]() -> QString {
if (auto channel = peer()->asChannel()) {
if (!channel->isMegagroup() && channel->canViewMembers()) {
int membersCount = qMax(channel->membersCount(), 1);
return lng_channel_members_link(lt_count, membersCount);
}
}
return QString();
};
addButton(getMembersText(), &_members, SLOT(onMembers()));
}
void ChannelMembersWidget::refreshVisibility() {
setVisible(_admins || _members);
}
int ChannelMembersWidget::resizeGetHeight(int newWidth) {
int newHeight = contentTop();
auto resizeButton = [this, &newHeight, newWidth](ChildWidget<Ui::LeftOutlineButton> &button) {
if (!button) {
return;
}
int left = defaultOutlineButtonLeft();
int availableWidth = newWidth - left - st::profileBlockMarginRight;
accumulate_min(availableWidth, st::profileBlockOneLineWidthMax);
button->resizeToWidth(availableWidth);
button->moveToLeft(left, newHeight);
newHeight += button->height();
};
resizeButton(_admins);
resizeButton(_members);
return newHeight;
}
void ChannelMembersWidget::onAdmins() {
if (auto channel = peer()->asChannel()) {
Ui::showLayer(new MembersBox(channel, MembersFilter::Admins));
}
}
void ChannelMembersWidget::onMembers() {
if (auto channel = peer()->asChannel()) {
Ui::showLayer(new MembersBox(channel, MembersFilter::Recent));
}
}
} // namespace Profile

View File

@ -0,0 +1,65 @@
/*
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
*/
#pragma once
#include "profile/profile_block_widget.h"
namespace Ui {
class LeftOutlineButton;
} // namespace Ui
namespace Notify {
struct PeerUpdate;
} // namespace Notify
namespace Profile {
class ChannelMembersWidget : public BlockWidget {
Q_OBJECT
public:
ChannelMembersWidget(QWidget *parent, PeerData *peer);
protected:
// Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override;
private slots:
void onAdmins();
void onMembers();
private:
// Observed notifications.
void notifyPeerUpdated(const Notify::PeerUpdate &update);
void refreshButtons();
void refreshAdmins();
void refreshMembers();
void refreshVisibility();
void addButton(const QString &text, ChildWidget<Ui::LeftOutlineButton> *button, const char *slot);
ChildWidget<Ui::LeftOutlineButton> _admins = { nullptr };
ChildWidget<Ui::LeftOutlineButton> _members = { nullptr };
};
} // namespace Profile

View File

@ -0,0 +1,175 @@
/*
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
*/
#include "stdafx.h"
#include "profile/profile_block_common_groups.h"
#include "profile/profile_section_memento.h"
#include "styles/style_widgets.h"
#include "observer_peer.h"
#include "apiwrap.h"
#include "lang.h"
namespace Profile {
namespace {
constexpr int kCommonGroupsPerPage = 20;
} // namespace
CommonGroupsWidget::CommonGroupsWidget(QWidget *parent, PeerData *peer)
: PeerListWidget(parent, peer, lang(lng_profile_common_groups_section)) {
refreshVisibility();
auto observeEvents = Notify::PeerUpdate::Flag::MembersChanged;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
notifyPeerUpdated(update);
}));
setSelectedCallback([this](PeerData *selectedPeer) {
Ui::showPeerHistory(selectedPeer, ShowAtUnreadMsgId, Ui::ShowWay::Forward);
});
setPreloadMoreCallback([this] {
preloadMore();
});
}
void CommonGroupsWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
for_const (auto item, items()) {
if (item->peer == update.peer) {
updateStatusText(item);
this->update();
return;
}
}
}
int CommonGroupsWidget::resizeGetHeight(int newWidth) {
auto result = PeerListWidget::resizeGetHeight(newWidth);
return _height.animating() ? _height.current() : result;
}
void CommonGroupsWidget::paintContents(Painter &p) {
_height.animating(getms());
return PeerListWidget::paintContents(p);
}
void CommonGroupsWidget::saveState(SectionMemento *memento) const {
if (auto count = itemsCount()) {
QList<PeerData*> groups;
groups.reserve(count);
for_const (auto item, items()) {
groups.push_back(item->peer);
}
memento->setCommonGroups(groups);
}
}
void CommonGroupsWidget::restoreState(const SectionMemento *memento) {
CommonGroupsEvent event;
event.groups = memento->getCommonGroups();
if (!event.groups.empty()) {
onShowCommonGroups(event);
}
}
void CommonGroupsWidget::onShowCommonGroups(const CommonGroupsEvent &event) {
for_const (auto group, event.groups) {
addItem(computeItem(group));
_preloadGroupId = group->bareId();
}
refreshVisibility();
if (event.initialHeight >= 0) {
_height.start([this] { contentSizeUpdated(); }, event.initialHeight, resizeGetHeight(width()), st::widgetSlideDuration);
}
contentSizeUpdated();
update();
}
void CommonGroupsWidget::preloadMore() {
if (_preloadRequestId || !_preloadGroupId) {
return;
}
auto user = peer()->asUser();
t_assert(user != nullptr);
auto request = MTPmessages_GetCommonChats(user->inputUser, MTP_int(_preloadGroupId), MTP_int(kCommonGroupsPerPage));
_preloadRequestId = MTP::send(request, ::rpcDone(base::lambda_guarded(this, [this](const MTPmessages_Chats &result) {
_preloadRequestId = 0;
_preloadGroupId = 0;
if (auto chats = Api::getChatsFromMessagesChats(result)) {
auto &list = chats->c_vector().v;
if (!list.empty()) {
reserveItemsForSize(itemsCount() + list.size());
for_const (auto &chatData, list) {
if (auto chat = App::feedChat(chatData)) {
addItem(computeItem(chat));
_preloadGroupId = chat->bareId();
}
}
contentSizeUpdated();
}
}
})));
}
void CommonGroupsWidget::updateStatusText(Item *item) {
auto group = item->peer;
if (auto chat = group->asChat()) {
auto count = qMax(chat->count, chat->participants.size());
item->statusText = count ? lng_chat_status_members(lt_count, count) : lang(lng_group_status);
} else if (auto megagroup = group->asMegagroup()) {
auto count = megagroup->membersCount();
item->statusText = (count > 0) ? lng_chat_status_members(lt_count, count) : lang(lng_group_status);
// Request members count.
if (!megagroup->wasFullUpdated()) App::api()->requestFullPeer(megagroup);
} else if (auto channel = group->asChannel()) {
auto count = channel->membersCount();
item->statusText = (count > 0) ? lng_chat_status_members(lt_count, count) : lang(lng_channel_status);
// Request members count.
if (!channel->wasFullUpdated()) App::api()->requestFullPeer(channel);
} else {
t_assert(!"Users should not get to CommonGroupsWidget::updateStatusText()");
}
}
CommonGroupsWidget::Item *CommonGroupsWidget::computeItem(PeerData *group) {
// Skip groups that migrated to supergroups.
if (group->migrateTo()) {
return nullptr;
}
auto it = _dataMap.constFind(group);
if (it == _dataMap.cend()) {
it = _dataMap.insert(group, new Item(group));
updateStatusText(it.value());
}
return it.value();
}
CommonGroupsWidget::~CommonGroupsWidget() {
for (auto item : base::take(_dataMap)) {
delete item;
}
}
} // namespace Profile

View File

@ -0,0 +1,75 @@
/*
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
*/
#pragma once
#include "profile/profile_block_peer_list.h"
namespace Notify {
struct PeerUpdate;
} // namespace Notify
namespace Profile {
struct CommonGroupsEvent {
QList<PeerData*> groups;
// If initialHeight >= 0 the common groups widget will
// slide down starting from height() == initialHeight.
// Otherwise it will just show instantly.
int initialHeight = -1;
};
class CommonGroupsWidget : public PeerListWidget {
public:
CommonGroupsWidget(QWidget *parent, PeerData *peer);
void setShowCommonGroupsObservable(base::Observable<CommonGroupsEvent> *observable) {
subscribe(observable, [this](const CommonGroupsEvent &event) { onShowCommonGroups(event); });
}
void saveState(SectionMemento *memento) const override;
void restoreState(const SectionMemento *memento) override;
~CommonGroupsWidget();
protected:
int resizeGetHeight(int newWidth) override;
void paintContents(Painter &p) override;
private:
// Observed notifications.
void notifyPeerUpdated(const Notify::PeerUpdate &update);
void updateStatusText(Item *item);
void onShowCommonGroups(const CommonGroupsEvent &event);
void preloadMore();
Item *computeItem(PeerData *group);
QMap<PeerData*, Item*> _dataMap;
IntAnimation _height;
int32 _preloadGroupId = 0;
mtpRequestId _preloadRequestId = 0;
};
} // namespace Profile

View File

@ -0,0 +1,429 @@
/*
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
*/
#include "stdafx.h"
#include "profile/profile_block_group_members.h"
#include "styles/style_profile.h"
#include "ui/widgets/labels.h"
#include "boxes/confirmbox.h"
#include "apiwrap.h"
#include "observer_peer.h"
#include "lang.h"
namespace Profile {
using UpdateFlag = Notify::PeerUpdate::Flag;
GroupMembersWidget::GroupMembersWidget(QWidget *parent, PeerData *peer, TitleVisibility titleVisibility)
: PeerListWidget(parent
, peer
, (titleVisibility == TitleVisibility::Visible) ? lang(lng_profile_participants_section) : QString()
, lang(lng_profile_kick)) {
_updateOnlineTimer.setSingleShot(true);
connect(&_updateOnlineTimer, SIGNAL(timeout()), this, SLOT(onUpdateOnlineDisplay()));
auto observeEvents = UpdateFlag::AdminsChanged
| UpdateFlag::MembersChanged
| UpdateFlag::UserOnlineChanged;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
notifyPeerUpdated(update);
}));
setRemovedCallback([this, peer](PeerData *selectedPeer) {
Ui::showLayer(new KickMemberBox(peer, selectedPeer->asUser()));
});
setSelectedCallback([this](PeerData *selectedPeer) {
Ui::showPeerProfile(selectedPeer);
});
setUpdateItemCallback([this](Item *item) {
updateItemStatusText(item);
});
setPreloadMoreCallback([this] {
preloadMore();
});
refreshMembers();
}
void GroupMembersWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.peer != peer()) {
if (update.flags & UpdateFlag::UserOnlineChanged) {
if (auto user = update.peer->asUser()) {
refreshUserOnline(user);
}
}
return;
}
if (update.flags & UpdateFlag::MembersChanged) {
refreshMembers();
contentSizeUpdated();
} else if (update.flags & UpdateFlag::AdminsChanged) {
if (auto chat = peer()->asChat()) {
for_const (auto item, items()) {
setItemFlags(getMember(item), chat);
}
} else if (auto megagroup = peer()->asMegagroup()) {
for_const (auto item, items()) {
setItemFlags(getMember(item), megagroup);
}
}
}
this->update();
}
void GroupMembersWidget::refreshUserOnline(UserData *user) {
auto it = _membersByUser.find(user);
if (it == _membersByUser.cend()) return;
_now = unixtime();
auto member = getMember(it.value());
member->statusHasOnlineColor = !user->botInfo && App::onlineColorUse(user->onlineTill, _now);
member->onlineTill = user->onlineTill;
member->onlineForSort = user->isSelf() ? INT_MAX : App::onlineForSort(user, _now);
member->statusText = QString();
sortMembers();
update();
}
void GroupMembersWidget::preloadMore() {
if (auto megagroup = peer()->asMegagroup()) {
auto megagroupInfo = megagroup->mgInfo;
if (!megagroupInfo->lastParticipants.isEmpty() && megagroupInfo->lastParticipants.size() < megagroup->membersCount()) {
App::api()->requestLastParticipants(megagroup, false);
}
}
}
int GroupMembersWidget::resizeGetHeight(int newWidth) {
if (_limitReachedInfo) {
int limitReachedInfoWidth = newWidth - getListLeft();
accumulate_min(limitReachedInfoWidth, st::profileBlockWideWidthMax);
_limitReachedInfo->resizeToWidth(limitReachedInfoWidth);
_limitReachedInfo->moveToLeft(getListLeft(), contentTop());
}
return PeerListWidget::resizeGetHeight(newWidth);
}
void GroupMembersWidget::paintContents(Painter &p) {
int left = getListLeft();
int top = getListTop();
int memberRowWidth = width() - left;
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
if (_limitReachedInfo) {
int infoTop = contentTop();
int infoHeight = top - infoTop - st::profileLimitReachedSkip;
paintOutlinedRect(p, left, infoTop, memberRowWidth, infoHeight);
}
_now = unixtime();
PeerListWidget::paintContents(p);
}
void GroupMembersWidget::updateItemStatusText(Item *item) {
auto member = getMember(item);
auto user = member->user();
if (member->statusText.isEmpty() || (member->onlineTextTill <= _now)) {
if (user->botInfo) {
bool seesAllMessages = (user->botInfo->readsAllHistory || member->hasAdminStar);
member->statusText = lang(seesAllMessages ? lng_status_bot_reads_all : lng_status_bot_not_reads_all);
member->onlineTextTill = _now + 86400;
} else {
member->statusHasOnlineColor = App::onlineColorUse(member->onlineTill, _now);
member->statusText = App::onlineText(member->onlineTill, _now);
member->onlineTextTill = _now + App::onlineWillChangeIn(member->onlineTill, _now);
}
}
if (_updateOnlineAt <= _now || _updateOnlineAt > member->onlineTextTill) {
_updateOnlineAt = member->onlineTextTill;
_updateOnlineTimer.start((_updateOnlineAt - _now + 1) * 1000);
}
}
int GroupMembersWidget::getListTop() const {
int result = contentTop();
if (_limitReachedInfo) {
result += _limitReachedInfo->height();
result += st::profileLimitReachedSkip;
}
return result;
}
void GroupMembersWidget::refreshMembers() {
_now = unixtime();
if (auto chat = peer()->asChat()) {
checkSelfAdmin(chat);
if (chat->noParticipantInfo()) {
App::api()->requestFullPeer(chat);
}
fillChatMembers(chat);
refreshLimitReached();
} else if (auto megagroup = peer()->asMegagroup()) {
checkSelfAdmin(megagroup);
auto megagroupInfo = megagroup->mgInfo;
if (megagroupInfo->lastParticipants.isEmpty() || megagroup->lastParticipantsCountOutdated()) {
App::api()->requestLastParticipants(megagroup);
}
fillMegagroupMembers(megagroup);
}
sortMembers();
refreshVisibility();
}
void GroupMembersWidget::refreshLimitReached() {
auto chat = peer()->asChat();
if (!chat) return;
bool limitReachedShown = (itemsCount() >= Global::ChatSizeMax()) && chat->amCreator() && !emptyTitle();
if (limitReachedShown && !_limitReachedInfo) {
_limitReachedInfo.create(this, st::profileLimitReachedLabel, st::profileLimitReachedStyle);
QString title = textRichPrepare(lng_profile_migrate_reached(lt_count, Global::ChatSizeMax()));
QString body = textRichPrepare(lang(lng_profile_migrate_body));
QString link = textRichPrepare(lang(lng_profile_migrate_learn_more));
QString text = qsl("%1%2%3\n%4 [a href=\"https://telegram.org/blog/supergroups5k\"]%5[/a]").arg(textcmdStartSemibold()).arg(title).arg(textcmdStopSemibold()).arg(body).arg(link);
_limitReachedInfo->setRichText(text);
_limitReachedInfo->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) {
Ui::showLayer(new ConvertToSupergroupBox(peer()->asChat()));
return false;
});
} else if (!limitReachedShown && _limitReachedInfo) {
_limitReachedInfo.destroy();
}
}
void GroupMembersWidget::checkSelfAdmin(ChatData *chat) {
if (chat->participants.isEmpty()) return;
auto self = App::self();
if (chat->amAdmin() && !chat->admins.contains(self)) {
chat->admins.insert(self);
} else if (!chat->amAdmin() && chat->admins.contains(self)) {
chat->admins.remove(self);
}
}
void GroupMembersWidget::checkSelfAdmin(ChannelData *megagroup) {
if (megagroup->mgInfo->lastParticipants.isEmpty()) return;
bool amAdmin = (megagroup->amCreator() || megagroup->amEditor());
auto self = App::self();
if (amAdmin && !megagroup->mgInfo->lastAdmins.contains(self)) {
megagroup->mgInfo->lastAdmins.insert(self);
} else if (!amAdmin && megagroup->mgInfo->lastAdmins.contains(self)) {
megagroup->mgInfo->lastAdmins.remove(self);
}
}
void GroupMembersWidget::sortMembers() {
if (!_sortByOnline || !itemsCount()) return;
sortItems([this](Item *a, Item *b) {
return getMember(a)->onlineForSort > getMember(b)->onlineForSort;
});
updateOnlineCount();
}
void GroupMembersWidget::updateOnlineCount() {
bool onlyMe = true;
int newOnlineCount = 0;
for_const (auto item, items()) {
auto member = getMember(item);
auto user = member->user();
auto isOnline = !user->botInfo && App::onlineColorUse(member->onlineTill, _now);
if (member->statusHasOnlineColor != isOnline) {
member->statusHasOnlineColor = isOnline;
member->statusText = QString();
}
if (member->statusHasOnlineColor) {
++newOnlineCount;
if (!user->isSelf()) {
onlyMe = false;
}
}
}
if (newOnlineCount == 1 && onlyMe) {
newOnlineCount = 0;
}
if (_onlineCount != newOnlineCount) {
_onlineCount = newOnlineCount;
emit onlineCountUpdated(_onlineCount);
}
}
GroupMembersWidget::Member *GroupMembersWidget::addUser(ChatData *chat, UserData *user) {
auto member = computeMember(user);
setItemFlags(member, chat);
addItem(member);
return member;
}
void GroupMembersWidget::fillChatMembers(ChatData *chat) {
if (chat->participants.isEmpty()) return;
clearItems();
if (!chat->amIn()) return;
_sortByOnline = true;
reserveItemsForSize(chat->participants.size());
addUser(chat, App::self())->onlineForSort = INT_MAX; // Put me on the first place.
for (auto i = chat->participants.cbegin(), e = chat->participants.cend(); i != e; ++i) {
auto user = i.key();
if (!user->isSelf()) {
addUser(chat, user);
}
}
}
void GroupMembersWidget::setItemFlags(Item *item, ChatData *chat) {
auto user = getMember(item)->user();
auto isCreator = (peerFromUser(chat->creator) == item->peer->id);
auto isAdmin = chat->admins.contains(user);
item->hasAdminStar = isCreator || isAdmin;
if (item->peer->id == peerFromUser(MTP::authedId())) {
item->hasRemoveLink = false;
} else if (chat->amCreator() || (chat->amAdmin() && !item->hasAdminStar)) {
item->hasRemoveLink = true;
} else {
item->hasRemoveLink = chat->invitedByMe.contains(user);
}
}
GroupMembersWidget::Member *GroupMembersWidget::addUser(ChannelData *megagroup, UserData *user) {
auto member = computeMember(user);
setItemFlags(member, megagroup);
addItem(member);
return member;
}
void GroupMembersWidget::fillMegagroupMembers(ChannelData *megagroup) {
t_assert(megagroup->mgInfo != nullptr);
if (megagroup->mgInfo->lastParticipants.isEmpty()) return;
if (!megagroup->canViewMembers()) {
clearItems();
return;
}
_sortByOnline = (megagroup->membersCount() > 0 && megagroup->membersCount() <= Global::ChatSizeMax());
auto &membersList = megagroup->mgInfo->lastParticipants;
if (_sortByOnline) {
clearItems();
reserveItemsForSize(membersList.size());
if (megagroup->amIn()) {
addUser(megagroup, App::self())->onlineForSort = INT_MAX;
}
} else if (membersList.size() >= itemsCount()) {
if (addUsersToEnd(megagroup)) {
return;
}
}
if (!_sortByOnline) {
clearItems();
reserveItemsForSize(membersList.size());
}
for_const (auto user, membersList) {
if (!_sortByOnline || !user->isSelf()) {
addUser(megagroup, user);
}
}
}
bool GroupMembersWidget::addUsersToEnd(ChannelData *megagroup) {
auto &membersList = megagroup->mgInfo->lastParticipants;
auto &itemsList = items();
for (int i = 0, count = itemsList.size(); i < count; ++i) {
if (itemsList[i]->peer != membersList.at(i)) {
return false;
}
}
reserveItemsForSize(membersList.size());
for (int i = itemsCount(), count = membersList.size(); i < count; ++i) {
addUser(megagroup, membersList.at(i));
}
return true;
}
void GroupMembersWidget::setItemFlags(Item *item, ChannelData *megagroup) {
auto amCreatorOrAdmin = (peerToUser(item->peer->id) == MTP::authedId()) && (megagroup->amCreator() || megagroup->amEditor());
auto isAdmin = megagroup->mgInfo->lastAdmins.contains(getMember(item)->user());
item->hasAdminStar = amCreatorOrAdmin || isAdmin;
if (item->peer->isSelf()) {
item->hasRemoveLink = false;
} else if (megagroup->amCreator() || (megagroup->amEditor() && !item->hasAdminStar)) {
item->hasRemoveLink = true;
} else {
item->hasRemoveLink = false;
}
}
GroupMembersWidget::Member *GroupMembersWidget::computeMember(UserData *user) {
auto it = _membersByUser.constFind(user);
if (it == _membersByUser.cend()) {
auto member = new Member(user);
it = _membersByUser.insert(user, member);
member->statusHasOnlineColor = !user->botInfo && App::onlineColorUse(user->onlineTill, _now);
member->onlineTill = user->onlineTill;
member->onlineForSort = App::onlineForSort(user, _now);
}
return it.value();
}
void GroupMembersWidget::onUpdateOnlineDisplay() {
if (_sortByOnline) {
_now = unixtime();
bool changed = false;
for_const (auto item, items()) {
if (!item->statusHasOnlineColor) {
if (!item->peer->isSelf()) {
continue;
} else {
break;
}
}
auto member = getMember(item);
bool isOnline = !member->user()->botInfo && App::onlineColorUse(member->onlineTill, _now);
if (!isOnline) {
changed = true;
}
}
if (changed) {
updateOnlineCount();
}
}
update();
}
GroupMembersWidget::~GroupMembersWidget() {
auto members = base::take(_membersByUser);
for_const (auto member, members) {
delete member;
}
}
} // namespace Profile

View File

@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "profile/profile_block_widget.h"
#include "profile/profile_block_peer_list.h"
namespace Ui {
class FlatLabel;
@ -33,7 +33,7 @@ struct PeerUpdate;
namespace Profile {
class MembersWidget : public BlockWidget {
class GroupMembersWidget : public PeerListWidget {
Q_OBJECT
public:
@ -41,14 +41,13 @@ public:
Visible,
Hidden,
};
MembersWidget(QWidget *parent, PeerData *peer, TitleVisibility titleVisibility = TitleVisibility::Visible);
GroupMembersWidget(QWidget *parent, PeerData *peer, TitleVisibility titleVisibility = TitleVisibility::Visible);
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
int onlineCount() const {
return _onlineCount;
}
~MembersWidget();
~GroupMembersWidget();
protected:
// Resizes content and counts natural widget height for the desired width.
@ -56,18 +55,6 @@ protected:
void paintContents(Painter &p) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void enterEvent(QEvent *e) override;
void enterFromChildEvent(QEvent *e, QWidget *child) override {
enterEvent(e);
}
void leaveEvent(QEvent *e) override;
void leaveToChildEvent(QEvent *e, QWidget *child) override {
leaveEvent(e);
}
signals:
void onlineCountUpdated(int onlineCount);
@ -78,8 +65,6 @@ private:
// Observed notifications.
void notifyPeerUpdated(const Notify::PeerUpdate &update);
void preloadUserPhotos();
void refreshMembers();
void fillChatMembers(ChatData *chat);
void fillMegagroupMembers(ChannelData *megagroup);
@ -89,91 +74,46 @@ private:
void checkSelfAdmin(ChannelData *megagroup);
void refreshLimitReached();
void preloadMore();
bool limitReachedHook(const ClickHandlerPtr &handler, Qt::MouseButton button);
void refreshVisibility();
void updateSelection();
void setSelected(int selected, bool selectedKick);
void repaintSelectedRow();
void refreshUserOnline(UserData *user);
int getListLeft() const;
int getListTop() const;
int getListTop() const override;
struct Member {
Member(UserData *user) : user(user) {
struct Member : public Item {
explicit Member(UserData *user) : Item(user) {
}
UserData *user() const {
return static_cast<UserData*>(peer);
}
UserData *user;
Text name;
QString onlineText;
TimeId onlineTextTill = 0;
TimeId onlineTill = 0;
TimeId onlineForSort = 0;
bool online = false;
bool isAdmin = false;
bool canBeKicked = false;
};
Member *getMember(UserData *user);
void paintMember(Painter &p, int x, int y, Member *member, bool selected, bool selectedKick);
void paintOutlinedRect(Painter &p, int x, int y, int w, int h) const;
void setMemberFlags(Member *member, ChatData *chat);
Member *getMember(Item *item) {
return static_cast<Member*>(item);
}
void updateItemStatusText(Item *item);
Member *computeMember(UserData *user);
Member *addUser(ChatData *chat, UserData *user);
void setMemberFlags(Member *member, ChannelData *megagroup);
Member *addUser(ChannelData *megagroup, UserData *user);
void setItemFlags(Item *item, ChatData *chat);
void setItemFlags(Item *item, ChannelData *megagroup);
bool addUsersToEnd(ChannelData *megagroup);
ChildWidget<Ui::FlatLabel> _limitReachedInfo = { nullptr };
QList<Member*> _list;
QMap<UserData*, Member*> _membersByUser;
bool _sortByOnline = false;
TimeId _now = 0;
int _visibleTop = 0;
int _visibleBottom = 0;
int _selected = -1;
int _pressed = -1;
bool _selectedKick = false;
bool _pressedKick = false;
QPoint _mousePosition;
int _onlineCount = 0;
TimeId _updateOnlineAt = 0;
QTimer _updateOnlineTimer;
int _removeWidth = 0;
};
class ChannelMembersWidget : public BlockWidget {
Q_OBJECT
public:
ChannelMembersWidget(QWidget *parent, PeerData *peer);
protected:
// Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override;
private slots:
void onAdmins();
void onMembers();
private:
// Observed notifications.
void notifyPeerUpdated(const Notify::PeerUpdate &update);
void refreshButtons();
void refreshAdmins();
void refreshMembers();
void refreshVisibility();
void addButton(const QString &text, ChildWidget<Ui::LeftOutlineButton> *button, const char *slot);
ChildWidget<Ui::LeftOutlineButton> _admins = { nullptr };
ChildWidget<Ui::LeftOutlineButton> _members = { nullptr };
};
} // namespace Profile

View File

@ -19,28 +19,56 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "profile/profile_info_widget.h"
#include "profile/profile_block_info.h"
#include "profile/profile_block_common_groups.h"
#include "profile/profile_section_memento.h"
#include "styles/style_profile.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h"
#include "ui/effects/widget_slide_wrap.h"
#include "core/click_handler_types.h"
#include "observer_peer.h"
#include "apiwrap.h"
#include "lang.h"
namespace Profile {
constexpr int kCommonGroupsLimit = 20;
using UpdateFlag = Notify::PeerUpdate::Flag;
InfoWidget::InfoWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_info_section)) {
auto observeEvents = UpdateFlag::AboutChanged
| UpdateFlag::UsernameChanged
| UpdateFlag::UserPhoneChanged
| UpdateFlag::UserCanShareContact;
| UpdateFlag::UserCanShareContact
| UpdateFlag::UserCommonChatsChanged;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
notifyPeerUpdated(update);
}));
refreshLabels();
if (_commonGroups && _commonGroups->isHidden()) {
_commonGroups->show();
refreshVisibility();
}
}
void InfoWidget::showFinished() {
_showFinished = true;
if (_commonGroups && _commonGroups->isHidden() && getCommonGroupsCount() > 0) {
_commonGroups->show();
refreshVisibility();
_height.start([this] { contentSizeUpdated(); }, isHidden() ? 0 : height(), resizeGetHeight(width()), st::widgetSlideDuration);
contentSizeUpdated();
}
}
void InfoWidget::restoreState(const SectionMemento *memento) {
if (!memento->getCommonGroups().isEmpty()) {
onForceHideCommonGroups();
}
}
void InfoWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
@ -58,13 +86,17 @@ void InfoWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.flags & (UpdateFlag::UserPhoneChanged | UpdateFlag::UserCanShareContact)) {
refreshMobileNumber();
}
if (update.flags & UpdateFlag::UserCommonChatsChanged) {
refreshCommonGroups();
}
refreshVisibility();
contentSizeUpdated();
}
int InfoWidget::resizeGetHeight(int newWidth) {
int newHeight = contentTop();
int initialHeight = contentTop();
int newHeight = initialHeight;
int marginLeft = st::profileBlockTextPart.margin.left();
int marginRight = st::profileBlockTextPart.margin.right();
@ -109,8 +141,18 @@ int InfoWidget::resizeGetHeight(int newWidth) {
moveLabeledText(_mobileNumberLabel, _mobileNumber, nullptr);
moveLabeledText(_usernameLabel, _username, nullptr);
if (_commonGroups && !_commonGroups->isHidden()) {
int left = defaultOutlineButtonLeft();
int availableWidth = newWidth - left - st::profileBlockMarginRight;
accumulate_min(availableWidth, st::profileBlockOneLineWidthMax);
_commonGroups->resizeToWidth(availableWidth);
_commonGroups->moveToLeft(left, newHeight);
newHeight += _commonGroups->height();
}
newHeight += st::profileBlockMarginBottom;
return newHeight;
return _height.animating() ? _height.current() : newHeight;
}
void InfoWidget::leaveEvent(QEvent *e) {
@ -123,12 +165,13 @@ void InfoWidget::refreshLabels() {
refreshMobileNumber();
refreshUsername();
refreshChannelLink();
refreshCommonGroups();
refreshVisibility();
}
void InfoWidget::refreshVisibility() {
setVisible(_about || _mobileNumber || _username || _channelLink);
setVisible(_about || _mobileNumber || _username || _channelLink || (_commonGroups && !_commonGroups->isHidden()));
}
void InfoWidget::refreshAbout() {
@ -198,6 +241,84 @@ void InfoWidget::refreshChannelLink() {
}
}
int InfoWidget::getCommonGroupsCount() const {
if (auto user = peer()->asUser()) {
return user->commonChatsCount();
}
return 0;
}
void InfoWidget::refreshCommonGroups() {
if (auto count = (_forceHiddenCommonGroups ? 0 : getCommonGroupsCount())) {
auto text = lng_profile_common_groups(lt_count, count);
if (_commonGroups) {
_commonGroups->setText(text);
} else {
_commonGroups.create(this, text, st::defaultLeftOutlineButton);
_commonGroups->setClickedCallback([this] { onShowCommonGroups(); });
_commonGroups->hide();
if (_showFinished) {
_height.start([this] { contentSizeUpdated(); }, isHidden() ? 0 : height(), resizeGetHeight(width()), st::widgetSlideDuration);
contentSizeUpdated();
}
}
} else if (_commonGroups) {
_commonGroups.destroyDelayed();
}
}
void InfoWidget::setShowCommonGroupsObservable(base::Observable<CommonGroupsEvent> *observable) {
_showCommonGroupsObservable = observable;
subscribe(_showCommonGroupsObservable, [this](const CommonGroupsEvent &event) {
onForceHideCommonGroups();
});
}
void InfoWidget::onForceHideCommonGroups() {
if (_forceHiddenCommonGroups) {
return;
}
_forceHiddenCommonGroups = true;
_commonGroups.destroyDelayed();
refreshVisibility();
contentSizeUpdated();
}
void InfoWidget::onShowCommonGroups() {
auto count = getCommonGroupsCount();
if (count <= 0) {
refreshCommonGroups();
return;
}
if (_getCommonGroupsRequestId) {
return;
}
auto user = peer()->asUser();
t_assert(user != nullptr);
auto request = MTPmessages_GetCommonChats(user->inputUser, MTP_int(0), MTP_int(kCommonGroupsLimit));
_getCommonGroupsRequestId = MTP::send(request, ::rpcDone(base::lambda_guarded(this, [this](const MTPmessages_Chats &result) {
_getCommonGroupsRequestId = 0;
CommonGroupsEvent event;
if (auto chats = Api::getChatsFromMessagesChats(result)) {
auto &list = chats->c_vector().v;
event.groups.reserve(list.size());
for_const (auto &chatData, list) {
if (auto chat = App::feedChat(chatData)) {
event.groups.push_back(chat);
}
}
}
auto oldHeight = height();
onForceHideCommonGroups();
if (!event.groups.empty() && _showCommonGroupsObservable) {
event.initialHeight = oldHeight - (isHidden() ? 0 : height());
_showCommonGroupsObservable->notify(event, true);
}
})));
}
void InfoWidget::setLabeledText(ChildWidget<Ui::FlatLabel> *labelWidget, const QString &label,
ChildWidget<Ui::FlatLabel> *textWidget, const TextWithEntities &textWithEntities, const QString &copyText) {
if (labelWidget) labelWidget->destroy();

View File

@ -30,12 +30,23 @@ namespace Notify {
struct PeerUpdate;
} // namespace Notify
namespace Ui {
class LeftOutlineButton;
} // namespace Ui
namespace Profile {
class InfoWidget : public BlockWidget {
struct CommonGroupsEvent;
class InfoWidget : public BlockWidget, public RPCSender {
public:
InfoWidget(QWidget *parent, PeerData *peer);
void setShowCommonGroupsObservable(base::Observable<CommonGroupsEvent> *observable);
void showFinished() override;
void restoreState(const SectionMemento *memento) override;
protected:
// Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override;
@ -51,8 +62,13 @@ private:
void refreshMobileNumber();
void refreshUsername();
void refreshChannelLink();
void refreshCommonGroups();
void refreshVisibility();
int getCommonGroupsCount() const;
void onForceHideCommonGroups();
void onShowCommonGroups();
// labelWidget may be nullptr.
void setLabeledText(ChildWidget<Ui::FlatLabel> *labelWidget, const QString &label,
ChildWidget<Ui::FlatLabel> *textWidget, const TextWithEntities &textWithEntities, const QString &copyText);
@ -65,6 +81,15 @@ private:
ChildWidget<Ui::FlatLabel> _mobileNumber = { nullptr };
ChildWidget<Ui::FlatLabel> _usernameLabel = { nullptr };
ChildWidget<Ui::FlatLabel> _username = { nullptr };
ChildWidget<Ui::LeftOutlineButton> _commonGroups = { nullptr };
IntAnimation _height;
bool _showFinished = false;
bool _forceHiddenCommonGroups = false;
mtpRequestId _getCommonGroupsRequestId = 0;
base::Observable<CommonGroupsEvent> *_showCommonGroupsObservable = nullptr;
};

View File

@ -19,7 +19,7 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "profile/profile_invite_link_widget.h"
#include "profile/profile_block_invite_link.h"
#include "styles/style_profile.h"
#include "ui/widgets/labels.h"

View File

@ -0,0 +1,241 @@
/*
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
*/
#include "stdafx.h"
#include "profile/profile_block_peer_list.h"
#include "styles/style_profile.h"
#include "styles/style_widgets.h"
namespace Profile {
PeerListWidget::PeerListWidget(QWidget *parent, PeerData *peer, const QString &title, const QString &removeText)
: BlockWidget(parent, peer, title)
, _removeText(removeText)
, _removeWidth(st::normalFont->width(_removeText)) {
setMouseTracking(true);
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
}
int PeerListWidget::resizeGetHeight(int newWidth) {
auto newHeight = getListTop();
newHeight += _items.size() * st::profileMemberHeight;
return newHeight + st::profileBlockMarginBottom;
}
void PeerListWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
if (_preloadMoreCallback) {
if (_visibleTop + PreloadHeightsCount * (_visibleBottom - _visibleTop) > height()) {
_preloadMoreCallback();
}
}
}
void PeerListWidget::paintContents(Painter &p) {
int left = getListLeft();
int top = getListTop();
int memberRowWidth = width() - left;
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
int from = floorclamp(_visibleTop - top, st::profileMemberHeight, 0, _items.size());
int to = ceilclamp(_visibleBottom - top, st::profileMemberHeight, 0, _items.size());
for (int i = from; i < to; ++i) {
int y = top + i * st::profileMemberHeight;
bool selected = (i == _selected);
bool selectedRemove = selected && _selectedRemove;
if (_pressed >= 0) {
if (_pressed != _selected) {
selected = selectedRemove = false;
} else if (!_pressedRemove) {
_selectedRemove = false;
}
}
paintItem(p, left, y, _items[i], selected, selectedRemove);
}
}
void PeerListWidget::paintItem(Painter &p, int x, int y, Item *item, bool selected, bool selectedKick) {
if (_updateItemCallback) {
_updateItemCallback(item);
}
int memberRowWidth = width() - x;
if (selected) {
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
paintOutlinedRect(p, x, y, memberRowWidth, st::profileMemberHeight);
}
int skip = st::profileMemberPhotoPosition.x();
item->peer->paintUserpicLeft(p, st::profileMemberPhotoSize, x + st::profileMemberPhotoPosition.x(), y + st::profileMemberPhotoPosition.y(), width());
if (item->name.isEmpty()) {
item->name.setText(st::semiboldFont, App::peerName(item->peer), _textNameOptions);
}
int nameLeft = x + st::profileMemberNamePosition.x();
int nameTop = y + st::profileMemberNamePosition.y();
int nameWidth = memberRowWidth - st::profileMemberNamePosition.x() - skip;
if (item->hasRemoveLink && selected) {
p.setFont(selectedKick ? st::normalFont->underline() : st::normalFont);
p.setPen(st::windowActiveTextFg);
p.drawTextLeft(nameLeft + nameWidth - _removeWidth, nameTop, width(), _removeText, _removeWidth);
nameWidth -= _removeWidth + skip;
}
if (item->hasAdminStar) {
nameWidth -= st::profileMemberAdminIcon.width();
int iconLeft = nameLeft + qMin(nameWidth, item->name.maxWidth());
st::profileMemberAdminIcon.paint(p, QPoint(iconLeft, nameTop), width());
}
p.setPen(st::profileMemberNameFg);
item->name.drawLeftElided(p, nameLeft, nameTop, nameWidth, width());
if (item->statusHasOnlineColor) {
p.setPen(st::profileMemberStatusFgActive);
} else {
p.setPen(selected ? st::profileMemberStatusFgOver : st::profileMemberStatusFg);
}
p.setFont(st::normalFont);
p.drawTextLeft(x + st::profileMemberStatusPosition.x(), y + st::profileMemberStatusPosition.y(), width(), item->statusText);
}
void PeerListWidget::paintOutlinedRect(Painter &p, int x, int y, int w, int h) const {
int outlineWidth = st::defaultLeftOutlineButton.outlineWidth;
p.fillRect(rtlrect(x, y, outlineWidth, h, width()), st::defaultLeftOutlineButton.outlineFgOver);
p.fillRect(rtlrect(x + outlineWidth, y, w - outlineWidth, h, width()), st::defaultLeftOutlineButton.textBgOver);
}
void PeerListWidget::mouseMoveEvent(QMouseEvent *e) {
_mousePosition = e->globalPos();
updateSelection();
}
void PeerListWidget::mousePressEvent(QMouseEvent *e) {
_mousePosition = e->globalPos();
updateSelection();
_pressed = _selected;
_pressedRemove = _selectedRemove;
}
void PeerListWidget::mouseReleaseEvent(QMouseEvent *e) {
_mousePosition = e->globalPos();
updateSelection();
auto pressed = _pressed;
auto pressedRemove = _pressedRemove;
_pressed = -1;
_pressedRemove = false;
if (pressed >= 0 && pressed < _items.size() && pressed == _selected && pressedRemove == _selectedRemove) {
if (auto &callback = (pressedRemove ? _removedCallback : _selectedCallback)) {
callback(_items[pressed]->peer);
}
}
setCursor(_selectedRemove ? style::cur_pointer : style::cur_default);
repaintSelectedRow();
}
void PeerListWidget::enterEvent(QEvent *e) {
_mousePosition = QCursor::pos();
updateSelection();
}
void PeerListWidget::leaveEvent(QEvent *e) {
_mousePosition = QPoint(-1, -1);
updateSelection();
}
void PeerListWidget::updateSelection() {
int selected = -1;
bool selectedKick = false;
auto mouse = mapFromGlobal(_mousePosition);
if (rtl()) mouse.setX(width() - mouse.x());
int left = getListLeft();
int top = getListTop();
int memberRowWidth = width() - left;
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
if (mouse.x() >= left && mouse.x() < left + memberRowWidth && mouse.y() >= top) {
selected = (mouse.y() - top) / st::profileMemberHeight;
if (selected >= _items.size()) {
selected = -1;
} else if (_items[selected]->hasRemoveLink) {
int skip = st::profileMemberPhotoPosition.x();
int nameLeft = left + st::profileMemberNamePosition.x();
int nameTop = top + _selected * st::profileMemberHeight + st::profileMemberNamePosition.y();
int nameWidth = memberRowWidth - st::profileMemberNamePosition.x() - skip;
if (mouse.x() >= nameLeft + nameWidth - _removeWidth && mouse.x() < nameLeft + nameWidth) {
if (mouse.y() >= nameTop && mouse.y() < nameTop + st::normalFont->height) {
selectedKick = true;
}
}
}
}
setSelected(selected, selectedKick);
}
void PeerListWidget::setSelected(int selected, bool selectedRemove) {
if (_selected == selected && _selectedRemove == selectedRemove) {
return;
}
repaintSelectedRow();
if (_selectedRemove != selectedRemove) {
_selectedRemove = selectedRemove;
if (_pressed < 0) {
setCursor(_selectedRemove ? style::cur_pointer : style::cur_default);
}
}
if (_selected != selected) {
_selected = selected;
repaintSelectedRow();
}
}
void PeerListWidget::repaintSelectedRow() {
if (_selected >= 0) {
int left = getListLeft();
rtlupdate(left, getListTop() + _selected * st::profileMemberHeight, width() - left, st::profileMemberHeight);
}
}
int PeerListWidget::getListLeft() const {
return st::profileBlockTitlePosition.x() - st::profileMemberPaddingLeft;
}
void PeerListWidget::preloadPhotos() {
int top = getListTop();
int preloadFor = (_visibleBottom - _visibleTop) * PreloadHeightsCount;
int from = floorclamp(_visibleTop - top, st::profileMemberHeight, 0, _items.size());
int to = ceilclamp(_visibleBottom + preloadFor - top, st::profileMemberHeight, 0, _items.size());
for (int i = from; i < to; ++i) {
_items[i]->peer->loadUserpic();
}
}
void PeerListWidget::refreshVisibility() {
setVisible(!_items.isEmpty());
}
} // namespace Profile

View File

@ -0,0 +1,139 @@
/*
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
*/
#pragma once
#include "profile/profile_block_widget.h"
namespace Notify {
struct PeerUpdate;
} // namespace Notify
namespace Profile {
class PeerListWidget : public BlockWidget {
public:
PeerListWidget(QWidget *parent, PeerData *peer, const QString &title, const QString &removeText = QString());
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
struct Item {
explicit Item(PeerData *peer) : peer(peer) {
}
PeerData * const peer;
Text name;
QString statusText;
bool statusHasOnlineColor = false;
bool hasAdminStar = false;
bool hasRemoveLink = false;
};
virtual int getListTop() const {
return contentTop();
}
int getListLeft() const;
const QList<Item*> &items() const {
return _items;
}
int itemsCount() const {
return _items.size();
}
// Does not take ownership of item.
void addItem(Item *item) {
if (!item) return;
_items.push_back(item);
}
void clearItems() {
_items.clear();
}
void reserveItemsForSize(int size) {
_items.reserve(size);
}
template <typename Predicate>
void sortItems(Predicate predicate) {
qSort(_items.begin(), _items.end(), std_::move(predicate));
}
void setPreloadMoreCallback(base::lambda<void()> &&callback) {
_preloadMoreCallback = std_::move(callback);
}
void setSelectedCallback(base::lambda<void(PeerData*)> &&callback) {
_selectedCallback = std_::move(callback);
}
void setRemovedCallback(base::lambda<void(PeerData*)> &&callback) {
_removedCallback = std_::move(callback);
}
void setUpdateItemCallback(base::lambda<void(Item*)> &&callback) {
_updateItemCallback = std_::move(callback);
}
protected:
void paintOutlinedRect(Painter &p, int x, int y, int w, int h) const;
void refreshVisibility();
// Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override;
void paintContents(Painter &p) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void enterEvent(QEvent *e) override;
void enterFromChildEvent(QEvent *e, QWidget *child) override {
enterEvent(e);
}
void leaveEvent(QEvent *e) override;
void leaveToChildEvent(QEvent *e, QWidget *child) override {
leaveEvent(e);
}
private:
void updateSelection();
void setSelected(int selected, bool selectedRemove);
void repaintSelectedRow();
void preloadPhotos();
void paintItem(Painter &p, int x, int y, Item *item, bool selected, bool selectedRemove);
base::lambda<void()> _preloadMoreCallback;
base::lambda<void(PeerData*)> _selectedCallback;
base::lambda<void(PeerData*)> _removedCallback;
base::lambda<void(Item*)> _updateItemCallback;
QList<Item*> _items;
int _visibleTop = 0;
int _visibleBottom = 0;
int _selected = -1;
int _pressed = -1;
bool _selectedRemove = false;
bool _pressedRemove = false;
QPoint _mousePosition;
QString _removeText;
int _removeWidth = 0;
};
} // namespace Profile

View File

@ -19,7 +19,7 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "profile/profile_settings_widget.h"
#include "profile/profile_block_settings.h"
#include "styles/style_profile.h"
#include "ui/widgets/buttons.h"

View File

@ -19,7 +19,7 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "profile/profile_shared_media_widget.h"
#include "profile/profile_block_shared_media.h"
#include "styles/style_profile.h"
#include "observer_peer.h"

View File

@ -24,12 +24,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Profile {
class SectionMemento;
class BlockWidget : public TWidget, protected base::Subscriber {
Q_OBJECT
public:
BlockWidget(QWidget *parent, PeerData *peer, const QString &title);
virtual void showFinished() {
}
virtual void saveState(SectionMemento *memento) const {
}
virtual void restoreState(const SectionMemento *memento) {
}
protected:
void paintEvent(QPaintEvent *e) override;
virtual void paintContents(Painter &p) {
@ -42,6 +52,7 @@ protected:
int resizeGetHeight(int newWidth) override = 0;
void contentSizeUpdated() {
auto oldHeight = height();
resizeToWidth(width());
emit heightUpdated();
}

View File

@ -24,12 +24,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_profile.h"
#include "styles/style_window.h"
#include "profile/profile_cover.h"
#include "profile/profile_info_widget.h"
#include "profile/profile_settings_widget.h"
#include "profile/profile_invite_link_widget.h"
#include "profile/profile_shared_media_widget.h"
#include "profile/profile_actions_widget.h"
#include "profile/profile_members_widget.h"
#include "profile/profile_block_common_groups.h"
#include "profile/profile_block_info.h"
#include "profile/profile_block_settings.h"
#include "profile/profile_block_invite_link.h"
#include "profile/profile_block_shared_media.h"
#include "profile/profile_block_actions.h"
#include "profile/profile_block_channel_members.h"
#include "profile/profile_block_group_members.h"
#include "apiwrap.h"
namespace Profile {
@ -48,7 +50,16 @@ void InnerWidget::createBlocks() {
auto channel = _peer->asChannel();
auto megagroup = _peer->isMegagroup() ? channel : nullptr;
if (user || channel || megagroup) {
_blocks.push_back({ new InfoWidget(this, _peer), BlockSide::Right });
auto widget = new InfoWidget(this, _peer);
widget->setShowCommonGroupsObservable(&_showCommonGroupsObservable);
_blocks.push_back({ widget, BlockSide::Right });
}
if (user) {
_commonGroupsWidget = new CommonGroupsWidget(this, _peer);
_commonGroupsWidget->setShowCommonGroupsObservable(&_showCommonGroupsObservable);
_blocks.push_back({ _commonGroupsWidget, BlockSide::Right });
} else {
_commonGroupsWidget = nullptr;
}
_blocks.push_back({ new SettingsWidget(this, _peer), BlockSide::Right });
if (chat || channel || megagroup) {
@ -60,7 +71,7 @@ void InnerWidget::createBlocks() {
}
_blocks.push_back({ new ActionsWidget(this, _peer), BlockSide::Right });
if (chat || megagroup) {
auto membersWidget = new MembersWidget(this, _peer);
auto membersWidget = new GroupMembersWidget(this, _peer);
connect(membersWidget, SIGNAL(onlineCountUpdated(int)), _cover, SLOT(onOnlineCountUpdated(int)));
_cover->onOnlineCountUpdated(membersWidget->onlineCount());
_blocks.push_back({ membersWidget, BlockSide::Left });
@ -89,8 +100,23 @@ bool InnerWidget::shareContactButtonShown() const {
return _cover->shareContactButtonShown();
}
void InnerWidget::saveState(SectionMemento *memento) const {
for_const (auto &blockData, _blocks) {
blockData.block->saveState(memento);
}
}
void InnerWidget::restoreState(const SectionMemento *memento) {
for_const (auto &blockData, _blocks) {
blockData.block->restoreState(memento);
}
}
void InnerWidget::showFinished() {
_cover->showFinished();
for_const (auto &blockData, _blocks) {
blockData.block->showFinished();
}
}
void InnerWidget::decreaseAdditionalHeight(int removeHeight) {
@ -182,6 +208,8 @@ void InnerWidget::refreshBlocksPositions() {
continue;
}
blockData.block->moveToLeft(left, top);
blockData.block->setVisibleTopBottom(_visibleTop - top, _visibleBottom - top);
top += blockData.block->height();
}
};

View File

@ -20,10 +20,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "profile/profile_block_common_groups.h"
namespace Profile {
class CoverWidget;
class BlockWidget;
struct CommonGroupsEvent;
class SectionMemento;
class InnerWidget final : public TWidget {
Q_OBJECT
@ -48,6 +52,9 @@ public:
// It should show it only if it is hidden in the cover.
bool shareContactButtonShown() const;
void saveState(SectionMemento *memento) const;
void restoreState(const SectionMemento *memento);
void showFinished();
signals:
@ -110,7 +117,12 @@ private:
};
QList<Block> _blocks;
// We need to save this pointer for getting common groups list for section memento.
CommonGroupsWidget *_commonGroupsWidget = nullptr;
Mode _mode = Mode::OneColumn;
base::Observable<CommonGroupsEvent> _showCommonGroupsObservable;
};
} // namespace Profile

View File

@ -1,713 +0,0 @@
/*
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
*/
#include "stdafx.h"
#include "profile/profile_members_widget.h"
#include "styles/style_profile.h"
#include "mtproto/file_download.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "boxes/contactsbox.h"
#include "boxes/confirmbox.h"
#include "core/click_handler_types.h"
#include "apiwrap.h"
#include "mainwidget.h"
#include "observer_peer.h"
#include "lang.h"
namespace Profile {
using UpdateFlag = Notify::PeerUpdate::Flag;
MembersWidget::MembersWidget(QWidget *parent, PeerData *peer, TitleVisibility titleVisibility)
: BlockWidget(parent, peer, (titleVisibility == TitleVisibility::Visible) ? lang(lng_profile_participants_section) : QString()) {
setMouseTracking(true);
_removeWidth = st::normalFont->width(lang(lng_profile_kick));
_updateOnlineTimer.setSingleShot(true);
connect(&_updateOnlineTimer, SIGNAL(timeout()), this, SLOT(onUpdateOnlineDisplay()));
auto observeEvents = UpdateFlag::AdminsChanged
| UpdateFlag::MembersChanged
| UpdateFlag::UserOnlineChanged;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
notifyPeerUpdated(update);
}));
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
refreshMembers();
}
void MembersWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.peer != peer()) {
if (update.flags & UpdateFlag::UserOnlineChanged) {
if (auto user = update.peer->asUser()) {
refreshUserOnline(user);
}
}
return;
}
if (update.flags & UpdateFlag::MembersChanged) {
refreshMembers();
contentSizeUpdated();
} else if (update.flags & UpdateFlag::AdminsChanged) {
if (auto chat = peer()->asChat()) {
for_const (auto member, _list) {
setMemberFlags(member, chat);
}
} else if (auto megagroup = peer()->asMegagroup()) {
for_const (auto member, _list) {
setMemberFlags(member, megagroup);
}
}
}
this->update();
}
void MembersWidget::refreshUserOnline(UserData *user) {
auto it = _membersByUser.find(user);
if (it == _membersByUser.cend()) return;
_now = unixtime();
auto member = it.value();
member->online = !user->botInfo && App::onlineColorUse(user->onlineTill, _now);
member->onlineTill = user->onlineTill;
member->onlineForSort = user->isSelf() ? INT_MAX : App::onlineForSort(user, _now);
member->onlineText = QString();
sortMembers();
update();
}
void MembersWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
if (auto megagroup = peer()->asMegagroup()) {
auto megagroupInfo = megagroup->mgInfo;
if (!megagroupInfo->lastParticipants.isEmpty() && megagroupInfo->lastParticipants.size() < megagroup->membersCount()) {
if (_visibleTop + PreloadHeightsCount * (_visibleBottom - _visibleTop) > height()) {
App::api()->requestLastParticipants(megagroup, false);
}
}
}
preloadUserPhotos();
}
int MembersWidget::resizeGetHeight(int newWidth) {
int newHeight = contentTop();
if (_limitReachedInfo) {
int limitReachedInfoWidth = newWidth - getListLeft();
accumulate_min(limitReachedInfoWidth, st::profileBlockWideWidthMax);
_limitReachedInfo->resizeToWidth(limitReachedInfoWidth);
_limitReachedInfo->moveToLeft(getListLeft(), contentTop());
newHeight = getListTop();
}
newHeight += _list.size() * st::profileMemberHeight;
return newHeight;
}
void MembersWidget::paintContents(Painter &p) {
int left = getListLeft();
int top = getListTop();
int memberRowWidth = width() - left;
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
if (_limitReachedInfo) {
int infoTop = contentTop();
int infoHeight = top - infoTop - st::profileLimitReachedSkip;
paintOutlinedRect(p, left, infoTop, memberRowWidth, infoHeight);
}
_now = unixtime();
int from = floorclamp(_visibleTop - top, st::profileMemberHeight, 0, _list.size());
int to = ceilclamp(_visibleBottom - top, st::profileMemberHeight, 0, _list.size());
for (int i = from; i < to; ++i) {
int y = top + i * st::profileMemberHeight;
bool selected = (i == _selected);
bool selectedKick = selected && _selectedKick;
if (_pressed >= 0) {
if (_pressed != _selected) {
selected = selectedKick = false;
} else if (!_pressedKick) {
_selectedKick = false;
}
}
paintMember(p, left, y, _list.at(i), selected, selectedKick);
}
}
void MembersWidget::paintOutlinedRect(Painter &p, int x, int y, int w, int h) const {
int outlineWidth = st::defaultLeftOutlineButton.outlineWidth;
p.fillRect(rtlrect(x, y, outlineWidth, h, width()), st::defaultLeftOutlineButton.outlineFgOver);
p.fillRect(rtlrect(x + outlineWidth, y, w - outlineWidth, h, width()), st::defaultLeftOutlineButton.textBgOver);
}
void MembersWidget::mouseMoveEvent(QMouseEvent *e) {
_mousePosition = e->globalPos();
updateSelection();
}
void MembersWidget::mousePressEvent(QMouseEvent *e) {
_mousePosition = e->globalPos();
updateSelection();
_pressed = _selected;
_pressedKick = _selectedKick;
}
void MembersWidget::mouseReleaseEvent(QMouseEvent *e) {
_mousePosition = e->globalPos();
updateSelection();
auto pressed = _pressed;
auto pressedKick = _pressedKick;
_pressed = -1;
_pressedKick = false;
if (pressed >= 0 && pressed < _list.size() && pressed == _selected && pressedKick == _selectedKick) {
auto member = _list.at(pressed);
if (pressedKick) {
Ui::showLayer(new KickMemberBox(peer(), member->user));
} else {
Ui::showPeerProfile(member->user);
}
}
setCursor(_selectedKick ? style::cur_pointer : style::cur_default);
repaintSelectedRow();
}
void MembersWidget::enterEvent(QEvent *e) {
_mousePosition = QCursor::pos();
updateSelection();
}
void MembersWidget::leaveEvent(QEvent *e) {
_mousePosition = QPoint(-1, -1);
updateSelection();
}
void MembersWidget::updateSelection() {
int selected = -1;
bool selectedKick = false;
auto mouse = mapFromGlobal(_mousePosition);
if (rtl()) mouse.setX(width() - mouse.x());
int left = getListLeft();
int top = getListTop();
int memberRowWidth = width() - left;
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
if (mouse.x() >= left && mouse.x() < left + memberRowWidth && mouse.y() >= top) {
selected = (mouse.y() - top) / st::profileMemberHeight;
if (selected >= _list.size()) {
selected = -1;
} else if (_list.at(selected)->canBeKicked) {
int skip = st::profileMemberPhotoPosition.x();
int nameLeft = left + st::profileMemberNamePosition.x();
int nameTop = top + _selected * st::profileMemberHeight + st::profileMemberNamePosition.y();
int nameWidth = memberRowWidth - st::profileMemberNamePosition.x() - skip;
if (mouse.x() >= nameLeft + nameWidth - _removeWidth && mouse.x() < nameLeft + nameWidth) {
if (mouse.y() >= nameTop && mouse.y() < nameTop + st::normalFont->height) {
selectedKick = true;
}
}
}
}
setSelected(selected, selectedKick);
}
void MembersWidget::setSelected(int selected, bool selectedKick) {
if (_selected == selected && _selectedKick == selectedKick) {
return;
}
repaintSelectedRow();
if (_selectedKick != selectedKick) {
_selectedKick = selectedKick;
if (_pressed < 0) {
setCursor(_selectedKick ? style::cur_pointer : style::cur_default);
}
}
if (_selected != selected) {
_selected = selected;
repaintSelectedRow();
}
}
void MembersWidget::repaintSelectedRow() {
if (_selected >= 0) {
int left = getListLeft();
rtlupdate(left, getListTop() + _selected * st::profileMemberHeight, width() - left, st::profileMemberHeight);
}
}
int MembersWidget::getListLeft() const {
return st::profileBlockTitlePosition.x() - st::profileMemberPaddingLeft;
}
int MembersWidget::getListTop() const {
int result = contentTop();
if (_limitReachedInfo) {
result += _limitReachedInfo->height();
result += st::profileLimitReachedSkip;
}
return result;
}
void MembersWidget::refreshMembers() {
_now = unixtime();
if (auto chat = peer()->asChat()) {
checkSelfAdmin(chat);
if (chat->noParticipantInfo()) {
App::api()->requestFullPeer(chat);
}
fillChatMembers(chat);
refreshLimitReached();
} else if (auto megagroup = peer()->asMegagroup()) {
checkSelfAdmin(megagroup);
auto megagroupInfo = megagroup->mgInfo;
if (megagroupInfo->lastParticipants.isEmpty() || megagroup->lastParticipantsCountOutdated()) {
App::api()->requestLastParticipants(megagroup);
}
fillMegagroupMembers(megagroup);
}
sortMembers();
refreshVisibility();
}
void MembersWidget::refreshLimitReached() {
auto chat = peer()->asChat();
if (!chat) return;
bool limitReachedShown = (_list.size() >= Global::ChatSizeMax()) && chat->amCreator() && !emptyTitle();
if (limitReachedShown && !_limitReachedInfo) {
_limitReachedInfo.create(this, st::profileLimitReachedLabel, st::profileLimitReachedStyle);
QString title = textRichPrepare(lng_profile_migrate_reached(lt_count, Global::ChatSizeMax()));
QString body = textRichPrepare(lang(lng_profile_migrate_body));
QString link = textRichPrepare(lang(lng_profile_migrate_learn_more));
QString text = qsl("%1%2%3\n%4 [a href=\"https://telegram.org/blog/supergroups5k\"]%5[/a]").arg(textcmdStartSemibold()).arg(title).arg(textcmdStopSemibold()).arg(body).arg(link);
_limitReachedInfo->setRichText(text);
_limitReachedInfo->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) {
Ui::showLayer(new ConvertToSupergroupBox(peer()->asChat()));
return false;
});
} else if (!limitReachedShown && _limitReachedInfo) {
_limitReachedInfo.destroy();
}
}
void MembersWidget::checkSelfAdmin(ChatData *chat) {
if (chat->participants.isEmpty()) return;
auto self = App::self();
if (chat->amAdmin() && !chat->admins.contains(self)) {
chat->admins.insert(self);
} else if (!chat->amAdmin() && chat->admins.contains(self)) {
chat->admins.remove(self);
}
}
void MembersWidget::checkSelfAdmin(ChannelData *megagroup) {
if (megagroup->mgInfo->lastParticipants.isEmpty()) return;
bool amAdmin = (megagroup->amCreator() || megagroup->amEditor());
auto self = App::self();
if (amAdmin && !megagroup->mgInfo->lastAdmins.contains(self)) {
megagroup->mgInfo->lastAdmins.insert(self);
} else if (!amAdmin && megagroup->mgInfo->lastAdmins.contains(self)) {
megagroup->mgInfo->lastAdmins.remove(self);
}
}
void MembersWidget::preloadUserPhotos() {
int top = getListTop();
int preloadFor = (_visibleBottom - _visibleTop) * PreloadHeightsCount;
int from = floorclamp(_visibleTop - top, st::profileMemberHeight, 0, _list.size());
int to = ceilclamp(_visibleBottom + preloadFor - top, st::profileMemberHeight, 0, _list.size());
for (int i = from; i < to; ++i) {
_list.at(i)->user->loadUserpic();
}
}
void MembersWidget::refreshVisibility() {
setVisible(!_list.isEmpty());
}
void MembersWidget::sortMembers() {
if (!_sortByOnline || _list.isEmpty()) return;
qSort(_list.begin(), _list.end(), [](Member *a, Member *b) -> bool {
return a->onlineForSort > b->onlineForSort;
});
updateOnlineCount();
}
void MembersWidget::updateOnlineCount() {
bool onlyMe = true;
int newOnlineCount = 0;
for_const (auto member, _list) {
bool isOnline = !member->user->botInfo && App::onlineColorUse(member->onlineTill, _now);
if (member->online != isOnline) {
member->online = isOnline;
member->onlineText = QString();
}
if (member->online) {
++newOnlineCount;
if (!member->user->isSelf()) {
onlyMe = false;
}
}
}
if (newOnlineCount == 1 && onlyMe) {
newOnlineCount = 0;
}
if (_onlineCount != newOnlineCount) {
_onlineCount = newOnlineCount;
emit onlineCountUpdated(_onlineCount);
}
}
MembersWidget::Member *MembersWidget::addUser(ChatData *chat, UserData *user) {
auto member = getMember(user);
setMemberFlags(member, chat);
_list.push_back(member);
return member;
}
void MembersWidget::fillChatMembers(ChatData *chat) {
if (chat->participants.isEmpty()) return;
_list.clear();
if (!chat->amIn()) return;
_sortByOnline = true;
_list.reserve(chat->participants.size());
addUser(chat, App::self())->onlineForSort = INT_MAX; // Put me on the first place.
for (auto i = chat->participants.cbegin(), e = chat->participants.cend(); i != e; ++i) {
auto user = i.key();
if (!user->isSelf()) {
addUser(chat, user);
}
}
}
void MembersWidget::setMemberFlags(Member *member, ChatData *chat) {
auto isCreator = (chat->creator == peerToUser(member->user->id));
auto isAdmin = chat->admins.contains(member->user);
member->isAdmin = isCreator || isAdmin;
if (member->user->id == peerFromUser(MTP::authedId())) {
member->canBeKicked = false;
} else if (chat->amCreator() || (chat->amAdmin() && !member->isAdmin)) {
member->canBeKicked = true;
} else {
member->canBeKicked = chat->invitedByMe.contains(member->user);
}
}
MembersWidget::Member *MembersWidget::addUser(ChannelData *megagroup, UserData *user) {
auto member = getMember(user);
setMemberFlags(member, megagroup);
_list.push_back(member);
return member;
}
void MembersWidget::fillMegagroupMembers(ChannelData *megagroup) {
t_assert(megagroup->mgInfo != nullptr);
if (megagroup->mgInfo->lastParticipants.isEmpty()) return;
if (!megagroup->canViewMembers()) {
_list.clear();
return;
}
_sortByOnline = (megagroup->membersCount() > 0 && megagroup->membersCount() <= Global::ChatSizeMax());
auto &membersList = megagroup->mgInfo->lastParticipants;
if (_sortByOnline) {
_list.clear();
_list.reserve(membersList.size());
if (megagroup->amIn()) {
addUser(megagroup, App::self())->onlineForSort = INT_MAX;
}
} else if (membersList.size() >= _list.size()) {
if (addUsersToEnd(megagroup)) {
return;
}
}
if (!_sortByOnline) {
_list.clear();
_list.reserve(membersList.size());
}
for_const (auto user, membersList) {
if (!_sortByOnline || !user->isSelf()) {
addUser(megagroup, user);
}
}
}
bool MembersWidget::addUsersToEnd(ChannelData *megagroup) {
auto &membersList = megagroup->mgInfo->lastParticipants;
for (int i = 0, count = _list.size(); i < count; ++i) {
if (_list.at(i)->user != membersList.at(i)) {
return false;
}
}
_list.reserve(membersList.size());
for (int i = _list.size(), count = membersList.size(); i < count; ++i) {
addUser(megagroup, membersList.at(i));
}
return true;
}
void MembersWidget::setMemberFlags(Member *member, ChannelData *megagroup) {
auto amCreatorOrAdmin = (peerToUser(member->user->id) == MTP::authedId()) && (megagroup->amCreator() || megagroup->amEditor());
auto isAdmin = megagroup->mgInfo->lastAdmins.contains(member->user);
member->isAdmin = amCreatorOrAdmin || isAdmin;
if (member->user->isSelf()) {
member->canBeKicked = false;
} else if (megagroup->amCreator() || (megagroup->amEditor() && !member->isAdmin)) {
member->canBeKicked = true;
} else {
member->canBeKicked = false;
}
}
MembersWidget::Member *MembersWidget::getMember(UserData *user) {
auto it = _membersByUser.constFind(user);
if (it == _membersByUser.cend()) {
auto member = new Member(user);
it = _membersByUser.insert(user, member);
member->online = !user->botInfo && App::onlineColorUse(user->onlineTill, _now);
member->onlineTill = user->onlineTill;
member->onlineForSort = App::onlineForSort(user, _now);
}
return it.value();
}
void MembersWidget::paintMember(Painter &p, int x, int y, Member *member, bool selected, bool selectedKick) {
int memberRowWidth = width() - x;
if (selected) {
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
paintOutlinedRect(p, x, y, memberRowWidth, st::profileMemberHeight);
}
int skip = st::profileMemberPhotoPosition.x();
member->user->paintUserpicLeft(p, st::profileMemberPhotoSize, x + st::profileMemberPhotoPosition.x(), y + st::profileMemberPhotoPosition.y(), width());
if (member->name.isEmpty()) {
member->name.setText(st::semiboldFont, App::peerName(member->user), _textNameOptions);
}
int nameLeft = x + st::profileMemberNamePosition.x();
int nameTop = y + st::profileMemberNamePosition.y();
int nameWidth = memberRowWidth - st::profileMemberNamePosition.x() - skip;
if (member->canBeKicked && selected) {
p.setFont(selectedKick ? st::normalFont->underline() : st::normalFont);
p.setPen(st::windowActiveTextFg);
p.drawTextLeft(nameLeft + nameWidth - _removeWidth, nameTop, width(), lang(lng_profile_kick), _removeWidth);
nameWidth -= _removeWidth + skip;
}
if (member->isAdmin) {
nameWidth -= st::profileMemberAdminIcon.width();
int iconLeft = nameLeft + qMin(nameWidth, member->name.maxWidth());
st::profileMemberAdminIcon.paint(p, QPoint(iconLeft, nameTop), width());
}
p.setPen(st::profileMemberNameFg);
member->name.drawLeftElided(p, nameLeft, nameTop, nameWidth, width());
if (member->onlineText.isEmpty() || (member->onlineTextTill <= _now)) {
if (member->user->botInfo) {
bool seesAllMessages = (member->user->botInfo->readsAllHistory || member->isAdmin);
member->onlineText = lang(seesAllMessages ? lng_status_bot_reads_all : lng_status_bot_not_reads_all);
member->onlineTextTill = _now + 86400;
} else {
member->online = App::onlineColorUse(member->onlineTill, _now);
member->onlineText = App::onlineText(member->onlineTill, _now);
member->onlineTextTill = _now + App::onlineWillChangeIn(member->onlineTill, _now);
}
}
if (_updateOnlineAt <= _now || _updateOnlineAt > member->onlineTextTill) {
_updateOnlineAt = member->onlineTextTill;
_updateOnlineTimer.start((_updateOnlineAt - _now + 1) * 1000);
}
if (member->online) {
p.setPen(st::profileMemberStatusFgActive);
} else {
p.setPen(selected ? st::profileMemberStatusFgOver : st::profileMemberStatusFg);
}
p.setFont(st::normalFont);
p.drawTextLeft(x + st::profileMemberStatusPosition.x(), y + st::profileMemberStatusPosition.y(), width(), member->onlineText);
}
void MembersWidget::onUpdateOnlineDisplay() {
if (_sortByOnline) {
_now = unixtime();
bool changed = false;
for_const (auto member, _list) {
if (!member->online) {
if (!member->user->isSelf()) {
continue;
} else {
break;
}
}
bool isOnline = !member->user->botInfo && App::onlineColorUse(member->onlineTill, _now);
if (!isOnline) {
changed = true;
}
}
if (changed) {
updateOnlineCount();
}
}
update();
}
MembersWidget::~MembersWidget() {
auto members = base::take(_membersByUser);
for_const (auto member, members) {
delete member;
}
}
ChannelMembersWidget::ChannelMembersWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_participants_section)) {
auto observeEvents = UpdateFlag::ChannelCanViewAdmins
| UpdateFlag::ChannelCanViewMembers
| UpdateFlag::AdminsChanged
| UpdateFlag::MembersChanged;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
notifyPeerUpdated(update);
}));
refreshButtons();
}
void ChannelMembersWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.peer != peer()) {
return;
}
if (update.flags & (UpdateFlag::ChannelCanViewAdmins | UpdateFlag::AdminsChanged)) {
refreshAdmins();
}
if (update.flags & (UpdateFlag::ChannelCanViewMembers | UpdateFlag::MembersChanged)) {
refreshMembers();
}
refreshVisibility();
contentSizeUpdated();
}
void ChannelMembersWidget::addButton(const QString &text, ChildWidget<Ui::LeftOutlineButton> *button, const char *slot) {
if (text.isEmpty()) {
button->destroy();
} else if (*button) {
(*button)->setText(text);
} else {
(*button) = new Ui::LeftOutlineButton(this, text, st::defaultLeftOutlineButton);
(*button)->show();
connect(*button, SIGNAL(clicked()), this, slot);
}
}
void ChannelMembersWidget::refreshButtons() {
refreshAdmins();
refreshMembers();
refreshVisibility();
}
void ChannelMembersWidget::refreshAdmins() {
auto getAdminsText = [this]() -> QString {
if (auto channel = peer()->asChannel()) {
if (!channel->isMegagroup() && channel->canViewAdmins()) {
int adminsCount = qMax(channel->adminsCount(), 1);
return lng_channel_admins_link(lt_count, adminsCount);
}
}
return QString();
};
addButton(getAdminsText(), &_admins, SLOT(onAdmins()));
}
void ChannelMembersWidget::refreshMembers() {
auto getMembersText = [this]() -> QString {
if (auto channel = peer()->asChannel()) {
if (!channel->isMegagroup() && channel->canViewMembers()) {
int membersCount = qMax(channel->membersCount(), 1);
return lng_channel_members_link(lt_count, membersCount);
}
}
return QString();
};
addButton(getMembersText(), &_members, SLOT(onMembers()));
}
void ChannelMembersWidget::refreshVisibility() {
setVisible(_admins || _members);
}
int ChannelMembersWidget::resizeGetHeight(int newWidth) {
int newHeight = contentTop();
auto resizeButton = [this, &newHeight, newWidth](ChildWidget<Ui::LeftOutlineButton> &button) {
if (!button) {
return;
}
int left = defaultOutlineButtonLeft();
int availableWidth = newWidth - left - st::profileBlockMarginRight;
accumulate_min(availableWidth, st::profileBlockOneLineWidthMax);
button->resizeToWidth(availableWidth);
button->moveToLeft(left, newHeight);
newHeight += button->height();
};
resizeButton(_admins);
resizeButton(_members);
return newHeight;
}
void ChannelMembersWidget::onAdmins() {
if (auto channel = peer()->asChannel()) {
Ui::showLayer(new MembersBox(channel, MembersFilter::Admins));
}
}
void ChannelMembersWidget::onMembers() {
if (auto channel = peer()->asChannel()) {
Ui::showLayer(new MembersBox(channel, MembersFilter::Recent));
}
}
} // namespace Profile

View File

@ -27,8 +27,7 @@ namespace Profile {
Window::SectionWidget *SectionMemento::createWidget(QWidget *parent, const QRect &geometry) const {
auto result = new Widget(parent, _peer);
result->setGeometry(geometry);
result->setInternalState(this);
result->setInternalState(geometry, this);
return result;
}

View File

@ -33,11 +33,26 @@ public:
Window::SectionWidget *createWidget(QWidget *parent, const QRect &geometry) const override;
private:
friend class Widget;
PeerData *getPeer() const {
return _peer;
}
void setScrollTop(int scrollTop) {
_scrollTop = scrollTop;
}
int getScrollTop() const {
return _scrollTop;
}
void setCommonGroups(const QList<PeerData*> &groups) {
_commonGroups = groups;
}
const QList<PeerData*> &getCommonGroups() const {
return _commonGroups;
}
private:
PeerData *_peer;
int _scrollTop = 0;
QList<PeerData*> _commonGroups;
};

View File

@ -74,28 +74,38 @@ void Widget::setInnerFocus() {
bool Widget::showInternal(const Window::SectionMemento *memento) {
if (auto profileMemento = dynamic_cast<const SectionMemento*>(memento)) {
if (profileMemento->_peer == peer()) {
// Perhaps no need to do that?..
_scroll->scrollToY(profileMemento->_scrollTop);
if (profileMemento->getPeer() == peer()) {
restoreState(profileMemento);
return true;
}
}
return false;
}
void Widget::setInternalState(const SectionMemento *memento) {
void Widget::setInternalState(const QRect &geometry, const SectionMemento *memento) {
setGeometry(geometry);
myEnsureResized(this);
_scroll->scrollToY(memento->_scrollTop);
_fixedBarShadow->setMode(memento->_scrollTop > 0 ? Ui::ToggleableShadow::Mode::ShownFast : Ui::ToggleableShadow::Mode::HiddenFast);
restoreState(memento);
}
std_::unique_ptr<Window::SectionMemento> Widget::createMemento() const {
auto result = std_::make_unique<SectionMemento>(peer());
result->_scrollTop = _scroll->scrollTop();
saveState(result.get());
return std_::move(result);
}
void Widget::saveState(SectionMemento *memento) const {
memento->setScrollTop(_scroll->scrollTop());
_inner->saveState(memento);
}
void Widget::restoreState(const SectionMemento *memento) {
_inner->restoreState(memento);
auto scrollTop = memento->getScrollTop();
_scroll->scrollToY(scrollTop);
_fixedBarShadow->setMode((scrollTop > 0) ? Ui::ToggleableShadow::Mode::ShownFast : Ui::ToggleableShadow::Mode::HiddenFast);
}
void Widget::resizeEvent(QResizeEvent *e) {
if (!width() || !height()) {
return;

View File

@ -54,7 +54,7 @@ public:
bool showInternal(const Window::SectionMemento *memento) override;
std_::unique_ptr<Window::SectionMemento> createMemento() const override;
void setInternalState(const SectionMemento *memento);
void setInternalState(const QRect &geometry, const SectionMemento *memento);
protected:
void resizeEvent(QResizeEvent *e) override;
@ -67,8 +67,8 @@ private slots:
private:
void updateAdaptiveLayout();
friend class SectionMemento;
void saveState(SectionMemento *memento) const;
void restoreState(const SectionMemento *memento);
ChildWidget<Ui::ScrollArea> _scroll;
ChildWidget<InnerWidget> _inner;

View File

@ -282,6 +282,13 @@ bool UserData::setAbout(const QString &newAbout) {
return true;
}
void UserData::setCommonChatsCount(int count) {
if (_commonChatsCount != count) {
_commonChatsCount = count;
Notify::peerUpdatedDelayed(this, UpdateFlag::UserCommonChatsChanged);
}
}
void UserData::setName(const QString &newFirstName, const QString &newLastName, const QString &newPhoneName, const QString &newUsername) {
bool changeName = !newFirstName.isEmpty() || !newLastName.isEmpty();

View File

@ -468,11 +468,17 @@ public:
_restrictionReason = reason;
}
int commonChatsCount() const {
return _commonChatsCount;
}
void setCommonChatsCount(int count);
private:
QString _restrictionReason;
QString _about;
QString _phone;
BlockStatus _blockStatus = BlockStatus::Unknown;
int _commonChatsCount = 0;
};
@ -615,14 +621,6 @@ private:
};
struct MegagroupInfo {
MegagroupInfo()
: botStatus(0)
, pinnedMsgId(0)
, joinedMessageFound(false)
, lastParticipantsStatus(LastParticipantsUpToDate)
, lastParticipantsCount(0)
, migrateFromPtr(0) {
}
typedef QList<UserData*> LastParticipants;
LastParticipants lastParticipants;
typedef OrderedSet<UserData*> LastAdmins;
@ -631,20 +629,20 @@ struct MegagroupInfo {
MarkupSenders markupSenders;
typedef OrderedSet<UserData*> Bots;
Bots bots;
int32 botStatus; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
MsgId pinnedMsgId;
bool joinedMessageFound;
int botStatus = 0; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
MsgId pinnedMsgId = 0;
bool joinedMessageFound = false;
enum LastParticipantsStatus {
LastParticipantsUpToDate = 0x00,
LastParticipantsAdminsOutdated = 0x01,
LastParticipantsCountOutdated = 0x02,
};
mutable int32 lastParticipantsStatus;
int32 lastParticipantsCount;
mutable int lastParticipantsStatus = LastParticipantsUpToDate;
int lastParticipantsCount = 0;
ChatData *migrateFromPtr;
ChatData *migrateFromPtr = nullptr;
};
class ChannelData : public PeerData {
@ -657,6 +655,9 @@ public:
void updateFull(bool force = false);
void fullUpdated();
bool wasFullUpdated() const {
return (_lastFullUpdate != 0);
}
uint64 access = 0;
@ -798,6 +799,12 @@ public:
void ptsWaitingForShortPoll(int32 ms) { // < 0 - not waiting
return _ptsWaiter.setWaitingForShortPoll(this, ms);
}
bool ptsWaitingForSkipped() const {
return _ptsWaiter.waitingForSkipped();
}
bool ptsWaitingForShortPoll() const {
return _ptsWaiter.waitingForShortPoll();
}
QString restrictionReason() const override {
return _restrictionReason;

View File

@ -24,7 +24,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwindow.h"
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/shadow.h"
#include "profile/profile_members_widget.h"
#include "ui/effects/panel_animation.h"
namespace {

View File

@ -390,8 +390,24 @@
'<(src_loc)/platform/platform_main_window.h',
'<(src_loc)/platform/platform_notifications_manager.h',
'<(src_loc)/platform/platform_window_title.h',
'<(src_loc)/profile/profile_actions_widget.cpp',
'<(src_loc)/profile/profile_actions_widget.h',
'<(src_loc)/profile/profile_block_actions.cpp',
'<(src_loc)/profile/profile_block_actions.h',
'<(src_loc)/profile/profile_block_channel_members.cpp',
'<(src_loc)/profile/profile_block_channel_members.h',
'<(src_loc)/profile/profile_block_common_groups.cpp',
'<(src_loc)/profile/profile_block_common_groups.h',
'<(src_loc)/profile/profile_block_info.cpp',
'<(src_loc)/profile/profile_block_info.h',
'<(src_loc)/profile/profile_block_invite_link.cpp',
'<(src_loc)/profile/profile_block_invite_link.h',
'<(src_loc)/profile/profile_block_group_members.cpp',
'<(src_loc)/profile/profile_block_group_members.h',
'<(src_loc)/profile/profile_block_peer_list.cpp',
'<(src_loc)/profile/profile_block_peer_list.h',
'<(src_loc)/profile/profile_block_settings.cpp',
'<(src_loc)/profile/profile_block_settings.h',
'<(src_loc)/profile/profile_block_shared_media.cpp',
'<(src_loc)/profile/profile_block_shared_media.h',
'<(src_loc)/profile/profile_block_widget.cpp',
'<(src_loc)/profile/profile_block_widget.h',
'<(src_loc)/profile/profile_cover_drop_area.cpp',
@ -400,20 +416,10 @@
'<(src_loc)/profile/profile_cover.h',
'<(src_loc)/profile/profile_fixed_bar.cpp',
'<(src_loc)/profile/profile_fixed_bar.h',
'<(src_loc)/profile/profile_info_widget.cpp',
'<(src_loc)/profile/profile_info_widget.h',
'<(src_loc)/profile/profile_inner_widget.cpp',
'<(src_loc)/profile/profile_inner_widget.h',
'<(src_loc)/profile/profile_invite_link_widget.cpp',
'<(src_loc)/profile/profile_invite_link_widget.h',
'<(src_loc)/profile/profile_members_widget.cpp',
'<(src_loc)/profile/profile_members_widget.h',
'<(src_loc)/profile/profile_section_memento.cpp',
'<(src_loc)/profile/profile_section_memento.h',
'<(src_loc)/profile/profile_settings_widget.cpp',
'<(src_loc)/profile/profile_settings_widget.h',
'<(src_loc)/profile/profile_shared_media_widget.cpp',
'<(src_loc)/profile/profile_shared_media_widget.h',
'<(src_loc)/profile/profile_userpic_button.cpp',
'<(src_loc)/profile/profile_userpic_button.h',
'<(src_loc)/profile/profile_widget.cpp',