From 2c4ec3d9f3d26b65a19548d1eaab4f52045f8866 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 2 Jun 2016 16:02:55 +0300 Subject: [PATCH] Shared media block done in the new profile implementation. Preparing to call Notify::peerUpdatedSendDelayed() only from event loop. --- Telegram/Resources/langs/lang.strings | 16 +-- Telegram/SourceFiles/apiwrap.cpp | 59 +++++---- Telegram/SourceFiles/app.cpp | 46 +++---- Telegram/SourceFiles/application.cpp | 4 + Telegram/SourceFiles/application.h | 1 + Telegram/SourceFiles/boxes/confirmbox.cpp | 1 + Telegram/SourceFiles/boxes/contactsbox.cpp | 31 ++--- Telegram/SourceFiles/facades.cpp | 2 + Telegram/SourceFiles/facades.h | 1 + Telegram/SourceFiles/history.cpp | 33 ++--- Telegram/SourceFiles/historywidget.cpp | 29 +++-- Telegram/SourceFiles/mainwidget.cpp | 13 +- Telegram/SourceFiles/mainwindow.cpp | 12 +- Telegram/SourceFiles/observer_peer.cpp | 9 +- Telegram/SourceFiles/observer_peer.h | 43 ++++--- Telegram/SourceFiles/overviewwidget.cpp | 8 +- .../profile/profile_actions_widget.cpp | 30 +++-- .../profile/profile_actions_widget.h | 5 +- .../profile/profile_block_widget.cpp | 4 + .../profile/profile_block_widget.h | 6 +- .../SourceFiles/profile/profile_cover.cpp | 10 +- .../SourceFiles/profile/profile_info_widget.h | 3 +- .../profile/profile_inner_widget.cpp | 4 +- .../profile/profile_invite_link_widget.h | 3 +- .../profile/profile_members_widget.cpp | 109 +++++++++++++++- .../profile/profile_members_widget.h | 28 +++++ .../profile/profile_settings_widget.cpp | 11 +- .../profile/profile_settings_widget.h | 3 +- .../profile/profile_shared_media_widget.cpp | 117 +++++++++++++++++- .../profile/profile_shared_media_widget.h | 27 ++++ Telegram/SourceFiles/profilewidget.cpp | 42 +++---- Telegram/SourceFiles/structs.cpp | 18 +++ Telegram/SourceFiles/structs.h | 27 +++- Telegram/Telegram.vcxproj | 54 +++++++- Telegram/Telegram.vcxproj.filters | 30 ++++- 35 files changed, 646 insertions(+), 193 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 1439518f5..753f79ac7 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -117,8 +117,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_channel_status" = "channel"; "lng_group_status" = "group"; -"lng_channel_members_link" = "{count:_not_used_|# member|# members} »"; -"lng_channel_admins_link" = "{count:Manage administrators|# administrator|# administrators} »"; +"lng_channel_members_link" = "{count:_not_used_|# member|# members}"; +"lng_channel_admins_link" = "{count:_not_used_|# administrator|# administrators}"; "lng_server_error" = "Internal server error."; "lng_flood_error" = "Too many tries. Please try again later."; @@ -446,17 +446,17 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_profile_loading" = "Loading..."; "lng_profile_shared_media" = "Shared media"; "lng_profile_no_media" = "No media in this conversation."; -"lng_profile_photos" = "{count:_not_used_|# photo|# photos} »"; +"lng_profile_photos" = "{count:_not_used_|# photo|# photos}"; "lng_profile_photos_header" = "Photos overview"; -"lng_profile_videos" = "{count:_not_used_|# video file|# video files} »"; +"lng_profile_videos" = "{count:_not_used_|# video file|# video files}"; "lng_profile_videos_header" = "Video files overview"; -"lng_profile_songs" = "{count:_not_used_|# audio file|# audio files} »"; +"lng_profile_songs" = "{count:_not_used_|# audio file|# audio files}"; "lng_profile_songs_header" = "Audio files overview"; -"lng_profile_files" = "{count:_not_used_|# file|# files} »"; +"lng_profile_files" = "{count:_not_used_|# file|# files}"; "lng_profile_files_header" = "Files overview"; -"lng_profile_audios" = "{count:_not_used_|# voice message|# voice messages} »"; +"lng_profile_audios" = "{count:_not_used_|# voice message|# voice messages}"; "lng_profile_audios_header" = "Voice messages overview"; -"lng_profile_shared_links" = "{count:_not_used_|# shared link|# shared links} »"; +"lng_profile_shared_links" = "{count:_not_used_|# shared link|# shared links}"; "lng_profile_shared_links_header" = "Shared links overview"; "lng_profile_copy_phone" = "Copy phone number"; "lng_profile_copy_fullname" = "Copy name"; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 361295ef2..7baab31b1 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -226,6 +226,10 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt const auto &f(d.vfull_chat.c_channelFull()); PhotoData *photo = App::feedPhoto(f.vchat_photo); ChannelData *channel = peer->asChannel(); + + auto canViewAdmins = channel->canViewAdmins(); + auto canViewMembers = channel->canViewMembers(); + channel->flagsFull = f.vflags.v; if (photo) { channel->photoId = photo->id; @@ -277,15 +281,8 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt } } channel->setAbout(qs(f.vabout)); - int32 newCount = f.has_participants_count() ? f.vparticipants_count.v : 0; - if (newCount != channel->count) { - if (channel->isMegagroup() && !channel->mgInfo->lastParticipants.isEmpty()) { - channel->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsCountOutdated; - channel->mgInfo->lastParticipantsCount = channel->count; - } - channel->count = newCount; - } - channel->adminsCount = f.has_admins_count() ? f.vadmins_count.v : 0; + channel->setMembersCount(f.has_participants_count() ? f.vparticipants_count.v : 0); + channel->setAdminsCount(f.has_admins_count() ? f.vadmins_count.v : 0); channel->setInviteLink((f.vexported_invite.type() == mtpc_chatInviteExported) ? qs(f.vexported_invite.c_chatInviteExported().vlink) : QString()); if (History *h = App::historyLoaded(channel->id)) { if (h->inboxReadBefore < f.vread_inbox_max_id.v + 1) { @@ -303,6 +300,9 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt } channel->fullUpdated(); + if (canViewAdmins != channel->canViewAdmins()) Notify::peerUpdatedDelayed(channel, Notify::PeerUpdate::Flag::ChannelCanViewAdmins); + if (canViewMembers != channel->canViewMembers()) Notify::peerUpdatedDelayed(channel, Notify::PeerUpdate::Flag::ChannelCanViewMembers); + notifySettingReceived(MTP_inputNotifyPeer(peer->input), f.vnotify_settings); } @@ -549,16 +549,16 @@ void ApiWrap::lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelP h->clearLastKeyboard(); if (App::main()) App::main()->updateBotKeyboard(h); } - if (d.vcount.v > peer->count) { - peer->count = d.vcount.v; - } else if (v.count() > peer->count) { - peer->count = v.count(); + int newMembersCount = qMax(d.vcount.v, v.count()); + if (newMembersCount > peer->membersCount()) { + peer->setMembersCount(newMembersCount); } if (!bots && v.isEmpty()) { - peer->count = peer->mgInfo->lastParticipants.size(); + peer->setMembersCount(peer->mgInfo->lastParticipants.size()); } peer->mgInfo->botStatus = botStatus; if (App::main()) emit fullPeerUpdated(peer); + Notify::peerUpdatedSendDelayed(); } bool ApiWrap::lastParticipantsFail(ChannelData *peer, const RPCError &error, mtpRequestId req) { @@ -637,28 +637,33 @@ void ApiWrap::kickParticipant(PeerData *peer, UserData *user) { void ApiWrap::kickParticipantDone(KickRequest kick, const MTPUpdates &result, mtpRequestId req) { _kickRequests.remove(kick); if (kick.first->isMegagroup()) { - int32 i = kick.first->asChannel()->mgInfo->lastParticipants.indexOf(kick.second); + auto channel = kick.first->asChannel(); + auto megagroupInfo = channel->mgInfo; + + int32 i = megagroupInfo->lastParticipants.indexOf(kick.second); if (i >= 0) { - kick.first->asChannel()->mgInfo->lastParticipants.removeAt(i); + megagroupInfo->lastParticipants.removeAt(i); } - if (kick.first->asChannel()->count > 1) { - --kick.first->asChannel()->count; + + if (channel->membersCount() > 1) { + channel->setMembersCount(channel->membersCount() - 1); } else { - kick.first->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsCountOutdated; - kick.first->asChannel()->mgInfo->lastParticipantsCount = 0; + megagroupInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsCountOutdated; + megagroupInfo->lastParticipantsCount = 0; } - if (kick.first->asChannel()->mgInfo->lastAdmins.contains(kick.second)) { - kick.first->asChannel()->mgInfo->lastAdmins.remove(kick.second); - if (kick.first->asChannel()->adminsCount > 1) { - --kick.first->asChannel()->adminsCount; + if (megagroupInfo->lastAdmins.contains(kick.second)) { + megagroupInfo->lastAdmins.remove(kick.second); + if (channel->adminsCount() > 1) { + channel->setAdminsCount(channel->adminsCount() - 1); } } - kick.first->asChannel()->mgInfo->bots.remove(kick.second); - if (kick.first->asChannel()->mgInfo->bots.isEmpty() && kick.first->asChannel()->mgInfo->botStatus > 0) { - kick.first->asChannel()->mgInfo->botStatus = -1; + megagroupInfo->bots.remove(kick.second); + if (megagroupInfo->bots.isEmpty() && megagroupInfo->botStatus > 0) { + megagroupInfo->botStatus = -1; } } emit fullPeerUpdated(kick.first); + Notify::peerUpdatedSendDelayed(); } bool ApiWrap::kickParticipantFail(KickRequest kick, const RPCError &error, mtpRequestId req) { diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 74889f624..3b449d87c 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -656,7 +656,9 @@ namespace { auto cdata = data->asChannel(); auto wasInChannel = cdata->amIn(); auto canEditPhoto = cdata->canEditPhoto(); - auto canAddMembers = cdata->canAddParticipants(); + auto canViewAdmins = cdata->canViewAdmins(); + auto canViewMembers = cdata->canViewMembers(); + auto canAddMembers = cdata->canAddMembers(); auto wasEditor = cdata->amEditor(); if (minimal) { @@ -683,18 +685,12 @@ namespace { cdata->flagsUpdated(); cdata->setPhoto(d.vphoto); - if (wasInChannel != cdata->amIn()) { - update.flags |= UpdateFlag::ChannelAmIn; - } - if (canEditPhoto != cdata->canEditPhoto()) { - update.flags |= UpdateFlag::ChannelCanEditPhoto; - } - if (canAddMembers != cdata->canAddParticipants()) { - update.flags |= UpdateFlag::ChannelCanAddMembers; - } - if (wasEditor != cdata->amEditor()) { - update.flags |= UpdateFlag::ChannelAmEditor; - } + if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn; + if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto; + if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins; + if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers; + if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers; + if (wasEditor != cdata->amEditor()) update.flags |= UpdateFlag::ChannelAmEditor; } break; case mtpc_channelForbidden: { auto &d(chat.c_channelForbidden()); @@ -706,7 +702,9 @@ namespace { auto cdata = data->asChannel(); auto wasInChannel = cdata->amIn(); auto canEditPhoto = cdata->canEditPhoto(); - auto canAddMembers = cdata->canAddParticipants(); + auto canViewAdmins = cdata->canViewAdmins(); + auto canViewMembers = cdata->canViewMembers(); + auto canAddMembers = cdata->canAddMembers(); auto wasEditor = cdata->amEditor(); cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash); @@ -716,21 +714,15 @@ namespace { cdata->access = d.vaccess_hash.v; cdata->setPhoto(MTP_chatPhotoEmpty()); cdata->date = 0; - cdata->count = 0; + cdata->setMembersCount(0); cdata->isForbidden = true; - if (wasInChannel != cdata->amIn()) { - update.flags |= UpdateFlag::ChannelAmIn; - } - if (canEditPhoto != cdata->canEditPhoto()) { - update.flags |= UpdateFlag::ChannelCanEditPhoto; - } - if (canAddMembers != cdata->canAddParticipants()) { - update.flags |= UpdateFlag::ChannelCanAddMembers; - } - if (wasEditor != cdata->amEditor()) { - update.flags |= UpdateFlag::ChannelAmEditor; - } + if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn; + if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto; + if (canViewAdmins != cdata->canViewAdmins()) update.flags |= UpdateFlag::ChannelCanViewAdmins; + if (canViewMembers != cdata->canViewMembers()) update.flags |= UpdateFlag::ChannelCanViewMembers; + if (canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelCanAddMembers; + if (wasEditor != cdata->amEditor()) update.flags |= UpdateFlag::ChannelAmEditor; } break; } if (!data) continue; diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index 4ff6daddf..17b9174e7 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -917,6 +917,10 @@ void AppClass::call_handleFileDialogQueue() { } } +void AppClass::call_handleDelayedPeerUpdates() { + Notify::peerUpdatedSendDelayed(); +} + void AppClass::killDownloadSessions() { uint64 ms = getms(), left = MTPAckSendWaiting + MTPKillFileSessionTimeout; for (QMap::iterator i = killDownloadSessionTimes.begin(); i != killDownloadSessionTimes.end(); ) { diff --git a/Telegram/SourceFiles/application.h b/Telegram/SourceFiles/application.h index 953b503e5..b7d595eed 100644 --- a/Telegram/SourceFiles/application.h +++ b/Telegram/SourceFiles/application.h @@ -204,6 +204,7 @@ public slots: void call_handleHistoryUpdate(); void call_handleUnreadCounterUpdate(); void call_handleFileDialogQueue(); + void call_handleDelayedPeerUpdates(); private: diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index f4c044e53..3b2dc1cce 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -477,6 +477,7 @@ void RichDeleteMessageBox::onDelete() { if (HistoryItem *item = App::histItemById(_channel ? peerToChannel(_channel->id) : 0, _msgId)) { bool wasLast = (item->history()->lastMsg == item); item->destroy(); + if (_msgId > 0) { App::main()->deleteMessages(_channel, QVector(1, MTP_int(_msgId))); } else if (wasLast) { diff --git a/Telegram/SourceFiles/boxes/contactsbox.cpp b/Telegram/SourceFiles/boxes/contactsbox.cpp index 3bed2d467..389d3e055 100644 --- a/Telegram/SourceFiles/boxes/contactsbox.cpp +++ b/Telegram/SourceFiles/boxes/contactsbox.cpp @@ -31,6 +31,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/filedialog.h" #include "boxes/photocropbox.h" #include "boxes/confirmbox.h" +#include "observer_peer.h" #include "apiwrap.h" QString cantInviteError() { @@ -740,7 +741,7 @@ int32 ContactsInner::selectedCount() const { if (_chat) { result += qMax(_chat->count, 1); } else if (_channel) { - result += qMax(_channel->count, _already.size()); + result += qMax(_channel->membersCount(), _already.size()); } else if (_creating == CreatingGroupGroup) { result += 1; } @@ -1739,7 +1740,7 @@ bool ContactsBox::creationFail(const RPCError &error) { MembersInner::MembersInner(ChannelData *channel, MembersFilter filter) : TWidget() , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) -, _newItemHeight((channel->amCreator() && (channel->count < (channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!channel->isMegagroup() && !channel->isPublic()) || filter == MembersFilterAdmins)) ? st::contactsNewItemHeight : 0) +, _newItemHeight((channel->amCreator() && (channel->membersCount() < (channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!channel->isMegagroup() && !channel->isPublic()) || filter == MembersFilterAdmins)) ? st::contactsNewItemHeight : 0) , _newItemSel(false) , _channel(channel) , _filter(filter) @@ -1808,7 +1809,7 @@ void MembersInner::paintEvent(QPaintEvent *e) { paintDialog(p, _rows[from], data(from), sel, kickSel, kickDown); p.translate(0, _rowHeight); } - if (to == _rows.size() && _filter == MembersFilterRecent && (_rows.size() < _channel->count || _rows.size() >= Global::ChatSizeMax())) { + if (to == _rows.size() && _filter == MembersFilterRecent && (_rows.size() < _channel->membersCount() || _rows.size() >= Global::ChatSizeMax())) { p.setPen(st::stickersReorderFg); _about.draw(p, st::contactsPadding.left(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center); } @@ -1987,7 +1988,7 @@ void MembersInner::refresh() { } else { _about.setText(st::boxTextFont, lng_channel_only_last_shown(lt_count, _rows.size())); _aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom(); - if (_filter != MembersFilterRecent || (_rows.size() >= _channel->count && _rows.size() < Global::ChatSizeMax())) { + if (_filter != MembersFilterRecent || (_rows.size() >= _channel->membersCount() && _rows.size() < Global::ChatSizeMax())) { _aboutHeight = 0; } resize(width(), st::membersPadding.top() + _newItemHeight + _rows.size() * _rowHeight + st::membersPadding.bottom() + _aboutHeight); @@ -2115,14 +2116,16 @@ void MembersInner::membersReceived(const MTPchannels_ChannelParticipants &result _datas.reserve(v.size()); _dates.reserve(v.size()); _roles.reserve(v.size()); - if (_filter == MembersFilterRecent && _channel->count < d.vcount.v) { - _channel->count = d.vcount.v; + + if (_filter == MembersFilterRecent && _channel->membersCount() < d.vcount.v) { + _channel->setMembersCount(d.vcount.v); if (App::main()) emit App::main()->peerUpdated(_channel); - } else if (_filter == MembersFilterAdmins && _channel->adminsCount < d.vcount.v) { - _channel->adminsCount = d.vcount.v; + } else if (_filter == MembersFilterAdmins && _channel->adminsCount() < d.vcount.v) { + _channel->setAdminsCount(d.vcount.v); if (App::main()) emit App::main()->peerUpdated(_channel); } - App::feedUsers(d.vusers); + App::feedUsersDelayed(d.vusers); + for (QVector::const_iterator i = v.cbegin(), e = v.cend(); i != e; ++i) { int32 userId = 0, addedTime = 0; MemberRole role = MemberRoleNone; @@ -2229,11 +2232,11 @@ void MembersInner::removeKicked() { _dates.removeAt(index); _roles.removeAt(index); clearSel(); - if (_filter == MembersFilterRecent && _channel->count > 1) { - --_channel->count; + if (_filter == MembersFilterRecent && _channel->membersCount() > 1) { + _channel->setMembersCount(_channel->membersCount() - 1); if (App::main()) emit App::main()->peerUpdated(_channel); - } else if (_filter == MembersFilterAdmins && _channel->adminsCount > 1) { - --_channel->adminsCount; + } else if (_filter == MembersFilterAdmins && _channel->adminsCount() > 1) { + _channel->setAdminsCount(_channel->adminsCount() - 1); if (App::main()) emit App::main()->peerUpdated(_channel); } refresh(); @@ -2290,7 +2293,7 @@ void MembersBox::onScroll() { } void MembersBox::onAdd() { - if (_inner.filter() == MembersFilterRecent && _inner.channel()->count >= (_inner.channel()->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) { + if (_inner.filter() == MembersFilterRecent && _inner.channel()->membersCount() >= (_inner.channel()->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) { Ui::showLayer(new MaxInviteBox(_inner.channel()->inviteLink()), KeepOtherLayers); return; } diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 66c42aa98..5480af8d4 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -524,6 +524,7 @@ struct Data { SingleDelayedCall HandleHistoryUpdate = { App::app(), "call_handleHistoryUpdate" }; SingleDelayedCall HandleUnreadCounterUpdate = { App::app(), "call_handleUnreadCounterUpdate" }; SingleDelayedCall HandleFileDialogQueue = { App::app(), "call_handleFileDialogQueue" }; + SingleDelayedCall HandleDelayedPeerUpdates = { App::app(), "call_handleDelayedPeerUpdates" }; Adaptive::Layout AdaptiveLayout = Adaptive::NormalLayout; bool AdaptiveForWide = true; @@ -588,6 +589,7 @@ DefineReadOnlyVar(Global, uint64, LaunchId); DefineRefVar(Global, SingleDelayedCall, HandleHistoryUpdate); DefineRefVar(Global, SingleDelayedCall, HandleUnreadCounterUpdate); DefineRefVar(Global, SingleDelayedCall, HandleFileDialogQueue); +DefineRefVar(Global, SingleDelayedCall, HandleDelayedPeerUpdates); DefineVar(Global, Adaptive::Layout, AdaptiveLayout); DefineVar(Global, bool, AdaptiveForWide); diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index c6fae8f47..a368db47c 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -205,6 +205,7 @@ DeclareReadOnlyVar(uint64, LaunchId); DeclareRefVar(SingleDelayedCall, HandleHistoryUpdate); DeclareRefVar(SingleDelayedCall, HandleUnreadCounterUpdate); DeclareRefVar(SingleDelayedCall, HandleFileDialogQueue); +DeclareRefVar(SingleDelayedCall, HandleDelayedPeerUpdates); DeclareVar(Adaptive::Layout, AdaptiveLayout); DeclareVar(bool, AdaptiveForWide); diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 16917c74f..061a54eb7 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -1098,26 +1098,29 @@ HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction, if (App::main()) App::main()->updateBotKeyboard(this); } if (peer->isMegagroup()) { - if (UserData *user = App::userLoaded(uid)) { - int32 index = peer->asChannel()->mgInfo->lastParticipants.indexOf(user); + if (auto user = App::userLoaded(uid)) { + auto channel = peer->asChannel(); + auto megagroupInfo = channel->mgInfo; + + int32 index = megagroupInfo->lastParticipants.indexOf(user); if (index >= 0) { - peer->asChannel()->mgInfo->lastParticipants.removeAt(index); + megagroupInfo->lastParticipants.removeAt(index); } - if (peer->asChannel()->count > 1) { - --peer->asChannel()->count; + if (peer->asChannel()->membersCount() > 1) { + peer->asChannel()->setMembersCount(channel->membersCount() - 1); } else { - peer->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsCountOutdated; - peer->asChannel()->mgInfo->lastParticipantsCount = 0; + megagroupInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsCountOutdated; + megagroupInfo->lastParticipantsCount = 0; } - if (peer->asChannel()->mgInfo->lastAdmins.contains(user)) { - peer->asChannel()->mgInfo->lastAdmins.remove(user); - if (peer->asChannel()->adminsCount > 1) { - --peer->asChannel()->adminsCount; + if (megagroupInfo->lastAdmins.contains(user)) { + megagroupInfo->lastAdmins.remove(user); + if (channel->adminsCount() > 1) { + channel->setAdminsCount(channel->adminsCount() - 1); } } - peer->asChannel()->mgInfo->bots.remove(user); - if (peer->asChannel()->mgInfo->bots.isEmpty() && peer->asChannel()->mgInfo->botStatus > 0) { - peer->asChannel()->mgInfo->botStatus = -1; + megagroupInfo->bots.remove(user); + if (megagroupInfo->bots.isEmpty() && megagroupInfo->botStatus > 0) { + megagroupInfo->botStatus = -1; } } } @@ -2059,6 +2062,7 @@ void History::getReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScro if (History *h = App::historyLoaded(peer->migrateFrom()->id)) { if (h->unreadCount()) { clear(true); + h->getReadyFor(msgId, fixInScrollMsgId, fixInScrollMsgTop); return; } @@ -2066,6 +2070,7 @@ void History::getReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScro } if (!isReadyFor(msgId, fixInScrollMsgId, fixInScrollMsgTop)) { clear(true); + if (msgId == ShowAtTheEndMsgId) { newLoaded = true; } diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 9aa61c4b8..d403c497b 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -4485,6 +4485,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages } else if (_migrated) { _migrated->clear(true); } + addMessagesToFront(peer, *histList, histCollapsed); if (_fixedInScrollMsgId && _history->isChannel()) { _history->asChannelHistory()->insertCollapseItem(_fixedInScrollMsgId); @@ -4507,6 +4508,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages } else if (_migrated) { _migrated->clear(true); } + _delayedShowAtRequest = 0; bool wasOnlyImportant = _history->isChannel() ? _history->asChannelHistory()->onlyImportant() : true; _history->getReadyFor(_delayedShowAtMsgId, _fixedInScrollMsgId, _fixedInScrollMsgTop); @@ -5094,6 +5096,8 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const App::main()->finishForwarding(h, _broadcast.checked(), _silent.checked()); cancelReply(lastKeyboardUsed); + + Notify::peerUpdatedSendDelayed(); } void HistoryWidget::onSendPaths(const PeerId &peer) { @@ -5999,8 +6003,8 @@ void HistoryWidget::updateOnlineDisplay(int32 x, int32 w) { } } } else if (_peer->isChannel()) { - if (_peer->isMegagroup() && _peer->asChannel()->count > 0 && _peer->asChannel()->count <= Global::ChatSizeMax()) { - if (_peer->asChannel()->mgInfo->lastParticipants.size() < _peer->asChannel()->count || _peer->asChannel()->lastParticipantsCountOutdated()) { + if (_peer->isMegagroup() && _peer->asChannel()->membersCount() > 0 && _peer->asChannel()->membersCount() <= Global::ChatSizeMax()) { + if (_peer->asChannel()->mgInfo->lastParticipants.size() < _peer->asChannel()->membersCount() || _peer->asChannel()->lastParticipantsCountOutdated()) { if (App::api()) App::api()->requestLastParticipants(_peer->asChannel()); } int32 onlineCount = 0; @@ -6012,12 +6016,12 @@ void HistoryWidget::updateOnlineDisplay(int32 x, int32 w) { } } if (onlineCount && !onlyMe) { - text = lng_chat_status_members_online(lt_count, _peer->asChannel()->count, lt_count_online, onlineCount); + text = lng_chat_status_members_online(lt_count, _peer->asChannel()->membersCount(), lt_count_online, onlineCount); } else { - text = lng_chat_status_members(lt_count, _peer->asChannel()->count); + text = lng_chat_status_members(lt_count, _peer->asChannel()->membersCount()); } } else { - text = _peer->asChannel()->count ? lng_chat_status_members(lt_count, _peer->asChannel()->count) : lang(_peer->isMegagroup() ? lng_group_status : lng_channel_status); + text = _peer->asChannel()->membersCount() ? lng_chat_status_members(lt_count, _peer->asChannel()->membersCount()) : lang(_peer->isMegagroup() ? lng_group_status : lng_channel_status); } } if (_titlePeerText != text) { @@ -6286,6 +6290,8 @@ void HistoryWidget::confirmSendFile(const FileLoadResultPtr &file, bool ctrlShif } App::main()->dialogsToUp(); peerMessagesUpdated(file->to.peer); + + Notify::peerUpdatedSendDelayed(); } void HistoryWidget::cancelSendFile(const FileLoadResultPtr &file) { @@ -6920,6 +6926,7 @@ void HistoryWidget::addMessagesToFront(PeerData *peer, const QVector } updateBotKeyboard(); } + Notify::peerUpdatedSendDelayed(); } void HistoryWidget::addMessagesToBack(PeerData *peer, const QVector &messages, const QVector *collapsed) { @@ -6927,6 +6934,7 @@ void HistoryWidget::addMessagesToBack(PeerData *peer, const QVector if (!_firstLoadRequest) { updateListSize(false, true, { ScrollChangeNoJumpToBottom, 0 }); } + Notify::peerUpdatedSendDelayed(); } void HistoryWidget::countHistoryShowFrom() { @@ -7174,6 +7182,8 @@ void HistoryWidget::onInlineResultSend(InlineBots::Result *result, UserData *bot App::main()->finishForwarding(_history, _broadcast.checked(), _silent.checked()); cancelReply(lastKeyboardUsed); + Notify::peerUpdatedSendDelayed(); + App::historyRegRandom(randomId, newId); clearFieldText(); @@ -7943,6 +7953,7 @@ void HistoryWidget::onDeleteSelected() { } void HistoryWidget::onDeleteSelectedSure() { + Ui::hideLayer(); if (!_list) return; SelectedItemSet sel; @@ -7960,7 +7971,7 @@ void HistoryWidget::onDeleteSelectedSure() { for (SelectedItemSet::const_iterator i = sel.cbegin(), e = sel.cend(); i != e; ++i) { i.value()->destroy(); } - Ui::hideLayer(); + Notify::peerUpdatedSendDelayed(); for (QMap >::const_iterator i = ids.cbegin(), e = ids.cend(); i != e; ++i) { App::main()->deleteMessages(i.key(), i.value()); @@ -7968,6 +7979,8 @@ void HistoryWidget::onDeleteSelectedSure() { } void HistoryWidget::onDeleteContextSure() { + Ui::hideLayer(); + HistoryItem *item = App::contextItem(); if (!item || item->type() != HistoryItemMsg) { return; @@ -7977,12 +7990,12 @@ void HistoryWidget::onDeleteContextSure() { History *h = item->history(); bool wasOnServer = (item->id > 0), wasLast = (h->lastMsg == item); item->destroy(); + Notify::peerUpdatedSendDelayed(); + if (!wasOnServer && wasLast && !h->lastMsg) { App::main()->checkPeerHistory(h->peer); } - Ui::hideLayer(); - if (wasOnServer) { App::main()->deleteMessages(h->peer, toDelete); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 061deae81..d85b401df 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -764,6 +764,7 @@ void MainWidget::deleteConversation(PeerData *peer, bool deleteHistory) { if (deleteHistory) { MTP::send(MTPmessages_DeleteHistory(peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, peer)); } + Notify::peerUpdatedSendDelayed(); } void MainWidget::deleteAndExit(ChatData *chat) { @@ -788,6 +789,7 @@ void MainWidget::deleteAllFromUser(ChannelData *channel, UserData *from) { item->destroy(); } } + Notify::peerUpdatedSendDelayed(); } MTP::send(MTPchannels_DeleteUserHistory(channel->inputChannel, from->inputUser), rpcDone(&MainWidget::deleteAllFromUserPart, { channel, from })); } @@ -820,6 +822,7 @@ void MainWidget::clearHistory(PeerData *peer) { } Ui::showPeerHistory(peer->id, ShowAtUnreadMsgId); MTP::send(MTPmessages_DeleteHistory(peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, peer)); + Notify::peerUpdatedSendDelayed(); } void MainWidget::addParticipants(PeerData *chatOrChannel, const QVector &users) { @@ -976,6 +979,7 @@ void MainWidget::checkedHistory(PeerData *peer, const MTPmessages_Messages &resu } } } + Notify::peerUpdatedSendDelayed(); } bool MainWidget::sendMessageFail(const RPCError &error) { @@ -1240,7 +1244,7 @@ bool MainWidget::preloadOverview(PeerData *peer, MediaOverviewType type) { if (type == OverviewCount) return false; History *h = App::history(peer->id); - if (h->overviewCountLoaded(type) || _overviewPreload[type].constFind(peer) != _overviewPreload[type].cend()) { + if (h->overviewCountLoaded(type) || _overviewPreload[type].contains(peer)) { return false; } @@ -1280,11 +1284,11 @@ void MainWidget::overviewPreloaded(PeerData *peer, const MTPmessages_Messages &r App::history(peer->id)->overviewSliceDone(type, result, true); - mediaOverviewUpdated(peer, type); + if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, type); + Notify::peerUpdatedSendDelayed(); } void MainWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) { -// if (_profile) _profile->mediaOverviewUpdated(peer, type); TODO if (!_player->isHidden()) _player->mediaOverviewUpdated(peer, type); if (_overview && (_overview->peer() == peer || _overview->peer()->migrateFrom() == peer)) { _overview->mediaOverviewUpdated(peer, type); @@ -1419,6 +1423,7 @@ void MainWidget::overviewLoaded(History *history, const MTPmessages_Messages &re history->overviewSliceDone(type, result); if (App::wnd()) App::wnd()->mediaOverviewUpdated(history->peer, type); + Notify::peerUpdatedSendDelayed(); } void MainWidget::sendReadRequest(PeerData *peer, MsgId upTo) { @@ -4451,7 +4456,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { // Request last active supergroup participants if the 'from' user was not loaded yet. // This will optimize similar getDifference() calls for almost all next messages. if (isDataLoaded == DataIsLoadedResult::FromNotLoaded && channel && channel->isMegagroup() && App::api()) { - if (channel->mgInfo->lastParticipants.size() < Global::ChatSizeMax() && (channel->mgInfo->lastParticipants.isEmpty() || channel->mgInfo->lastParticipants.size() < channel->count)) { + if (channel->mgInfo->lastParticipants.size() < Global::ChatSizeMax() && (channel->mgInfo->lastParticipants.isEmpty() || channel->mgInfo->lastParticipants.size() < channel->membersCount())) { App::api()->requestLastParticipants(channel); } } diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 9795f9d1f..e6ad6d271 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -35,6 +35,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/confirmbox.h" #include "boxes/contactsbox.h" #include "boxes/addcontactbox.h" +#include "observer_peer.h" #include "autoupdater.h" #include "mediaview.h" #include "localstorage.h" @@ -1880,8 +1881,15 @@ void MainWindow::sendPaths() { void MainWindow::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) { if (main) main->mediaOverviewUpdated(peer, type); - if (!_mediaView || _mediaView->isHidden()) return; - _mediaView->mediaOverviewUpdated(peer, type); + if (_mediaView && !_mediaView->isHidden()) { + _mediaView->mediaOverviewUpdated(peer, type); + } + if (type != OverviewCount) { + Notify::PeerUpdate update(peer); + update.flags |= Notify::PeerUpdate::Flag::SharedMediaChanged; + update.mediaTypesMask |= (1 << type); + Notify::peerUpdatedDelayed(update); + } } void MainWindow::documentUpdated(DocumentData *doc) { diff --git a/Telegram/SourceFiles/observer_peer.cpp b/Telegram/SourceFiles/observer_peer.cpp index 76348480c..12e84f556 100644 --- a/Telegram/SourceFiles/observer_peer.cpp +++ b/Telegram/SourceFiles/observer_peer.cpp @@ -65,12 +65,17 @@ void mergePeerUpdate(PeerUpdate &mergeTo, const PeerUpdate &mergeFrom) { mergeTo.oldNameFirstChars = mergeFrom.oldNameFirstChars; } } + if (mergeFrom.flags & PeerUpdate::Flag::SharedMediaChanged) { + mergeTo.mediaTypesMask |= mergeFrom.mediaTypesMask; + } mergeTo.flags |= mergeFrom.flags; } void peerUpdatedDelayed(const PeerUpdate &update) { t_assert(creator.started()); + Global::RefHandleDelayedPeerUpdates().call(); + int existingUpdatesCount = SmallUpdates->size(); for (int i = 0; i < existingUpdatesCount; ++i) { auto &existingUpdate = (*SmallUpdates)[i]; @@ -96,9 +101,9 @@ void peerUpdatedDelayed(const PeerUpdate &update) { } void peerUpdatedSendDelayed() { - App::emitPeerUpdated(); + if (!creator.started()) return; - t_assert(creator.started()); + App::emitPeerUpdated(); if (SmallUpdates->isEmpty()) return; diff --git a/Telegram/SourceFiles/observer_peer.h b/Telegram/SourceFiles/observer_peer.h index bb735d77f..de12a9727 100644 --- a/Telegram/SourceFiles/observer_peer.h +++ b/Telegram/SourceFiles/observer_peer.h @@ -34,25 +34,32 @@ struct PeerUpdate { PeerData *peer; enum class Flag { - NameChanged = 0x00000001U, - UsernameChanged = 0x00000002U, - PhotoChanged = 0x00000004U, - AboutChanged = 0x00000008U, - NotificationsEnabled = 0x00000010U, - InviteLinkChanged = 0x00000020U, + NameChanged = 0x00000001U, + UsernameChanged = 0x00000002U, + PhotoChanged = 0x00000004U, + AboutChanged = 0x00000008U, + NotificationsEnabled = 0x00000010U, + SharedMediaChanged = 0x00000020U, - UserCanShareContact = 0x00010000U, - UserIsContact = 0x00020000U, - UserPhoneChanged = 0x00040000U, - UserIsBlocked = 0x00080000U, - BotCommandsChanged = 0x00100000U, + // For chats and channels + InviteLinkChanged = 0x00000020U, + MembersChanged = 0x00000040U, + AdminsChanged = 0x00000080U, - ChatCanEdit = 0x00010000U, + UserCanShareContact = 0x00010000U, + UserIsContact = 0x00020000U, + UserPhoneChanged = 0x00040000U, + UserIsBlocked = 0x00080000U, + BotCommandsChanged = 0x00100000U, - ChannelAmIn = 0x00010000U, - ChannelAmEditor = 0x00020000U, - ChannelCanEditPhoto = 0x00040000U, - ChannelCanAddMembers = 0x00080000U, + ChatCanEdit = 0x00010000U, + + ChannelAmIn = 0x00010000U, + ChannelAmEditor = 0x00020000U, + ChannelCanEditPhoto = 0x00040000U, + ChannelCanAddMembers = 0x00080000U, + ChannelCanViewAdmins = 0x00100000U, + ChannelCanViewMembers = 0x00200000U, }; Q_DECLARE_FLAGS(Flags, Flag); Flags flags = 0; @@ -60,6 +67,10 @@ struct PeerUpdate { // NameChanged data PeerData::Names oldNames; PeerData::NameFirstChars oldNameFirstChars; + + // SharedMediaChanged data + int32 mediaTypesMask = 0; + }; Q_DECLARE_OPERATORS_FOR_FLAGS(PeerUpdate::Flags); diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 8d8b1651d..48acc1c47 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -2336,6 +2336,8 @@ void OverviewWidget::onDeleteSelected() { } void OverviewWidget::onDeleteSelectedSure() { + Ui::hideLayer(); + SelectedItemSet sel; _inner.fillSelectedItems(sel); if (sel.isEmpty()) return; @@ -2351,7 +2353,6 @@ void OverviewWidget::onDeleteSelectedSure() { for (SelectedItemSet::const_iterator i = sel.cbegin(), e = sel.cend(); i != e; ++i) { i.value()->destroy(); } - Ui::hideLayer(); for (QMap >::const_iterator i = ids.cbegin(), e = ids.cend(); i != e; ++i) { App::main()->deleteMessages(i.key(), i.value()); @@ -2359,6 +2360,8 @@ void OverviewWidget::onDeleteSelectedSure() { } void OverviewWidget::onDeleteContextSure() { + Ui::hideLayer(); + HistoryItem *item = App::contextItem(); if (!item || item->type() != HistoryItemMsg) { return; @@ -2368,12 +2371,11 @@ void OverviewWidget::onDeleteContextSure() { History *h = item->history(); bool wasOnServer = (item->id > 0), wasLast = (h->lastMsg == item); item->destroy(); + if (!wasOnServer && wasLast && !h->lastMsg) { App::main()->checkPeerHistory(h->peer); } - Ui::hideLayer(); - if (wasOnServer) { App::main()->deleteMessages(h->peer, toDelete); } diff --git a/Telegram/SourceFiles/profile/profile_actions_widget.cpp b/Telegram/SourceFiles/profile/profile_actions_widget.cpp index 1087f484f..b40b35ad5 100644 --- a/Telegram/SourceFiles/profile/profile_actions_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_actions_widget.cpp @@ -34,7 +34,10 @@ namespace Profile { using UpdateFlag = Notify::PeerUpdate::Flag; ActionsWidget::ActionsWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_actions_section)) { - auto observeEvents = UpdateFlag::ChannelAmIn | UpdateFlag::UserIsBlocked | UpdateFlag::BotCommandsChanged; + auto observeEvents = UpdateFlag::ChannelAmIn + | UpdateFlag::UserIsBlocked + | UpdateFlag::BotCommandsChanged + | UpdateFlag::MembersChanged; Notify::registerPeerObserver(observeEvents, this, &ActionsWidget::notifyPeerUpdated); validateBlockStatus(); @@ -57,6 +60,9 @@ void ActionsWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { if (needFullRefresh()) { refreshButtons(); } else { + if (update.flags & UpdateFlag::MembersChanged) { + refreshDeleteChannel(); + } if (update.flags & UpdateFlag::ChannelAmIn) { refreshLeaveChannel(); } @@ -99,11 +105,11 @@ Ui::LeftOutlineButton *ActionsWidget::addButton(const QString &text, const char }; void ActionsWidget::resizeButton(Ui::LeftOutlineButton *button, int top) { - int left = st::profileBlockTitlePosition.x(); - int availableWidth = width() - left + st::defaultLeftOutlineButton.padding.left() - st::profileBlockMarginRight; + int left = defaultOutlineButtonLeft(); + int availableWidth = width() - left - st::profileBlockMarginRight; accumulate_min(availableWidth, st::profileBlockOneLineWidthMax); button->resizeToWidth(availableWidth); - button->moveToLeft(left - st::defaultLeftOutlineButton.padding.left(), top); + button->moveToLeft(left, top); } void ActionsWidget::refreshButtons() { @@ -131,9 +137,7 @@ void ActionsWidget::refreshButtons() { addButton(lang(lng_profile_clear_and_exit), SLOT(onDeleteConversation())); } else if (auto channel = peer()->asChannel()) { // addButton(lang(lng_profile_report), SLOT(onReport())); - if (channel->amCreator()) { - addButton(lang(channel->isMegagroup() ? lng_profile_delete_group : lng_profile_delete_channel), SLOT(onDeleteChannel()), st::attentionLeftOutlineButton); - } + refreshDeleteChannel(); refreshLeaveChannel(); } @@ -208,6 +212,18 @@ void ActionsWidget::refreshBlockUser() { } } +void ActionsWidget::refreshDeleteChannel() { + if (auto channel = peer()->asChannel()) { + if (channel->canDelete() && !_deleteChannel) { + _deleteChannel = addButton(lang(channel->isMegagroup() ? lng_profile_delete_group : lng_profile_delete_channel), SLOT(onDeleteChannel()), st::attentionLeftOutlineButton); + } else if (!channel->canDelete() && _deleteChannel) { + _buttons.removeOne(_deleteChannel); + delete _deleteChannel; + _deleteChannel = nullptr; + } + } +} + void ActionsWidget::refreshLeaveChannel() { if (auto channel = peer()->asChannel()) { if (!channel->amCreator()) { diff --git a/Telegram/SourceFiles/profile/profile_actions_widget.h b/Telegram/SourceFiles/profile/profile_actions_widget.h index 32646ae76..895f066b1 100644 --- a/Telegram/SourceFiles/profile/profile_actions_widget.h +++ b/Telegram/SourceFiles/profile/profile_actions_widget.h @@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "profile/profile_block_widget.h" -#include "core/observer.h" namespace Ui { class LeftOutlineButton; @@ -33,7 +32,7 @@ struct PeerUpdate; namespace Profile { -class ActionsWidget : public BlockWidget, public Notify::Observer { +class ActionsWidget : public BlockWidget { Q_OBJECT public: @@ -67,6 +66,7 @@ private: void refreshButtons(); void refreshBlockUser(); + void refreshDeleteChannel(); void refreshLeaveChannel(); void refreshVisibility(); @@ -93,6 +93,7 @@ private: bool _hasBotHelp = false; bool _hasBotSettings = false; Ui::LeftOutlineButton *_blockUser = nullptr; + Ui::LeftOutlineButton *_deleteChannel = nullptr; Ui::LeftOutlineButton *_leaveChannel = nullptr; }; diff --git a/Telegram/SourceFiles/profile/profile_block_widget.cpp b/Telegram/SourceFiles/profile/profile_block_widget.cpp index 6548fbb61..ba2c8ac5f 100644 --- a/Telegram/SourceFiles/profile/profile_block_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_block_widget.cpp @@ -50,4 +50,8 @@ void BlockWidget::paintEvent(QPaintEvent *e) { paintContents(p); } +int defaultOutlineButtonLeft() { + return st::profileBlockTitlePosition.x() - st::defaultLeftOutlineButton.padding.left(); +} + } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_widget.h b/Telegram/SourceFiles/profile/profile_block_widget.h index 8607aa0b5..fd2230f2d 100644 --- a/Telegram/SourceFiles/profile/profile_block_widget.h +++ b/Telegram/SourceFiles/profile/profile_block_widget.h @@ -20,9 +20,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +#include "core/observer.h" + namespace Profile { -class BlockWidget : public TWidget { +class BlockWidget : public TWidget, public Notify::Observer { Q_OBJECT public: @@ -64,4 +66,6 @@ private: }; +int defaultOutlineButtonLeft(); + } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_cover.cpp b/Telegram/SourceFiles/profile/profile_cover.cpp index c6dbb3961..e31a83135 100644 --- a/Telegram/SourceFiles/profile/profile_cover.cpp +++ b/Telegram/SourceFiles/profile/profile_cover.cpp @@ -363,10 +363,10 @@ void CoverWidget::refreshStatusText() { for_const (auto user, _peerMegagroup->mgInfo->lastParticipants) { counter.feedUser(user); } - _statusText = counter.result(_peerMegagroup->count); + _statusText = counter.result(_peerMegagroup->membersCount()); } else if (_peerChannel) { - if (_peerChannel->count > 0) { - _statusText = lng_chat_status_members(lt_count, _peerChannel->count); + if (_peerChannel->membersCount() > 0) { + _statusText = lng_chat_status_members(lt_count, _peerChannel->membersCount()); } else { _statusText = lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status); } @@ -381,7 +381,7 @@ bool CoverWidget::isUsingMegagroupOnlineCount() const { return false; } - if (_peerMegagroup->count <= 0 || _peerMegagroup->count > Global::ChatSizeMax()) { + if (_peerMegagroup->membersCount() <= 0 || _peerMegagroup->membersCount() > Global::ChatSizeMax()) { return false; } @@ -425,7 +425,7 @@ void CoverWidget::setMegagroupButtons() { if (_peerMegagroup->canEditPhoto()) { addButton(lang(lng_profile_set_group_photo), SLOT(onSetPhoto())); } - if (_peerMegagroup->canAddParticipants()) { + if (_peerMegagroup->canAddMembers()) { addButton(lang(lng_profile_add_participant), SLOT(onAddMember()), &st::profileAddMemberButton); } } diff --git a/Telegram/SourceFiles/profile/profile_info_widget.h b/Telegram/SourceFiles/profile/profile_info_widget.h index b94f5199d..16be5604b 100644 --- a/Telegram/SourceFiles/profile/profile_info_widget.h +++ b/Telegram/SourceFiles/profile/profile_info_widget.h @@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "profile/profile_block_widget.h" -#include "core/observer.h" class FlatLabel; @@ -31,7 +30,7 @@ struct PeerUpdate; namespace Profile { -class InfoWidget : public BlockWidget, public Notify::Observer { +class InfoWidget : public BlockWidget { public: InfoWidget(QWidget *parent, PeerData *peer); diff --git a/Telegram/SourceFiles/profile/profile_inner_widget.cpp b/Telegram/SourceFiles/profile/profile_inner_widget.cpp index 0cd9d0e17..e0423f428 100644 --- a/Telegram/SourceFiles/profile/profile_inner_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_inner_widget.cpp @@ -54,10 +54,10 @@ void InnerWidget::createBlocks() { _blocks.push_back({ new InviteLinkWidget(this, _peer), BlockSide::Right }); } _blocks.push_back({ new SharedMediaWidget(this, _peer), BlockSide::Right }); - _blocks.push_back({ new ActionsWidget(this, _peer), BlockSide::Right }); if (channel && !megagroup) { _blocks.push_back({ new ChannelMembersWidget(this, _peer), BlockSide::Right }); } + _blocks.push_back({ new ActionsWidget(this, _peer), BlockSide::Right }); if (chat || megagroup) { _blocks.push_back({ new MembersWidget(this, _peer), BlockSide::Left }); } @@ -82,7 +82,7 @@ void InnerWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) { } //loadProfilePhotos(_visibleTop); - if (peer()->isMegagroup() && !peer()->asChannel()->mgInfo->lastParticipants.isEmpty() && peer()->asChannel()->mgInfo->lastParticipants.size() < peer()->asChannel()->count) { + if (peer()->isMegagroup() && !peer()->asChannel()->mgInfo->lastParticipants.isEmpty() && peer()->asChannel()->mgInfo->lastParticipants.size() < peer()->asChannel()->membersCount()) { if (_visibleTop + (PreloadHeightsCount + 1) * (_visibleBottom - _visibleTop) > height()) { App::api()->requestLastParticipants(peer()->asChannel(), false); } diff --git a/Telegram/SourceFiles/profile/profile_invite_link_widget.h b/Telegram/SourceFiles/profile/profile_invite_link_widget.h index 76f3557c2..65ef20b71 100644 --- a/Telegram/SourceFiles/profile/profile_invite_link_widget.h +++ b/Telegram/SourceFiles/profile/profile_invite_link_widget.h @@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "profile/profile_block_widget.h" -#include "core/observer.h" class FlatLabel; @@ -31,7 +30,7 @@ struct PeerUpdate; namespace Profile { -class InviteLinkWidget : public BlockWidget, public Notify::Observer { +class InviteLinkWidget : public BlockWidget { public: InviteLinkWidget(QWidget *parent, PeerData *peer); diff --git a/Telegram/SourceFiles/profile/profile_members_widget.cpp b/Telegram/SourceFiles/profile/profile_members_widget.cpp index 26ccc9308..57dca8f2c 100644 --- a/Telegram/SourceFiles/profile/profile_members_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_members_widget.cpp @@ -22,10 +22,15 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "profile/profile_members_widget.h" #include "styles/style_profile.h" +#include "ui/buttons/left_outline_button.h" +#include "boxes/contactsbox.h" +#include "observer_peer.h" #include "lang.h" namespace Profile { +using UpdateFlag = Notify::PeerUpdate::Flag; + MembersWidget::MembersWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_participants_section)) { show(); @@ -37,15 +42,113 @@ int MembersWidget::resizeGetHeight(int newWidth) { return newHeight; } -ChannelMembersWidget::ChannelMembersWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_participants_section)) -{ - show(); +ChannelMembersWidget::ChannelMembersWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_participants_section)) { + auto observeEvents = UpdateFlag::ChannelCanViewAdmins + | UpdateFlag::ChannelCanViewMembers + | UpdateFlag::AdminsChanged + | UpdateFlag::MembersChanged; + Notify::registerPeerObserver(observeEvents, this, &ChannelMembersWidget::notifyPeerUpdated); + + 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 *button, const char *slot) { + if (text.isEmpty()) { + button->destroy(); + } else if (*button) { + (*button)->setText(text); + } else { + (*button) = new Ui::LeftOutlineButton(this, text); + (*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 &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, MembersFilterAdmins)); + } +} + +void ChannelMembersWidget::onMembers() { + if (auto channel = peer()->asChannel()) { + Ui::showLayer(new MembersBox(channel, MembersFilterRecent)); + } +} + } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_members_widget.h b/Telegram/SourceFiles/profile/profile_members_widget.h index 8278091c1..ef82b90cd 100644 --- a/Telegram/SourceFiles/profile/profile_members_widget.h +++ b/Telegram/SourceFiles/profile/profile_members_widget.h @@ -22,6 +22,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "profile/profile_block_widget.h" +namespace Ui { +class LeftOutlineButton; +} // namespace Ui + +namespace Notify { +struct PeerUpdate; +} // namespace Notify + namespace Profile { class MembersWidget : public BlockWidget { @@ -35,6 +43,8 @@ protected: }; class ChannelMembersWidget : public BlockWidget { + Q_OBJECT + public: ChannelMembersWidget(QWidget *parent, PeerData *peer); @@ -42,6 +52,24 @@ 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 *button, const char *slot); + + ChildWidget _admins = { nullptr }; + ChildWidget _members = { nullptr }; + }; } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_settings_widget.cpp b/Telegram/SourceFiles/profile/profile_settings_widget.cpp index 3b5b7d716..706b3958a 100644 --- a/Telegram/SourceFiles/profile/profile_settings_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_settings_widget.cpp @@ -80,18 +80,17 @@ void SettingsWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { int SettingsWidget::resizeGetHeight(int newWidth) { int newHeight = contentTop(); - int left = st::profileBlockTitlePosition.x(); - - _enableNotifications->moveToLeft(left, newHeight); + _enableNotifications->moveToLeft(st::profileBlockTitlePosition.x(), newHeight); newHeight += _enableNotifications->height() + st::profileBlockOneLineSkip; - auto moveLink = [&newHeight, left, newWidth](Ui::LeftOutlineButton *button) { + auto moveLink = [&newHeight, newWidth](Ui::LeftOutlineButton *button) { if (!button) return; - int availableWidth = newWidth - left + st::defaultLeftOutlineButton.padding.left() - st::profileBlockMarginRight; + int left = defaultOutlineButtonLeft(); + int availableWidth = newWidth - left - st::profileBlockMarginRight; accumulate_min(availableWidth, st::profileBlockOneLineWidthMax); button->resizeToWidth(availableWidth); - button->moveToLeft(left - st::defaultLeftOutlineButton.padding.left(), newHeight); + button->moveToLeft(left, newHeight); newHeight += button->height(); }; moveLink(_manageAdmins); diff --git a/Telegram/SourceFiles/profile/profile_settings_widget.h b/Telegram/SourceFiles/profile/profile_settings_widget.h index 3efe880f1..4b02ee17c 100644 --- a/Telegram/SourceFiles/profile/profile_settings_widget.h +++ b/Telegram/SourceFiles/profile/profile_settings_widget.h @@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "profile/profile_block_widget.h" -#include "core/observer.h" class Checkbox; @@ -35,7 +34,7 @@ struct PeerUpdate; namespace Profile { -class SettingsWidget : public BlockWidget, public Notify::Observer { +class SettingsWidget : public BlockWidget { Q_OBJECT public: diff --git a/Telegram/SourceFiles/profile/profile_shared_media_widget.cpp b/Telegram/SourceFiles/profile/profile_shared_media_widget.cpp index 5215e86fc..f7263f22b 100644 --- a/Telegram/SourceFiles/profile/profile_shared_media_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_shared_media_widget.cpp @@ -22,19 +22,132 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "profile/profile_shared_media_widget.h" #include "styles/style_profile.h" +#include "observer_peer.h" +#include "ui/buttons/left_outline_button.h" +#include "mainwidget.h" #include "lang.h" namespace Profile { +namespace { + +QString getButtonText(MediaOverviewType type, int count) { + if (count <= 0) { + return QString(); + } + + switch (type) { + case OverviewPhotos: return lng_profile_photos(lt_count, count); + case OverviewVideos: return lng_profile_videos(lt_count, count); + case OverviewMusicFiles: return lng_profile_songs(lt_count, count); + case OverviewFiles: return lng_profile_files(lt_count, count); + case OverviewVoiceFiles: return lng_profile_audios(lt_count, count); + case OverviewLinks: return lng_profile_shared_links(lt_count, count); + } + return QString(); +} + +} // namespace SharedMediaWidget::SharedMediaWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_shared_media)) -{ - show(); +, _history(App::history(peer)) +, _migrated(peer->migrateFrom() ? App::history(peer->migrateFrom()) : nullptr) { + Notify::registerPeerObserver(Notify::PeerUpdate::Flag::SharedMediaChanged, this, &SharedMediaWidget::notifyPeerUpdated); + + App::main()->preloadOverviews(peer); + if (_migrated) { + App::main()->preloadOverviews(_migrated->peer); + } + + refreshButtons(); + refreshVisibility(); +} + +void SharedMediaWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { + if (update.peer != peer() && (!_migrated || update.peer != _migrated->peer)) { + return; + } + + bool updated = false; + for (int i = 0; i < OverviewCount; ++i) { + if (update.mediaTypesMask & (1 << i)) { + refreshButton(static_cast(i)); + updated = true; + } + } + if (updated) { + refreshVisibility(); + + contentSizeUpdated(); + } } int SharedMediaWidget::resizeGetHeight(int newWidth) { int newHeight = contentTop(); + resizeButtons(&newHeight); + return newHeight; } +void SharedMediaWidget::refreshButtons() { + for (int typeIndex = 0; typeIndex < OverviewCount; ++typeIndex) { + refreshButton(static_cast(typeIndex)); + } +} + +void SharedMediaWidget::refreshButton(MediaOverviewType type) { + int count = _history->overviewCount(type), migrated = _migrated ? _migrated->overviewCount(type) : 0; + int finalCount = (count >= 0 && migrated >= 0) ? (count + migrated) : -1; + auto text = getButtonText(type, finalCount); + if (text.isEmpty()) { + if (_mediaButtons[type]) { + delete _mediaButtons[type]; + _mediaButtons[type] = nullptr; + } + } else { + if (_mediaButtons[type]) { + _mediaButtons[type]->setText(text); + } else { + _mediaButtons[type] = new Ui::LeftOutlineButton(this, text); + _mediaButtons[type]->show(); + connect(_mediaButtons[type], SIGNAL(clicked()), this, SLOT(onMediaChosen())); + } + } +} + +void SharedMediaWidget::refreshVisibility() { + for_const (auto button, _mediaButtons) { + if (button) { + show(); + return; + } + } + hide(); +} + +void SharedMediaWidget::onMediaChosen() { + for (int i = 0; i < OverviewCount; ++i) { + auto button = _mediaButtons[i]; + if (button && button == sender()) { + App::main()->showMediaOverview(peer(), static_cast(i)); + return; + } + } +} + +void SharedMediaWidget::resizeButtons(int *top) { + t_assert(top != nullptr); + + int left = defaultOutlineButtonLeft(); + int availableWidth = width() - left - st::profileBlockMarginRight; + accumulate_min(availableWidth, st::profileBlockOneLineWidthMax); + for_const (auto button, _mediaButtons) { + if (!button) continue; + + button->resizeToWidth(availableWidth); + button->moveToLeft(left, *top); + *top += button->height(); + } +} + } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_shared_media_widget.h b/Telegram/SourceFiles/profile/profile_shared_media_widget.h index 49597f69e..24db5cedc 100644 --- a/Telegram/SourceFiles/profile/profile_shared_media_widget.h +++ b/Telegram/SourceFiles/profile/profile_shared_media_widget.h @@ -22,9 +22,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "profile/profile_block_widget.h" +namespace Ui { +class LeftOutlineButton; +} // namespace Ui + +namespace Notify { +struct PeerUpdate; +} // namespace Notify + namespace Profile { class SharedMediaWidget : public BlockWidget { + Q_OBJECT + public: SharedMediaWidget(QWidget *parent, PeerData *peer); @@ -32,6 +42,23 @@ protected: // Resizes content and counts natural widget height for the desired width. int resizeGetHeight(int newWidth) override; +private slots: + void onMediaChosen(); + +private: + // Observed notifications. + void notifyPeerUpdated(const Notify::PeerUpdate &update); + + void refreshButtons(); + void refreshButton(MediaOverviewType type); + void refreshVisibility(); + + void resizeButtons(int *top); + + Ui::LeftOutlineButton *_mediaButtons[OverviewCount] = { nullptr }; + History *_history; + History *_migrated; + }; } // namespace Profile diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp index eaeb9fea0..f792c03a1 100644 --- a/Telegram/SourceFiles/profilewidget.cpp +++ b/Telegram/SourceFiles/profilewidget.cpp @@ -61,8 +61,8 @@ ProfileInner::ProfileInner(ProfileWidget *profile, PeerData *peer) : TWidget(0) , _botHelp(this, lang(lng_profile_bot_help)) , _pinnedMessage(this, lang(lng_pinned_message)) , _username(this, (_peerChannel && _peerChannel->isPublic()) ? (qsl("telegram.me/") + _peerChannel->username) : lang(lng_profile_create_public_link)) -, _members(this, lng_channel_members_link(lt_count, (_peerChannel && _peerChannel->count > 0) ? _peerChannel->count : 1)) -, _admins(this, lng_channel_admins_link(lt_count, (_peerChannel ? (_peerChannel->adminsCount > 0 ? _peerChannel->adminsCount : 1) : ((_peerChat && _peerChat->adminsEnabled()) ? (_peerChat->admins.size() + 1) : 0)))) +, _members(this, lng_channel_members_link(lt_count, (_peerChannel && _peerChannel->membersCount() > 0) ? _peerChannel->membersCount() : 1)) +, _admins(this, lng_channel_admins_link(lt_count, (_peerChannel ? (_peerChannel->adminsCount() > 0 ? _peerChannel->adminsCount() : 1) : ((_peerChat && _peerChat->adminsEnabled()) ? (_peerChat->admins.size() + 1) : 0)))) // about , _about(st::wndMinWidth - st::profilePadding.left() - st::profilePadding.right()) @@ -554,9 +554,9 @@ void ProfileInner::onFullPeerUpdated(PeerData *peer) { _admins.setText(lng_channel_admins_link(lt_count, _peerChat->adminsEnabled() ? (_peerChat->admins.size() + 1) : 0)); } else if (_peerChannel) { updateInvitationLink(); - _members.setText(lng_channel_members_link(lt_count, (_peerChannel->count > 0) ? _peerChannel->count : 1)); - _admins.setText(lng_channel_admins_link(lt_count, (_peerChannel->adminsCount > 0) ? _peerChannel->adminsCount : 1)); - _onlineText = (_peerChannel->count > 0) ? lng_chat_status_members(lt_count, _peerChannel->count) : lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status); + _members.setText(lng_channel_members_link(lt_count, (_peerChannel->membersCount() > 0) ? _peerChannel->membersCount() : 1)); + _admins.setText(lng_channel_admins_link(lt_count, (_peerChannel->adminsCount() > 0) ? _peerChannel->adminsCount() : 1)); + _onlineText = (_peerChannel->membersCount() > 0) ? lng_chat_status_members(lt_count, _peerChannel->membersCount()) : lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status); if (_peerChannel->about().isEmpty()) { _about = Text(st::wndMinWidth - st::profilePadding.left() - st::profilePadding.right()); } else { @@ -623,9 +623,9 @@ void ProfileInner::peerUpdated(PeerData *data) { if (_peerChannel->isPublic() != _invitationLink.isHidden()) { peerUsernameChanged(); } - _members.setText(lng_channel_members_link(lt_count, (_peerChannel->count > 0) ? _peerChannel->count : 1)); - _admins.setText(lng_channel_admins_link(lt_count, (_peerChannel->adminsCount > 0) ? _peerChannel->adminsCount : 1)); - _onlineText = (_peerChannel->count > 0) ? lng_chat_status_members(lt_count, _peerChannel->count) : lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status); + _members.setText(lng_channel_members_link(lt_count, (_peerChannel->membersCount() > 0) ? _peerChannel->membersCount() : 1)); + _admins.setText(lng_channel_admins_link(lt_count, (_peerChannel->adminsCount() > 0) ? _peerChannel->adminsCount() : 1)); + _onlineText = (_peerChannel->membersCount() > 0) ? lng_chat_status_members(lt_count, _peerChannel->membersCount()) : lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status); updatePinnedMessageVisibility(); } if (photo && photo->date) { @@ -719,7 +719,7 @@ void ProfileInner::reorderParticipants() { loadProfilePhotos(_lastPreload); } else if (_peerChannel && _peerChannel->isMegagroup() && _peerChannel->amIn() && !_peerChannel->mgInfo->lastParticipants.isEmpty()) { bool needAdmins = true, adminsOutdated = (_peerChannel->mgInfo->lastParticipantsStatus & MegagroupInfo::LastParticipantsAdminsOutdated); - bool orderByOnline = (_peerChannel->count > 0) && (_peerChannel->count <= Global::ChatSizeMax()); + bool orderByOnline = (_peerChannel->membersCount() > 0) && (_peerChannel->membersCount() <= Global::ChatSizeMax()); _onlineText.clear(); if (_peerChannel->mgInfo->lastParticipants.isEmpty() || (needAdmins && adminsOutdated) || _peerChannel->lastParticipantsCountOutdated()) { @@ -758,9 +758,9 @@ void ProfileInner::reorderParticipants() { } } if (onlineCount && !onlyMe) { - _onlineText = lng_chat_status_members_online(lt_count, _peerChannel->count, lt_count_online, onlineCount); + _onlineText = lng_chat_status_members_online(lt_count, _peerChannel->membersCount(), lt_count_online, onlineCount); } else { - _onlineText = lng_chat_status_members(lt_count, _peerChannel->count); + _onlineText = lng_chat_status_members(lt_count, _peerChannel->membersCount()); } } else { for (int32 i = 0, l = _participants.size(); i < l; ++i) { @@ -786,7 +786,7 @@ void ProfileInner::reorderParticipants() { _participantsData.resize(s); } if (_onlineText.isEmpty()) { - _onlineText = (_peerChannel->count > 0) ? lng_chat_status_members(lt_count, _peerChannel->count) : lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status); + _onlineText = (_peerChannel->membersCount() > 0) ? lng_chat_status_members(lt_count, _peerChannel->membersCount()) : lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status); } loadProfilePhotos(_lastPreload); } else { @@ -794,7 +794,7 @@ void ProfileInner::reorderParticipants() { if (_peerUser) { _onlineText = App::onlineText(_peerUser, t, true); } else if (_peerChannel) { - _onlineText = (_peerChannel->count > 0) ? lng_chat_status_members(lt_count, _peerChannel->count) : lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status); + _onlineText = (_peerChannel->membersCount() > 0) ? lng_chat_status_members(lt_count, _peerChannel->membersCount()) : lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status); } else { _onlineText = lang(lng_chat_status_unaccessible); } @@ -867,7 +867,7 @@ void ProfileInner::paintEvent(QPaintEvent *e) { } else if (_peerChannel && (_peerChannel->isPublic() || _peerChannel->canEditUsername())) { // addbyname = st::profileStatusTop + st::linkFont->ascent - (st::profileNameTop + st::profileNameFont->ascent); } - if (!_peerChannel || !_peerChannel->canViewParticipants() || _peerChannel->isMegagroup()) { + if (!_peerChannel || !_peerChannel->canViewMembers() || _peerChannel->isMegagroup()) { //p.setPen((_peerUser && App::onlineColorUse(_peerUser, l_time) ? st::profileOnlineColor : st::profileOfflineColor)->p); //p.drawText(_left + st::profilePhotoSize + st::profileStatusLeft, top + addbyname + st::profileStatusTop + st::linkFont->ascent, _onlineText); } @@ -889,7 +889,7 @@ void ProfileInner::paintEvent(QPaintEvent *e) { // top += st::profilePhotoSize; // top += st::profileButtonTop; - if ((!_peerChat || _peerChat->canEdit()) && (!_peerChannel || _amCreator || (_peerChannel->canAddParticipants() && _peerChannel->isMegagroup()))) { + if ((!_peerChat || _peerChat->canEdit()) && (!_peerChannel || _amCreator || (_peerChannel->canAddMembers() && _peerChannel->isMegagroup()))) { top += _shareContact.height(); } else { // top -= st::profileButtonTop; @@ -1371,7 +1371,7 @@ bool ProfileInner::migrateFail(const RPCError &error) { } bool ProfileInner::canDeleteChannel() const { - return _peerChannel && _amCreator && (_peerChannel->count <= 1000); + return _peerChannel && _amCreator && (_peerChannel->membersCount() <= 1000); } void ProfileInner::resizeEvent(QResizeEvent *e) { @@ -1406,7 +1406,7 @@ void ProfileInner::resizeEvent(QResizeEvent *e) { //top += st::profileButtonTop; _uploadPhoto.setGeometry(_left, top, btnWidth, _uploadPhoto.height()); - if (_peerChannel && _peerChannel->count < Global::MegagroupSizeMax() && _peerChannel->isMegagroup() && !_amCreator && !_peerChannel->amEditor() && _peerChannel->canAddParticipants()) { + if (_peerChannel && _peerChannel->membersCount() < Global::MegagroupSizeMax() && _peerChannel->isMegagroup() && !_amCreator && !_peerChannel->amEditor() && _peerChannel->canAddMembers()) { _addParticipant.setGeometry(_left, top, btnWidth, _addParticipant.height()); } else { _addParticipant.setGeometry(_left + _width - btnWidth, top, btnWidth, _addParticipant.height()); @@ -1416,7 +1416,7 @@ void ProfileInner::resizeEvent(QResizeEvent *e) { _shareContact.setGeometry(_left + _width - btnWidth, top, btnWidth, _shareContact.height()); _inviteToGroup.setGeometry(_left + _width - btnWidth, top, btnWidth, _inviteToGroup.height()); - if ((!_peerChat || _peerChat->canEdit()) && (!_peerChannel || _amCreator || (_peerChannel->canAddParticipants() && _peerChannel->isMegagroup()))) { + if ((!_peerChat || _peerChat->canEdit()) && (!_peerChannel || _amCreator || (_peerChannel->canAddMembers() && _peerChannel->isMegagroup()))) { top += _shareContact.height(); } else { //top -= st::profileButtonTop; @@ -1766,7 +1766,7 @@ void ProfileInner::showAll() { _invitationLink.hide(); } } - if (_peerChannel->count < Global::MegagroupSizeMax() && _peerChannel->isMegagroup() && _peerChannel->canAddParticipants()) { + if (_peerChannel->membersCount() < Global::MegagroupSizeMax() && _peerChannel->isMegagroup() && _peerChannel->canAddMembers()) { _addParticipant.show(); } else { _addParticipant.hide(); @@ -1787,7 +1787,7 @@ void ProfileInner::showAll() { } else { _admins.hide(); } - if (_peerChannel->canViewParticipants() && !_peerChannel->isMegagroup()) { + if (_peerChannel->canViewMembers() && !_peerChannel->isMegagroup()) { _members.show(); } else { _members.hide(); @@ -1880,7 +1880,7 @@ void ProfileWidget::onScroll() { if (!_scroll.isHidden() && _scroll.scrollTop() < _scroll.scrollTopMax()) { _inner.allowDecreaseHeight(_scroll.scrollTopMax() - _scroll.scrollTop()); } - if (peer()->isMegagroup() && !peer()->asChannel()->mgInfo->lastParticipants.isEmpty() && peer()->asChannel()->mgInfo->lastParticipants.size() < peer()->asChannel()->count) { + if (peer()->isMegagroup() && !peer()->asChannel()->mgInfo->lastParticipants.isEmpty() && peer()->asChannel()->mgInfo->lastParticipants.size() < peer()->asChannel()->membersCount()) { if (_scroll.scrollTop() + PreloadHeightsCount * _scroll.height() > _scroll.scrollTopMax()) { App::api()->requestLastParticipants(peer()->asChannel(), false); } diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 1ef865058..30d1bfc03 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -516,6 +516,24 @@ void ChannelData::setInviteLink(const QString &newInviteLink) { } } +void ChannelData::setMembersCount(int newMembersCount) { + if (_membersCount != newMembersCount) { + if (isMegagroup() && !mgInfo->lastParticipants.isEmpty()) { + mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsCountOutdated; + mgInfo->lastParticipantsCount = membersCount(); + } + _membersCount = newMembersCount; + Notify::peerUpdatedDelayed(this, Notify::PeerUpdate::Flag::MembersChanged); + } +} + +void ChannelData::setAdminsCount(int newAdminsCount) { + if (_adminsCount != newAdminsCount) { + _adminsCount = newAdminsCount; + Notify::peerUpdatedDelayed(this, Notify::PeerUpdate::Flag::AdminsChanged); + } +} + void ChannelData::flagsUpdated() { if (isMegagroup()) { if (!mgInfo) { diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index 536fc2c55..c631972db 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -697,8 +697,16 @@ public: return _about; } - int count = 1; - int adminsCount = 1; + int membersCount() const { + return _membersCount; + } + void setMembersCount(int newMembersCount); + + int adminsCount() const { + return _adminsCount; + } + void setAdminsCount(int newAdminsCount); + int32 date = 0; int version = 0; MTPDchannel::Flags flags = { 0 }; @@ -708,7 +716,7 @@ public: if (!mgInfo || !(mgInfo->lastParticipantsStatus & MegagroupInfo::LastParticipantsCountOutdated)) { return false; } - if (mgInfo->lastParticipantsCount == count) { + if (mgInfo->lastParticipantsCount == membersCount()) { mgInfo->lastParticipantsStatus &= ~MegagroupInfo::LastParticipantsCountOutdated; return false; } @@ -748,9 +756,12 @@ public: bool canWrite() const { return amIn() && (canPublish() || !isBroadcast()); } - bool canViewParticipants() const { + bool canViewMembers() const { return flagsFull & MTPDchannelFull::Flag::f_can_view_participants; } + bool canViewAdmins() const { + return (isMegagroup() || amCreator() || amEditor() || amModerator()); + } bool addsSignature() const { return flags & MTPDchannel::Flag::f_signatures; } @@ -758,7 +769,7 @@ public: bool isVerified() const { return flags & MTPDchannel::Flag::f_verified; } - bool canAddParticipants() const { + bool canAddMembers() const { return amCreator() || amEditor() || (flags & MTPDchannel::Flag::f_democracy); } bool canEditPhoto() const { @@ -767,6 +778,9 @@ public: bool canEditUsername() const { return amCreator() && (flagsFull & MTPDchannelFull::Flag::f_can_set_username); } + bool canDelete() const { + return amCreator() && (membersCount() <= 1000); + } // ImagePtr photoFull; @@ -824,6 +838,9 @@ private: PtsWaiter _ptsWaiter; uint64 _lastFullUpdate = 0; + int _membersCount = 1; + int _adminsCount = 1; + QString _restrictionReason; QString _about; diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index 39cb0bcbc..d23d6d9d1 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -410,10 +410,18 @@ true true + + true + true + true true + + true + true + true true @@ -733,10 +741,18 @@ true true + + true + true + true true + + true + true + true true @@ -1082,10 +1098,18 @@ true true + + true + true + true true + + true + true + true true @@ -1610,7 +1634,20 @@ - + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing profile_members_widget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/profile/profile_members_widget.h" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl\Release\include" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing profile_members_widget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/profile/profile_members_widget.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl_debug\Debug\include" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing profile_members_widget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/profile/profile_members_widget.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl\Release\include" + $(QTDIR)\bin\moc.exe;%(FullPath) @@ -1626,7 +1663,20 @@ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/profile/profile_settings_widget.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl\Release\include" - + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing profile_shared_media_widget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/profile/profile_shared_media_widget.h" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl\Release\include" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing profile_shared_media_widget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/profile/profile_shared_media_widget.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl_debug\Debug\include" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing profile_shared_media_widget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/profile/profile_shared_media_widget.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl\Release\include" + diff --git a/Telegram/Telegram.vcxproj.filters b/Telegram/Telegram.vcxproj.filters index a4bd1d17b..c51141a60 100644 --- a/Telegram/Telegram.vcxproj.filters +++ b/Telegram/Telegram.vcxproj.filters @@ -1254,6 +1254,24 @@ GeneratedFiles\Release + + GeneratedFiles\Deploy + + + GeneratedFiles\Debug + + + GeneratedFiles\Release + + + GeneratedFiles\Deploy + + + GeneratedFiles\Debug + + + GeneratedFiles\Release + @@ -1463,12 +1481,6 @@ SourceFiles\profile - - SourceFiles\profile - - - SourceFiles\profile - SourceFiles\ui\buttons @@ -1741,6 +1753,12 @@ SourceFiles\profile + + SourceFiles\profile + + + SourceFiles\profile +