From a06a989f9717c226eca2ded745157cf8094990c0 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 27 May 2016 18:45:35 +0300 Subject: [PATCH] New profile fixed top bar now is peer observer. Multiple showAnimated() calls for SectionWidget are now allowed. --- Telegram/SourceFiles/app.cpp | 49 ++++++++++++++++--- Telegram/SourceFiles/historywidget.cpp | 6 ++- Telegram/SourceFiles/observer_peer.h | 6 ++- .../SourceFiles/profile/profile_fixed_bar.cpp | 35 ++++++++++--- .../SourceFiles/profile/profile_fixed_bar.h | 15 ++++-- .../SourceFiles/profile/profile_widget.cpp | 2 +- Telegram/SourceFiles/structs.cpp | 6 ++- Telegram/SourceFiles/structs.h | 16 +++++- .../SourceFiles/window/section_widget.cpp | 3 +- 9 files changed, 112 insertions(+), 26 deletions(-) diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 260a5268c..be22abcf3 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -381,7 +381,8 @@ namespace { PeerId peer(peerFromUser(d.vid.v)); data = App::user(peer); - auto canShareThisContact = data->canShareThisContact(); + auto canShareThisContact = data->canShareThisContactFast(); + wasContact = data->isContact(); data->input = MTP_inputPeerUser(d.vid, MTP_long(0)); data->inputUser = MTP_inputUser(d.vid, MTP_long(0)); @@ -390,13 +391,15 @@ namespace { data->access = UserNoAccess; data->flags = 0; data->setBotInfoVersion(-1); - wasContact = (data->contact > 0); status = &emptyStatus; data->contact = -1; - if (canShareThisContact != data->canShareThisContact()) { + if (canShareThisContact != data->canShareThisContactFast()) { update.flags |= UpdateFlag::UserCanShareContact; } + if (wasContact != data->isContact()) { + update.flags |= UpdateFlag::UserIsContact; + } } break; case mtpc_user: { const auto &d(user.c_user()); @@ -404,8 +407,8 @@ namespace { PeerId peer(peerFromUser(d.vid.v)); data = App::user(peer); - auto canShareThisContact = data->canShareThisContact(); - + auto canShareThisContact = data->canShareThisContactFast(); + wasContact = data->isContact(); if (!minimal) { data->flags = d.vflags.v; if (d.is_self()) { @@ -468,7 +471,6 @@ namespace { if (d.has_access_hash()) data->access = d.vaccess_hash.v; status = d.has_status() ? &d.vstatus : &emptyStatus; } - wasContact = (data->contact > 0); if (!minimal) { if (d.has_bot_info_version()) { data->setBotInfoVersion(d.vbot_info_version.v); @@ -489,9 +491,12 @@ namespace { } } - if (canShareThisContact != data->canShareThisContact()) { + if (canShareThisContact != data->canShareThisContactFast()) { update.flags |= UpdateFlag::UserCanShareContact; } + if (wasContact != data->isContact()) { + update.flags |= UpdateFlag::UserIsContact; + } } break; } @@ -647,6 +652,7 @@ namespace { auto wasInChannel = cdata->amIn(); auto canEditPhoto = cdata->canEditPhoto(); auto canAddMembers = cdata->canAddParticipants(); + auto wasEditor = cdata->amEditor(); if (minimal) { MTPDchannel::Flags mask = MTPDchannel::Flag::f_broadcast | MTPDchannel::Flag::f_verified | MTPDchannel::Flag::f_megagroup | MTPDchannel::Flag::f_democracy; @@ -681,6 +687,9 @@ namespace { if (canAddMembers != cdata->canAddParticipants()) { update.flags |= UpdateFlag::ChannelCanAddMembers; } + if (wasEditor != cdata->amEditor()) { + update.flags |= UpdateFlag::ChannelAmEditor; + } } break; case mtpc_channelForbidden: { auto &d(chat.c_channelForbidden()); @@ -693,6 +702,7 @@ namespace { auto wasInChannel = cdata->amIn(); auto canEditPhoto = cdata->canEditPhoto(); auto canAddMembers = cdata->canAddParticipants(); + auto wasEditor = cdata->amEditor(); cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash); @@ -713,6 +723,9 @@ namespace { if (canAddMembers != cdata->canAddParticipants()) { update.flags |= UpdateFlag::ChannelCanAddMembers; } + if (wasEditor != cdata->amEditor()) { + update.flags |= UpdateFlag::ChannelAmEditor; + } } break; } if (!data) continue; @@ -1227,7 +1240,7 @@ namespace { void feedUserLinkDelayed(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink) { UserData *user = userLoaded(userId.v); if (user) { - bool wasContact = (user->contact > 0); + auto wasContact = user->isContact(); bool wasShowPhone = !user->contact; switch (myLink.type()) { case mtpc_contactLinkContact: @@ -1250,6 +1263,12 @@ namespace { user->contact = 0; } } + + if (wasContact != user->isContact()) { + Notify::PeerUpdate update(user); + update.flags |= Notify::PeerUpdateFlag::UserIsContact; + Notify::peerUpdatedDelayed(update); + } if ((user->contact > 0 && !wasContact) || (wasContact && user->contact < 1)) { Notify::userIsContactChanged(user); } @@ -2353,11 +2372,25 @@ namespace { } void regSharedContactItem(int32 userId, HistoryItem *item) { + auto user = App::userLoaded(userId); + auto canShareThisContact = user ? user->canShareThisContact() : false; ::sharedContactItems[userId].insert(item, NullType()); + if (canShareThisContact != (user ? user->canShareThisContact() : false)) { + Notify::PeerUpdate update(user); + update.flags |= Notify::PeerUpdateFlag::UserCanShareContact; + Notify::peerUpdatedDelayed(update); + } } void unregSharedContactItem(int32 userId, HistoryItem *item) { + auto user = App::userLoaded(userId); + auto canShareThisContact = user ? user->canShareThisContact() : false; ::sharedContactItems[userId].remove(item); + if (canShareThisContact != (user ? user->canShareThisContact() : false)) { + Notify::PeerUpdate update(user); + update.flags |= Notify::PeerUpdateFlag::UserCanShareContact; + Notify::peerUpdatedDelayed(update); + } } const SharedContactItems &sharedContactItems() { diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 281848506..4375ede39 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -5034,12 +5034,14 @@ void HistoryWidget::onBroadcastSilentChange() { } void HistoryWidget::onShareContact(const PeerId &peer, UserData *contact) { - if (!contact || contact->phone.isEmpty()) return; + auto phone = contact->phone; + if (phone.isEmpty()) phone = App::phoneFromSharedContact(peerToUser(contact->id)); + if (!contact || phone.isEmpty()) return; Ui::showPeerHistory(peer, ShowAtTheEndMsgId); if (!_history) return; - shareContact(peer, contact->phone, contact->firstName, contact->lastName, replyToId(), peerToUser(contact->id)); + shareContact(peer, phone, contact->firstName, contact->lastName, replyToId(), peerToUser(contact->id)); } void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, int32 userId) { diff --git a/Telegram/SourceFiles/observer_peer.h b/Telegram/SourceFiles/observer_peer.h index 18a425bcf..06f07b73a 100644 --- a/Telegram/SourceFiles/observer_peer.h +++ b/Telegram/SourceFiles/observer_peer.h @@ -35,12 +35,14 @@ enum class PeerUpdateFlag { PhotoChanged = 0x00000004U, UserCanShareContact = 0x00010000U, + UserIsContact = 0x00020000U, ChatCanEdit = 0x00010000U, ChannelAmIn = 0x00010000U, - ChannelCanEditPhoto = 0x00020000U, - ChannelCanAddMembers = 0x00040000U, + ChannelAmEditor = 0x00020000U, + ChannelCanEditPhoto = 0x00040000U, + ChannelCanAddMembers = 0x00080000U, }; Q_DECLARE_FLAGS(PeerUpdateFlags, PeerUpdateFlag); Q_DECLARE_OPERATORS_FOR_FLAGS(PeerUpdateFlags); diff --git a/Telegram/SourceFiles/profile/profile_fixed_bar.cpp b/Telegram/SourceFiles/profile/profile_fixed_bar.cpp index 4c09eb88c..71980895f 100644 --- a/Telegram/SourceFiles/profile/profile_fixed_bar.cpp +++ b/Telegram/SourceFiles/profile/profile_fixed_bar.cpp @@ -26,6 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "mainwidget.h" #include "boxes/addcontactbox.h" #include "boxes/confirmbox.h" +#include "observer_peer.h" namespace Profile { @@ -60,6 +61,15 @@ private: }; +namespace { + +const Notify::PeerUpdateFlags ButtonsUpdateFlags = Notify::PeerUpdateFlag::UserCanShareContact + | Notify::PeerUpdateFlag::UserIsContact + | Notify::PeerUpdateFlag::ChatCanEdit + | Notify::PeerUpdateFlag::ChannelAmEditor; + +} // namespace + FixedBar::FixedBar(QWidget *parent, PeerData *peer) : TWidget(parent) , _peer(peer) , _peerUser(peer->asUser()) @@ -70,9 +80,20 @@ FixedBar::FixedBar(QWidget *parent, PeerData *peer) : TWidget(parent) _backButton->moveToLeft(0, 0); connect(_backButton, SIGNAL(clicked()), this, SLOT(onBack())); + Notify::registerPeerObserver(ButtonsUpdateFlags, this, &FixedBar::notifyPeerUpdate); + refreshRightActions(); } +void FixedBar::notifyPeerUpdate(const Notify::PeerUpdate &update) { + if (update.peer != _peer) { + return; + } + if ((update.flags & ButtonsUpdateFlags) != 0) { + refreshRightActions(); + } +} + void FixedBar::refreshRightActions() { _currentAction = 0; if (_peerUser) { @@ -92,13 +113,14 @@ void FixedBar::refreshRightActions() { } void FixedBar::setUserActions() { - if (_peerUser->contact > 0) { + if (_peerUser->canShareThisContact()) { + addRightAction(RightActionType::ShareContact, lang(lng_profile_top_bar_share_contact), SLOT(onShareContact())); + } + if (_peerUser->isContact()) { addRightAction(RightActionType::EditContact, lang(lng_profile_edit_contact), SLOT(onEditContact())); addRightAction(RightActionType::DeleteContact, lang(lng_profile_delete_contact), SLOT(onDeleteContact())); - addRightAction(RightActionType::ShareContact, lang(lng_profile_top_bar_share_contact), SLOT(onShareContact())); - } else if (_peerUser->contact == 0 || !App::phoneFromSharedContact(peerToUser(_peer->id)).isEmpty()) { + } else if (_peerUser->canAddContact()) { addRightAction(RightActionType::AddContact, lang(lng_profile_add_contact), SLOT(onAddContact())); - addRightAction(RightActionType::ShareContact, lang(lng_profile_top_bar_share_contact), SLOT(onShareContact())); } } @@ -129,9 +151,10 @@ void FixedBar::addRightAction(RightActionType type, const QString &text, const c } } else { t_assert(_rightActions.size() == _currentAction); - _rightActions.push_back({}); + _rightActions.push_back(RightAction()); } _rightActions[_currentAction].type = type; + delete _rightActions[_currentAction].button; _rightActions[_currentAction].button = new FlatButton(this, text, st::profileFixedBarButton); connect(_rightActions[_currentAction].button, SIGNAL(clicked()), this, slot); bool showButton = !_animatingMode && (type != RightActionType::ShareContact || !_hideShareContactButton); @@ -235,7 +258,7 @@ void FixedBar::setHideShareContactButton(bool hideButton) { void FixedBar::applyHideShareContactButton() { for_const (auto &action, _rightActions) { if (action.type == RightActionType::ShareContact) { - action.button->setVisible(_hideShareContactButton); + action.button->setVisible(!_hideShareContactButton); } } } diff --git a/Telegram/SourceFiles/profile/profile_fixed_bar.h b/Telegram/SourceFiles/profile/profile_fixed_bar.h index fdc685057..0b6d131e0 100644 --- a/Telegram/SourceFiles/profile/profile_fixed_bar.h +++ b/Telegram/SourceFiles/profile/profile_fixed_bar.h @@ -20,11 +20,17 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +#include "core/observer.h" + +namespace Notify { +struct PeerUpdate; +} // namespace Notify + namespace Profile { class BackButton; -class FixedBar final : public TWidget { +class FixedBar final : public TWidget, public Notify::Observer { Q_OBJECT public: @@ -57,6 +63,8 @@ private slots: void onLeaveGroupSure(); private: + void notifyPeerUpdate(const Notify::PeerUpdate &update); + void refreshRightActions(); void setUserActions(); void setChatActions(); @@ -64,6 +72,7 @@ private: void setChannelActions(); enum class RightActionType { + None, EditChannel, EditGroup, LeaveGroup, @@ -86,8 +95,8 @@ private: int _currentAction = 0; struct RightAction { - RightActionType type; - FlatButton *button; + RightActionType type = RightActionType::None; + FlatButton *button = nullptr; }; QList _rightActions; diff --git a/Telegram/SourceFiles/profile/profile_widget.cpp b/Telegram/SourceFiles/profile/profile_widget.cpp index 15a258e07..2ee66562f 100644 --- a/Telegram/SourceFiles/profile/profile_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_widget.cpp @@ -109,7 +109,7 @@ void Widget::resizeEvent(QResizeEvent *e) { // _inner->resizeToWidth(scrollSize.width(), _scroll->height()); _inner->resizeToWidth(scrollSize.width(), _scroll->height() * 2); // testing } - _fixedBar->setHideShareContactButton(!_inner->shareContactButtonShown()); + _fixedBar->setHideShareContactButton(_inner->shareContactButtonShown()); if (!_scroll->isHidden()) { if (topDelta()) { diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index a3e3f72bd..2d0971297 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -198,6 +198,10 @@ const Text &BotCommand::descriptionText() const { return _descriptionText; } +bool UserData::canShareThisContact() const { + return canShareThisContactFast() || !App::phoneFromSharedContact(peerToUser(id)).isEmpty(); +} + void UserData::setPhoto(const MTPUserProfilePhoto &p) { // see Local::readPeer as well PhotoId newPhotoId = photoId; ImagePtr newPhoto = _userpic; @@ -490,7 +494,7 @@ void ChannelData::flagsUpdated() { } } else if (mgInfo) { delete mgInfo; - mgInfo = 0; + mgInfo = nullptr; } } diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index 99698b27d..e14eb290b 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -429,8 +429,20 @@ public: bool canWrite() const { return access != UserNoAccess; } - bool canShareThisContact() const { - return contact >= 0; + bool isContact() const { + return (contact > 0); + } + + bool canShareThisContact() const; + bool canAddContact() const { + return canShareThisContact() && !isContact(); + } + + // In feedUsers() we check only that. + // When actually trying to share contact we perform + // a full check by canShareThisContact() call. + bool canShareThisContactFast() const { + return !phone.isEmpty(); } MTPInputUser inputUser; diff --git a/Telegram/SourceFiles/window/section_widget.cpp b/Telegram/SourceFiles/window/section_widget.cpp index f9c3a1454..47c085446 100644 --- a/Telegram/SourceFiles/window/section_widget.cpp +++ b/Telegram/SourceFiles/window/section_widget.cpp @@ -41,7 +41,7 @@ void SectionWidget::setGeometryWithTopMoved(const QRect &newGeometry, int topDel } void SectionWidget::showAnimated(SlideDirection direction, const SectionSlideParams ¶ms) { - t_assert(_showAnimation == nullptr); + if (_showAnimation) return; showChildren(); auto myContentCache = grabForShowAnimation(params); @@ -69,6 +69,7 @@ void SectionWidget::paintEvent(QPaintEvent *e) { } void SectionWidget::showFinished() { + _showAnimation.reset(); if (isHidden()) return; App::app()->mtpUnpause();