diff --git a/Telegram/Resources/icons/info_administrators.png b/Telegram/Resources/icons/info_administrators.png new file mode 100644 index 000000000..18629085a Binary files /dev/null and b/Telegram/Resources/icons/info_administrators.png differ diff --git a/Telegram/Resources/icons/info_administrators@2x.png b/Telegram/Resources/icons/info_administrators@2x.png new file mode 100644 index 000000000..c23630fa8 Binary files /dev/null and b/Telegram/Resources/icons/info_administrators@2x.png differ diff --git a/Telegram/Resources/icons/info_blacklist.png b/Telegram/Resources/icons/info_blacklist.png new file mode 100644 index 000000000..8907a45cc Binary files /dev/null and b/Telegram/Resources/icons/info_blacklist.png differ diff --git a/Telegram/Resources/icons/info_blacklist@2x.png b/Telegram/Resources/icons/info_blacklist@2x.png new file mode 100644 index 000000000..597edc9db Binary files /dev/null and b/Telegram/Resources/icons/info_blacklist@2x.png differ diff --git a/Telegram/Resources/icons/info_recent_actions.png b/Telegram/Resources/icons/info_recent_actions.png new file mode 100644 index 000000000..ec6b701b0 Binary files /dev/null and b/Telegram/Resources/icons/info_recent_actions.png differ diff --git a/Telegram/Resources/icons/info_recent_actions@2x.png b/Telegram/Resources/icons/info_recent_actions@2x.png new file mode 100644 index 000000000..432446119 Binary files /dev/null and b/Telegram/Resources/icons/info_recent_actions@2x.png differ diff --git a/Telegram/Resources/icons/info_restricted_users.png b/Telegram/Resources/icons/info_restricted_users.png new file mode 100644 index 000000000..348a6a820 Binary files /dev/null and b/Telegram/Resources/icons/info_restricted_users.png differ diff --git a/Telegram/Resources/icons/info_restricted_users@2x.png b/Telegram/Resources/icons/info_restricted_users@2x.png new file mode 100644 index 000000000..e059b2efe Binary files /dev/null and b/Telegram/Resources/icons/info_restricted_users@2x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index d5fc7f8e6..95241634c 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -649,6 +649,16 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_media_selected_link#one" = "{count} Shared link"; "lng_media_selected_link#other" = "{count} Shared links"; +"lng_manage_group_title" = "Manage Group"; +"lng_manage_channel_title" = "Manage Channel"; +"lng_manage_group_info" = "Group Info"; +"lng_manage_channel_info" = "Channel Info"; +"lng_manage_peer_recent_actions" = "Recent Actions"; +"lng_manage_peer_members" = "Members"; +"lng_manage_peer_administrators" = "Administrators"; +"lng_manage_peer_banned_users" = "Banned users"; +"lng_manage_peer_restricted_users" = "Restricted users"; + "lng_report_title" = "Report channel"; "lng_report_group_title" = "Report group"; "lng_report_bot_title" = "Report bot"; diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index d043049de..bf39695a7 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -387,7 +387,8 @@ void PeerListRow::paintNameIcon( Painter &p, int x, int y, - int outerWidth) { + int outerWidth, + bool selected) { st::dialogsVerifiedIcon.paint(p, x, y, outerWidth); } @@ -1060,7 +1061,8 @@ TimeMs PeerListContent::paintRow(Painter &p, TimeMs ms, RowIndex index) { p, namex + qMin(name.maxWidth(), namew), _st.item.namePosition.y(), - width()); + width(), + selected); } auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio(); p.setPen(anim::pen(st::contactsNameFg, st::contactsNameCheckedFg, nameCheckedRatio)); diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index 19c128acd..203998f41 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -91,7 +91,8 @@ public: Painter &p, int x, int y, - int outerWidth); + int outerWidth, + bool selected); virtual QSize actionSize() const { return QSize(); } diff --git a/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp b/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp new file mode 100644 index 000000000..8cd0af796 --- /dev/null +++ b/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp @@ -0,0 +1,228 @@ +/* +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-2017 John Preston, https://desktop.telegram.org +*/ +#include "boxes/peers/manage_peer_box.h" + +#include +#include "lang/lang_keys.h" +#include "ui/wrap/vertical_layout.h" +#include "ui/widgets/labels.h" +#include "history/history_admin_log_section.h" +#include "window/window_controller.h" +#include "profile/profile_channel_controllers.h" +#include "info/profile/info_profile_button.h" +#include "info/profile/info_profile_icon.h" +#include "info/profile/info_profile_values.h" +#include "styles/style_boxes.h" +#include "styles/style_info.h" + +namespace { + +base::lambda ManageBoxTitle( + not_null channel) { + return langFactory(channel->isMegagroup() + ? lng_manage_group_title + : lng_manage_channel_title); +} + +auto ToPositiveNumberString() { + return rpl::map([](int count) { + return count ? QString::number(count) : QString(); + }); +} + +template +Info::Profile::Button *AddButton( + not_null parent, + rpl::producer &&text, + Callback callback, + const style::icon &icon) { + auto button = parent->add( + object_ptr( + parent, + std::move(text), + st::managePeerButton)); + button->addClickHandler(std::forward(callback)); + Ui::CreateChild( + button, + icon, + st::managePeerButtonIconPosition); + return button; +} + +template +void AddButtonWithCount( + not_null parent, + rpl::producer &&text, + rpl::producer &&count, + Callback callback, + const style::icon &icon) { + auto button = AddButton( + parent, + std::move(text), + std::forward(callback), + icon); + auto label = Ui::CreateChild( + button, + std::move(count), + st::managePeerButtonLabel); + rpl::combine(button->widthValue(), label->widthValue()) + | rpl::start_with_next([label](int outerWidth, int width) { + label->moveToRight( + st::managePeerButtonLabelPosition.x(), + st::managePeerButtonLabelPosition.y(), + outerWidth); + }, label->lifetime()); +} + +bool HasRecentActions(not_null channel) { + return channel->hasAdminRights() || channel->amCreator(); +} + +void ShowRecentActions( + not_null controller, + not_null channel) { + controller->showSection( + AdminLog::SectionMemento(channel), + Window::SectionShow()); + +} + +void FillManageBox( + not_null controller, + not_null channel, + not_null content) { + using Profile::ParticipantsBoxController; + + auto isGroup = channel->isMegagroup(); + if (channel->canEditInformation()) { + AddButton( + content, + Lang::Viewer(isGroup + ? lng_manage_group_info + : lng_manage_channel_info), + [=] { + + }, + st::infoIconInformation); + } + if (HasRecentActions(channel)) { + AddButton( + content, + Lang::Viewer(lng_manage_peer_recent_actions), + [=] { ShowRecentActions(controller, channel); }, + st::infoIconRecentActions); + } + if (channel->canViewMembers()) { + AddButtonWithCount( + content, + Lang::Viewer(lng_manage_peer_members), + Info::Profile::MembersCountValue(channel) + | ToPositiveNumberString(), + [=] { + ParticipantsBoxController::Start( + controller, + channel, + ParticipantsBoxController::Role::Members); + }, + st::infoIconMembers); + } + if (channel->canViewAdmins()) { + AddButtonWithCount( + content, + Lang::Viewer(lng_manage_peer_administrators), + Info::Profile::AdminsCountValue(channel) + | ToPositiveNumberString(), + [=] { + ParticipantsBoxController::Start( + controller, + channel, + ParticipantsBoxController::Role::Admins); + }, + st::infoIconAdministrators); + } + if (channel->canViewBanned()) { + AddButtonWithCount( + content, + Lang::Viewer(lng_manage_peer_restricted_users), + Info::Profile::RestrictedCountValue(channel) + | ToPositiveNumberString(), + [=] { + ParticipantsBoxController::Start( + controller, + channel, + ParticipantsBoxController::Role::Restricted); + }, + st::infoIconRestrictedUsers); + AddButtonWithCount( + content, + Lang::Viewer(lng_manage_peer_banned_users), + Info::Profile::KickedCountValue(channel) + | ToPositiveNumberString(), + [=] { + ParticipantsBoxController::Start( + controller, + channel, + ParticipantsBoxController::Role::Kicked); + }, + st::infoIconBlacklist); + } +} + +} // namespace + +ManagePeerBox::ManagePeerBox( + QWidget*, + not_null channel) +: _channel(channel) { +} + +bool ManagePeerBox::Available(not_null channel) { + // canViewAdmins() is removed, because in supergroups it is + // always true and in channels it is equal to canViewBanned(). + + return channel->canViewMembers() +// || channel->canViewAdmins() + || channel->canViewBanned() + || channel->canEditInformation() + || HasRecentActions(channel); +} + +void ManagePeerBox::prepare() { + _channel->updateFull(); + + setTitle(ManageBoxTitle(_channel)); + addButton(langFactory(lng_cancel), [this] { closeBox(); }); + + setupContent(); +} + +void ManagePeerBox::setupContent() { + auto content = Ui::CreateChild(this); + FillManageBox(controller(), _channel, content); + widthValue() + | rpl::start_with_next([=](int width) { + content->resizeToWidth(width); + }, content->lifetime()); + content->heightValue() + | rpl::start_with_next([=](int height) { + setDimensions(st::boxWidth, height); + }, content->lifetime()); +} diff --git a/Telegram/SourceFiles/boxes/peers/manage_peer_box.h b/Telegram/SourceFiles/boxes/peers/manage_peer_box.h new file mode 100644 index 000000000..a0acfe37c --- /dev/null +++ b/Telegram/SourceFiles/boxes/peers/manage_peer_box.h @@ -0,0 +1,39 @@ +/* +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-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "boxes/abstract_box.h" + +class ManagePeerBox : public BoxContent { +public: + ManagePeerBox(QWidget*, not_null channel); + + static bool Available(not_null channel); + +protected: + void prepare() override; + +private: + void setupContent(); + + not_null _channel; + +}; diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 281c2bea6..56891867a 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -245,16 +245,20 @@ using UpdateFlag = Notify::PeerUpdate::Flag; NotifySettings globalNotifyAll, globalNotifyUsers, globalNotifyChats; NotifySettingsPtr globalNotifyAllPtr = UnknownNotifySettings, globalNotifyUsersPtr = UnknownNotifySettings, globalNotifyChatsPtr = UnknownNotifySettings; -PeerClickHandler::PeerClickHandler(not_null peer) : _peer(peer) { +PeerClickHandler::PeerClickHandler(not_null peer) +: _peer(peer) { } void PeerClickHandler::onClick(Qt::MouseButton button) const { - if (button == Qt::LeftButton && App::main()) { - if (_peer && _peer->isChannel() && App::main()->historyPeer() != _peer) { + if (button == Qt::LeftButton && App::wnd()) { + auto controller = App::wnd()->controller(); + if (_peer && _peer->isChannel() && controller->historyPeer.current() != _peer) { if (!_peer->asChannel()->isPublic() && !_peer->asChannel()->amIn()) { - Ui::show(Box(lang((_peer->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); + Ui::show(Box(lang(_peer->isMegagroup() + ? lng_group_not_accessible + : lng_channel_not_accessible))); } else { - App::wnd()->controller()->showPeerHistory( + controller->showPeerHistory( _peer, Window::SectionShow::Way::Forward); } @@ -264,15 +268,21 @@ void PeerClickHandler::onClick(Qt::MouseButton button) const { } } -PeerData::PeerData(const PeerId &id) : id(id), _colorIndex(peerColorIndex(id)) { +PeerData::PeerData(const PeerId &id) +: id(id) +, _colorIndex(peerColorIndex(id)) { nameText.setText(st::msgNameStyle, QString(), _textNameOptions); _userpicEmpty.set(_colorIndex, QString()); } -void PeerData::updateNameDelayed(const QString &newName, const QString &newNameOrPhone, const QString &newUsername) { +void PeerData::updateNameDelayed( + const QString &newName, + const QString &newNameOrPhone, + const QString &newUsername) { if (name == newName) { if (isUser()) { - if (asUser()->nameOrPhone == newNameOrPhone && asUser()->username == newUsername) { + if (asUser()->nameOrPhone == newNameOrPhone + && asUser()->username == newUsername) { return; } } else if (isChannel()) { diff --git a/Telegram/SourceFiles/history/history_admin_log_section.h b/Telegram/SourceFiles/history/history_admin_log_section.h index ab4ea1387..314b43c66 100644 --- a/Telegram/SourceFiles/history/history_admin_log_section.h +++ b/Telegram/SourceFiles/history/history_admin_log_section.h @@ -85,7 +85,7 @@ public: Widget(QWidget *parent, not_null controller, not_null channel); not_null channel() const; - PeerData *peerForDialogs() const override { + PeerData *activePeer() const override { return channel(); } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index fc956e485..8e46127f3 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -1731,6 +1731,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re if (peerId) { _peer = App::peer(peerId); + _topBar->setHistoryPeer(_peer); _channel = peerToChannel(_peer->id); _canSendMessages = canSendMessages(_peer); _tabbedSelector->setCurrentPeer(_peer); @@ -1843,6 +1844,9 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re emit historyShown(_history, _showAtMsgId); controller()->historyPeer = _peer; + if (_peer) { + controller()->activePeer = _peer; + } update(); } diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index fe494253c..06c999198 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -313,6 +313,10 @@ infoIconMediaLink: icon {{ "info_media_link", infoIconFg }}; infoIconMediaGroup: icon {{ "info_common_groups", infoIconFg }}; infoIconMediaVoice: icon {{ "info_media_voice", infoIconFg }}; infoIconMediaRound: icon {{ "info_media_round", infoIconFg }}; +infoIconRecentActions: icon {{ "info_recent_actions", infoIconFg }}; +infoIconAdministrators: icon {{ "info_administrators", infoIconFg }}; +infoIconBlacklist: icon {{ "info_blacklist", infoIconFg }}; +infoIconRestrictedUsers: icon {{ "info_restricted_users", infoIconFg }}; infoInformationIconPosition: point(25px, 12px); infoNotificationsIconPosition: point(20px, 5px); infoSharedMediaIconPosition: point(20px, 24px); @@ -483,11 +487,21 @@ infoMembersCreatorIcon: icon {{ profileAdminStartFg, point(4px, 3px) }}; +infoMembersCreatorIconOver: icon {{ + "profile_admin_star", + profileAdminStarFgOver, + point(4px, 3px) +}}; infoMembersAdminIcon: icon {{ "profile_admin_star", profileOtherAdminStarFg, point(4px, 3px) }}; +infoMembersAdminIconOver: icon {{ + "profile_admin_star", + profileOtherAdminStarFgOver, + point(4px, 3px) +}}; infoMembersRemoveIcon: icon {{ "simple_close", menuIconFg @@ -522,3 +536,13 @@ infoCommonGroupsList: PeerList(infoMembersList) { statusPosition: point(79px, 31px); } } + +managePeerButton: InfoProfileButton(infoProfileButton) { + padding: margins(76px, 10px, 76px, 8px); +} +managePeerButtonIconPosition: infoSharedMediaButtonIconPosition; +managePeerButtonLabel: FlatLabel(defaultFlatLabel) { + textFg: windowActiveTextFg; + style: semiboldTextStyle; +} +managePeerButtonLabelPosition: point(25px, 10px); diff --git a/Telegram/SourceFiles/info/info_section_widget.cpp b/Telegram/SourceFiles/info/info_section_widget.cpp index 7a8d7d7b9..fff4f9846 100644 --- a/Telegram/SourceFiles/info/info_section_widget.cpp +++ b/Telegram/SourceFiles/info/info_section_widget.cpp @@ -56,8 +56,8 @@ void SectionWidget::init() { }, _content->lifetime()); } -PeerData *SectionWidget::peerForDialogs() const { - return _content->peerForDialogs(); +PeerData *SectionWidget::activePeer() const { + return _content->activePeer(); } bool SectionWidget::hasTopBarShadow() const { diff --git a/Telegram/SourceFiles/info/info_section_widget.h b/Telegram/SourceFiles/info/info_section_widget.h index 7ee9f899d..6dd34ae8d 100644 --- a/Telegram/SourceFiles/info/info_section_widget.h +++ b/Telegram/SourceFiles/info/info_section_widget.h @@ -48,7 +48,7 @@ public: Wrap wrap, not_null memento); - PeerData *peerForDialogs() const override; + PeerData *activePeer() const override; bool hasTopBarShadow() const override; QPixmap grabForShowAnimation( diff --git a/Telegram/SourceFiles/info/info_wrap_widget.h b/Telegram/SourceFiles/info/info_wrap_widget.h index e15dba0d0..d0b7f1da0 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.h +++ b/Telegram/SourceFiles/info/info_wrap_widget.h @@ -88,7 +88,7 @@ public: not_null memento); not_null peer() const; - PeerData *peerForDialogs() const override { + PeerData *activePeer() const override { return peer(); } Wrap wrap() const { diff --git a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp index 0a4b562a3..f6e5dea5a 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp @@ -363,11 +363,16 @@ void MemberListRow::paintNameIcon( Painter &p, int x, int y, - int outerWidth) { + int outerWidth, + bool selected) { auto icon = [&] { return (_type.rights == Rights::Admin) - ? &st::infoMembersAdminIcon - : &st::infoMembersCreatorIcon; + ? (selected + ? &st::infoMembersAdminIconOver + : &st::infoMembersAdminIcon) + : (selected + ? &st::infoMembersCreatorIconOver + : &st::infoMembersCreatorIcon); }(); icon->paint(p, x, y, outerWidth); } diff --git a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h index 56762d9fe..2c1ad5fd6 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h +++ b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h @@ -58,7 +58,8 @@ public: Painter &p, int x, int y, - int outerWidth) override; + int outerWidth, + bool selected) override; not_null user() const { return peer()->asUser(); diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index 7d1d535f4..5bbc677b3 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -202,6 +202,45 @@ rpl::producer MembersCountValue( Unexpected("User in MembersCountViewer()."); } +rpl::producer AdminsCountValue( + not_null channel) { + using Flag = Notify::PeerUpdate::Flag; + return Notify::PeerUpdateValue( + channel, + Flag::AdminsChanged | Flag::ChannelRightsChanged) + | rpl::map([channel] { + return channel->canViewAdmins() + ? channel->adminsCount() + : 0; + }); +} + +rpl::producer RestrictedCountValue( + not_null channel) { + using Flag = Notify::PeerUpdate::Flag; + return Notify::PeerUpdateValue( + channel, + Flag::BannedUsersChanged | Flag::ChannelRightsChanged) + | rpl::map([channel] { + return channel->canViewBanned() + ? channel->restrictedCount() + : 0; + }); +} + +rpl::producer KickedCountValue( + not_null channel) { + using Flag = Notify::PeerUpdate::Flag; + return Notify::PeerUpdateValue( + channel, + Flag::BannedUsersChanged | Flag::ChannelRightsChanged) + | rpl::map([channel] { + return channel->canViewBanned() + ? channel->kickedCount() + : 0; + }); +} + rpl::producer SharedMediaCountValue( not_null peer, PeerData *migrated, diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.h b/Telegram/SourceFiles/info/profile/info_profile_values.h index 3852ab82f..79ead5e86 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.h +++ b/Telegram/SourceFiles/info/profile/info_profile_values.h @@ -75,6 +75,12 @@ rpl::producer AmInChannelValue( not_null channel); rpl::producer MembersCountValue( not_null peer); +rpl::producer AdminsCountValue( + not_null channel); +rpl::producer RestrictedCountValue( + not_null channel); +rpl::producer KickedCountValue( + not_null channel); rpl::producer SharedMediaCountValue( not_null peer, PeerData *migrated, diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index f2ad4e059..306407568 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -271,7 +271,7 @@ MainWidget::MainWidget( }); using namespace rpl::mappers; - _controller->historyPeer.value() + _controller->activePeer.value() | rpl::map([](PeerData *peer) { auto canWrite = peer ? Data::CanWriteValue(peer) @@ -2432,7 +2432,7 @@ void MainWidget::ui_showPeerHistory( break; } } - if (auto historyPeer = _history->peer()) { + if (auto historyPeer = _controller->historyPeer.current()) { if (way == Way::Forward && historyPeer->id == peerId) { way = Way::ClearStack; } @@ -2552,6 +2552,10 @@ void MainWidget::ui_showPeerHistory( _dialogs->update(); } + if (!peerId) { + _controller->activePeer = nullptr; + } + checkFloatPlayerVisibility(); } @@ -2577,10 +2581,6 @@ void MainWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPe _dialogs->peerAfter(inPeer, inMsg, outPeer, outMsg); } -PeerData *MainWidget::historyPeer() { - return _history->peer(); -} - PeerData *MainWidget::peer() { return _overview ? _overview->peer() : _history->peer(); } @@ -2962,6 +2962,10 @@ void MainWidget::showNewSection( settingSection->showFast(); } + if (settingSection.data() == _mainSection.data()) { + _controller->activePeer = _mainSection->activePeer(); + } + checkFloatPlayerVisibility(); orderWidgets(); } @@ -3530,8 +3534,11 @@ void MainWidget::updateThirdColumnToCurrentPeer( } else { Auth().data().setTabbedReplacedWithInfo(false); if (!peer) { - _thirdSection.destroy(); - _thirdShadow.destroy(); + if (_thirdSection) { + _thirdSection.destroy(); + _thirdShadow.destroy(); + updateControlsGeometry(); + } } else if (Adaptive::ThreeColumn() && Auth().data().thirdSectionInfoEnabled()) { switchInfoFast(); diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 0144793e9..2a8488161 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -149,7 +149,6 @@ public: void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg); void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg); - PeerData *historyPeer(); PeerData *peer(); PeerData *activePeer(); diff --git a/Telegram/SourceFiles/profile/profile_common_groups_section.h b/Telegram/SourceFiles/profile/profile_common_groups_section.h index f9afacac8..b0734f028 100644 --- a/Telegram/SourceFiles/profile/profile_common_groups_section.h +++ b/Telegram/SourceFiles/profile/profile_common_groups_section.h @@ -177,7 +177,7 @@ public: Widget(QWidget *parent, not_null controller, not_null user); not_null user() const; - PeerData *peerForDialogs() const override { + PeerData *activePeer() const override { return user(); } diff --git a/Telegram/SourceFiles/profile/profile_widget.h b/Telegram/SourceFiles/profile/profile_widget.h index 6fc462d95..b43a80cd4 100644 --- a/Telegram/SourceFiles/profile/profile_widget.h +++ b/Telegram/SourceFiles/profile/profile_widget.h @@ -39,7 +39,7 @@ public: Widget(QWidget *parent, not_null controller, PeerData *peer); PeerData *peer() const; - PeerData *peerForDialogs() const override { + PeerData *activePeer() const override { return peer(); } diff --git a/Telegram/SourceFiles/rpl/rpl.h b/Telegram/SourceFiles/rpl/rpl.h index 1805607f6..67505b4a3 100644 --- a/Telegram/SourceFiles/rpl/rpl.h +++ b/Telegram/SourceFiles/rpl/rpl.h @@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once +// rpl - reactive programming library + #include #include #include diff --git a/Telegram/SourceFiles/window/section_widget.h b/Telegram/SourceFiles/window/section_widget.h index 1847ec398..1b3ae98db 100644 --- a/Telegram/SourceFiles/window/section_widget.h +++ b/Telegram/SourceFiles/window/section_widget.h @@ -82,7 +82,7 @@ class SectionWidget : public AbstractSectionWidget { public: SectionWidget(QWidget *parent, not_null controller); - virtual PeerData *peerForDialogs() const { + virtual PeerData *activePeer() const { return nullptr; } diff --git a/Telegram/SourceFiles/window/top_bar_widget.cpp b/Telegram/SourceFiles/window/top_bar_widget.cpp index 684ec2fd3..6a59b95c7 100644 --- a/Telegram/SourceFiles/window/top_bar_widget.cpp +++ b/Telegram/SourceFiles/window/top_bar_widget.cpp @@ -99,7 +99,7 @@ TopBarWidget::TopBarWidget( }); } subscribe(App::histories().sendActionAnimationUpdated(), [this](const Histories::SendActionAnimationUpdate &update) { - if (App::main() && update.history->peer == App::main()->historyPeer()) { + if (update.history->peer == _controller->historyPeer.current()) { rtlupdate(0, 0, width(), height()); } }); @@ -139,9 +139,8 @@ void TopBarWidget::onClearSelection() { } void TopBarWidget::onInfoClicked() { - auto p = App::main() ? App::main()->historyPeer() : nullptr; - if (p) { - _controller->showPeerInfo(p); + if (auto peer = _controller->historyPeer.current()) { + _controller->showPeerInfo(peer); } } @@ -205,7 +204,7 @@ void TopBarWidget::toggleInfoSection() { && (Auth().data().thirdSectionInfoEnabled() || Auth().data().tabbedReplacedWithInfo())) { _controller->closeThirdSection(); - } else if (auto peer = App::main()->historyPeer()) { + } else if (auto peer = _controller->historyPeer.current()) { if (_controller->canShowThirdSection()) { Auth().data().setThirdSectionInfoEnabled(true); Auth().saveDataDelayed(); @@ -289,7 +288,7 @@ void TopBarWidget::paintUnreadCounter(Painter &p, int outerWidth) { auto fullCounter = App::histories().unreadBadge() + (Global::IncludeMuted() ? 0 : mutedCount); // Do not include currently shown chat in the top bar unread counter. - if (auto historyShown = App::historyLoaded(App::main()->historyPeer())) { + if (auto historyShown = App::historyLoaded(App::wnd()->controller()->historyPeer.current())) { auto shownUnreadCount = historyShown->unreadCount(); if (!historyShown->mute() || Global::IncludeMuted()) { fullCounter -= shownUnreadCount; @@ -370,7 +369,6 @@ void TopBarWidget::animationFinished() { } void TopBarWidget::updateControlsVisibility() { - auto historyPeer = App::main() ? App::main()->historyPeer() : nullptr; auto overviewPeer = App::main() ? App::main()->overviewPeer() : nullptr; _clearSelection->show(); @@ -378,9 +376,9 @@ void TopBarWidget::updateControlsVisibility() { _forward->setVisible(_canForward); _mediaType->setVisible(App::main() ? App::main()->showMediaTypeSwitch() : false); - if (historyPeer && !overviewPeer) { + if (_historyPeer && !overviewPeer) { if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) { - _info->setPeer(historyPeer); + _info->setPeer(_historyPeer); _info->show(); _menuToggle->hide(); _menu.destroy(); @@ -392,7 +390,7 @@ void TopBarWidget::updateControlsVisibility() { _infoToggle->setVisible(!Adaptive::OneColumn() && _controller->canShowThirdSection()); auto callsEnabled = false; - if (auto user = historyPeer->asUser()) { + if (auto user = _historyPeer->asUser()) { callsEnabled = Global::PhoneCallsEnabled() && user->hasCalls(); } _call->setVisible(callsEnabled); diff --git a/Telegram/SourceFiles/window/top_bar_widget.h b/Telegram/SourceFiles/window/top_bar_widget.h index 3fabbc739..0e1ba7c71 100644 --- a/Telegram/SourceFiles/window/top_bar_widget.h +++ b/Telegram/SourceFiles/window/top_bar_widget.h @@ -52,6 +52,9 @@ public: void updateMembersShowArea(); Ui::RoundButton *mediaTypeButton(); + void setHistoryPeer(not_null historyPeer) { + _historyPeer = historyPeer; + } static void paintUnreadCounter(Painter &p, int outerWidth); @@ -83,6 +86,7 @@ private: int countSelectedButtonsTop(float64 selectedShown); not_null _controller; + PeerData *_historyPeer = nullptr; int _selectedCount = 0; bool _canDelete = false; diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h index 9889f9db8..7f10978ad 100644 --- a/Telegram/SourceFiles/window/window_controller.h +++ b/Telegram/SourceFiles/window/window_controller.h @@ -90,8 +90,13 @@ public: // This is needed while we have one HistoryWidget and one TopBarWidget // for all histories we show in a window. Once each history is shown // in its own HistoryWidget with its own TopBarWidget this can be removed. + // + // Also used in the Info::Profile to toggle Send Message button. rpl::variable historyPeer; + // This is used for auto-switch in third column Info::Profile. + rpl::variable activePeer; + void enableGifPauseReason(GifPauseReason reason); void disableGifPauseReason(GifPauseReason reason); base::Observable &gifPauseLevelChanged() { diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index fa0d31e38..bdb94cfef 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -26,6 +26,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "boxes/add_contact_box.h" #include "boxes/report_box.h" #include "boxes/peer_list_controllers.h" +#include "boxes/peers/manage_peer_box.h" #include "auth_session.h" #include "apiwrap.h" #include "mainwidget.h" @@ -153,7 +154,7 @@ Filler::Filler( bool Filler::showInfo() { if (_source == PeerMenuSource::Profile) { return false; - } else if (_controller->historyPeer.current() != _peer) { + } else if (_controller->activePeer.current() != _peer) { return true; } else if (!Adaptive::ThreeColumn()) { return true; @@ -377,7 +378,14 @@ void Filler::addChatActions(not_null chat) { void Filler::addChannelActions(not_null channel) { if (_source != PeerMenuSource::ChatsList) { - //_addAction(manage); + if (ManagePeerBox::Available(channel)) { + auto text = lang(channel->isMegagroup() + ? lng_manage_group_title + : lng_manage_channel_title); + _addAction(text, [channel] { + Ui::show(Box(channel)); + }); + } if (channel->canAddMembers()) { _addAction( lang(lng_channel_add_members), diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 1d652e793..eb13f292c 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -34,6 +34,8 @@ <(src_loc)/base/virtual_method.h <(src_loc)/base/weak_unique_ptr.h <(src_loc)/base/zlib_help.h +<(src_loc)/boxes/peers/manage_peer_box.cpp +<(src_loc)/boxes/peers/manage_peer_box.h <(src_loc)/boxes/about_box.cpp <(src_loc)/boxes/about_box.h <(src_loc)/boxes/abstract_box.cpp