diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 9137e9c09d..8b7912ff59 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -47,6 +47,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "auth_session.h" #include "window/notifications_manager.h" #include "ui/effects/widget_fade_wrap.h" +#include "window/window_controller.h" namespace { @@ -2265,7 +2266,8 @@ void DialogsWidget::UpdateButton::paintEvent(QPaintEvent *e) { } } -DialogsWidget::DialogsWidget(QWidget *parent) : TWidget(parent) +DialogsWidget::DialogsWidget(QWidget *parent, gsl::not_null controller) : TWidget(parent) +, _controller(controller) , _mainMenuToggle(this, st::dialogsMenuToggle) , _filter(this, st::dialogsFilter, lang(lng_dlg_filter)) , _jumpToDate(this, object_ptr(this, st::dialogsCalendar)) @@ -2984,7 +2986,7 @@ void DialogsWidget::setSearchInPeer(PeerData *peer) { _searchInMigrated = newSearchInPeer ? newSearchInPeer->migrateFrom() : nullptr; if (newSearchInPeer != _searchInPeer) { _searchInPeer = newSearchInPeer; - App::main()->searchInPeerChanged().notify(_searchInPeer, true); + _controller->searchInPeerChanged().notify(_searchInPeer, true); updateJumpToDateVisibility(); } _inner->searchInPeer(_searchInPeer); diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index 91e7eff4f9..b8e4a91cf7 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -41,6 +41,10 @@ template class WidgetScaledFadeWrap; } // namespace Ui +namespace Window { +class Controller; +} // namespace Window + enum DialogsSearchRequestType { DialogsSearchFromStart, DialogsSearchFromOffset, @@ -303,7 +307,7 @@ class DialogsWidget : public TWidget, public RPCSender, private base::Subscriber Q_OBJECT public: - DialogsWidget(QWidget *parent); + DialogsWidget(QWidget *parent, gsl::not_null controller); void updateDragInScroll(bool inScroll); @@ -402,16 +406,18 @@ private: void updateControlsGeometry(); void updateForwardBar(); - bool _dragInScroll = false; - bool _dragForward = false; - QTimer _chooseByDragTimer; - void unreadCountsReceived(const QVector &dialogs); bool dialogsFailed(const RPCError &error, mtpRequestId req); bool contactsFailed(const RPCError &error); bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req); bool peopleFailed(const RPCError &error, mtpRequestId req); + gsl::not_null _controller; + + bool _dragInScroll = false; + bool _dragForward = false; + QTimer _chooseByDragTimer; + bool _dialogsFull = false; int32 _dialogsOffsetDate = 0; MsgId _dialogsOffsetId = 0; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 8cb33643bd..1e46c7ed6a 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -62,6 +62,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "platform/platform_file_utilities.h" #include "auth_session.h" #include "window/notifications_manager.h" +#include "window/window_controller.h" namespace { @@ -3191,8 +3192,10 @@ TextWithTags::Tags textTagsFromEntities(const EntitiesInText &entities) { return result; } -HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) +HistoryWidget::HistoryWidget(QWidget *parent, gsl::not_null controller) : TWidget(parent) +, _controller(controller) , _fieldBarCancel(this, st::historyReplyCancel) +, _topBar(this, _controller) , _scroll(this, st::historyScroll, false) , _historyDown(_scroll, st::historyToDown) , _fieldAutocomplete(this) @@ -3220,6 +3223,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) setAcceptDrops(true); subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); }); + connect(_topBar, &Window::TopBarWidget::clicked, this, [this] { topBarClick(); }); connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); connect(_reportSpamPanel, SIGNAL(reportClicked()), this, SLOT(onReportSpamClicked())); connect(_reportSpamPanel, SIGNAL(hideClicked()), this, SLOT(onReportSpamHide())); @@ -3280,6 +3284,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) _fieldBarCancel->hide(); + _topBar->hide(); _scroll->hide(); _keyboard = _kbScroll->setOwnedWidget(object_ptr(this)); @@ -4341,7 +4346,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re App::main()->dlgUpdated(wasHistory ? wasHistory->peer : nullptr, wasMsgId); emit historyShown(_history, _showAtMsgId); - App::main()->topBar()->update(); + _topBar->update(); update(); if (startBot && _peer->isUser() && _peer->asUser()->botInfo) { @@ -4423,7 +4428,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re noSelectingScroll(); _selCount = 0; - App::main()->topBar()->showSelected(0); + _topBar->showSelected(0); App::hoveredItem(nullptr); App::pressedItem(nullptr); @@ -4505,7 +4510,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re App::main()->dlgUpdated(wasHistory ? wasHistory->peer : nullptr, wasMsgId); emit historyShown(_history, _showAtMsgId); - App::main()->historyPeerChanged().notify(_peer, true); + _controller->historyPeerChanged().notify(_peer, true); update(); } @@ -4663,7 +4668,8 @@ bool HistoryWidget::canWriteMessage() const { void HistoryWidget::updateControlsVisibility() { if (!_a_show.animating()) { - _topShadow->setVisible(_peer ? true : false); + _topShadow->setVisible(_peer != nullptr); + _topBar->setVisible(_peer != nullptr); } updateHistoryDownVisibility(); if (!_history || _a_show.animating()) { @@ -5584,12 +5590,13 @@ void HistoryWidget::showAnimated(Window::SlideDirection direction, const Window: _cacheUnder = params.oldContentCache; show(); - _topShadow->setVisible(params.withTopBarShadow ? false : true); + _topBar->showAll(); historyDownAnimationFinish(); + _topShadow->setVisible(params.withTopBarShadow ? false : true); _cacheOver = App::main()->grabForShowAnimation(params); - App::main()->topBar()->startAnim(); _topShadow->setVisible(params.withTopBarShadow ? true : false); + _topBar->hide(); _scroll->hide(); _kbScroll->hide(); _reportSpamPanel->hide(); @@ -5617,26 +5624,30 @@ void HistoryWidget::showAnimated(Window::SlideDirection direction, const Window: std::swap(_cacheUnder, _cacheOver); } _a_show.start([this] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition()); - - App::main()->topBar()->update(); + if (_history) { + _backAnimationButton.create(this); + _backAnimationButton->setClickedCallback([this] { topBarClick(); }); + _backAnimationButton->setGeometry(_topBar->geometry()); + _backAnimationButton->show(); + } activate(); } void HistoryWidget::animationCallback() { update(); - App::main()->topBar()->update(); if (!_a_show.animating()) { - _topShadow->setVisible(_peer ? true : false); + _topShadow->setVisible(_peer != nullptr); + _topBar->setVisible(_peer != nullptr); historyDownAnimationFinish(); - _cacheUnder = _cacheOver = QPixmap(); - App::main()->topBar()->stopAnim(); doneShow(); } } void HistoryWidget::doneShow() { + _topBar->animationFinished(); + _backAnimationButton.destroy(); updateReportSpamStatus(); updateBotKeyboard(); updateControlsVisibility(); @@ -5655,7 +5666,8 @@ void HistoryWidget::doneShow() { void HistoryWidget::finishAnimation() { if (!_a_show.animating()) return; _a_show.finish(); - _topShadow->setVisible(_peer ? true : false); + _topShadow->setVisible(_peer != nullptr); + _topBar->setVisible(_peer != nullptr); historyDownAnimationFinish(); } @@ -5751,7 +5763,7 @@ void HistoryWidget::mouseMoveEvent(QMouseEvent *e) { void HistoryWidget::updateOverStates(QPoint pos) { auto inField = pos.y() >= (_scroll->y() + _scroll->height()) && pos.y() < height() && pos.x() >= 0 && pos.x() < width(); auto inReplyEdit = QRect(st::historyReplySkip, _field->y() - st::historySendPadding - st::historyReplyHeight, width() - st::historyReplySkip - _fieldBarCancel->width(), st::historyReplyHeight).contains(pos) && (_editMsgId || replyToId()); - auto inPinnedMsg = QRect(0, 0, width(), st::historyReplyHeight).contains(pos) && _pinnedBar; + auto inPinnedMsg = QRect(0, _topBar->bottomNoMargins(), width(), st::historyReplyHeight).contains(pos) && _pinnedBar; auto inClickable = inReplyEdit || inPinnedMsg; if (inField != _inField && _recording) { _inField = inField; @@ -6318,25 +6330,6 @@ void HistoryWidget::selectMessage() { } bool HistoryWidget::paintTopBar(Painter &p, int decreaseWidth, TimeMs ms) { - if (_a_show.animating()) { - auto progress = _a_show.current(1.); - auto retina = cIntRetinaFactor(); - auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft); - auto coordUnder = fromLeft ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress); - auto coordOver = fromLeft ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress); - auto shadow = fromLeft ? (1. - progress) : progress; - if (coordOver > 0) { - p.drawPixmap(QRect(0, 0, coordOver, st::topBarHeight), _cacheUnder, QRect(-coordUnder * retina, 0, coordOver * retina, st::topBarHeight * retina)); - p.setOpacity(shadow); - p.fillRect(0, 0, coordOver, st::topBarHeight, st::slideFadeOutBg); - p.setOpacity(1); - } - p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, st::topBarHeight), _cacheOver, QRect(0, 0, _cacheOver.width(), st::topBarHeight * retina)); - p.setOpacity(shadow); - st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), st::topBarHeight)); - return false; - } - if (!_history) return false; auto increaseLeft = (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) ? (st::topBarArrowPadding.left() - st::topBarArrowPadding.right()) : 0; @@ -6466,8 +6459,8 @@ void HistoryWidget::updateOnlineDisplay() { _titlePeerTextOnline = titlePeerTextOnline; _titlePeerTextWidth = st::dialogsTextFont->width(_titlePeerText); if (App::main()) { - App::main()->topBar()->updateMembersShowArea(); - App::main()->topBar()->update(); + _topBar->updateMembersShowArea(); + _topBar->update(); } } updateOnlineDisplayTimer(); @@ -7182,21 +7175,20 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) { } void HistoryWidget::updateControlsGeometry() { + _topBar->setGeometryToLeft(0, 0, width(), st::topBarHeight); _reportSpamPanel->resize(width(), _reportSpamPanel->height()); moveFieldControls(); + auto scrollAreaTop = _topBar->bottomNoMargins(); if (_pinnedBar) { - if (_scroll->y() != st::historyReplyHeight) { - _scroll->move(0, st::historyReplyHeight); - _reportSpamPanel->move(0, st::historyReplyHeight); - _fieldAutocomplete->setBoundings(_scroll->geometry()); - } - _pinnedBar->cancel->move(width() - _pinnedBar->cancel->width(), 0); - _pinnedBar->shadow->setGeometry(0, st::historyReplyHeight, width(), st::lineWidth); - } else if (_scroll->y() != 0) { - _scroll->move(0, 0); - _reportSpamPanel->move(0, 0); + _pinnedBar->cancel->move(width() - _pinnedBar->cancel->width(), scrollAreaTop); + scrollAreaTop += st::historyReplyHeight; + _pinnedBar->shadow->setGeometry(0, scrollAreaTop, width(), st::lineWidth); + } + if (_scroll->y() != scrollAreaTop) { + _scroll->move(0, scrollAreaTop); + _reportSpamPanel->move(0, scrollAreaTop); _fieldAutocomplete->setBoundings(_scroll->geometry()); } @@ -7230,7 +7222,7 @@ void HistoryWidget::updateControlsGeometry() { } _topShadow->resize(width() - ((!Adaptive::OneColumn() && !_inGrab) ? st::lineWidth : 0), st::lineWidth); - _topShadow->moveToLeft((!Adaptive::OneColumn() && !_inGrab) ? st::lineWidth : 0, 0); + _topShadow->moveToLeft((!Adaptive::OneColumn() && !_inGrab) ? st::lineWidth : 0, _topBar->bottomNoMargins()); } void HistoryWidget::itemRemoved(HistoryItem *item) { @@ -7276,7 +7268,7 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh return; // scrollTopMax etc are not working after recountHeight() } - int newScrollHeight = height(); + int newScrollHeight = height() - _topBar->height(); if (isBlocked() || isBotStart() || isJoinChannel() || isMuteUnmute()) { newScrollHeight -= _unblock->height(); } else { @@ -8597,14 +8589,14 @@ void HistoryWidget::fillSelectedItems(SelectedItemSet &sel, bool forDelete) { void HistoryWidget::updateTopBarSelection() { if (!_list) { - App::main()->topBar()->showSelected(0); + _topBar->showSelected(0); return; } int32 selectedForForward, selectedForDelete; _list->getSelectionState(selectedForForward, selectedForDelete); _selCount = selectedForForward ? selectedForForward : selectedForDelete; - App::main()->topBar()->showSelected(_selCount > 0 ? _selCount : 0, (selectedForDelete == selectedForForward)); + _topBar->showSelected(_selCount > 0 ? _selCount : 0, (selectedForDelete == selectedForForward)); updateControlsVisibility(); updateListSize(); if (!Ui::isLayerShown() && !App::passcoded()) { @@ -8614,7 +8606,7 @@ void HistoryWidget::updateTopBarSelection() { _field->setFocus(); } } - App::main()->topBar()->update(); + _topBar->update(); update(); } @@ -8843,14 +8835,16 @@ void HistoryWidget::drawRecording(Painter &p, float64 recordActive) { } void HistoryWidget::drawPinnedBar(Painter &p) { - t_assert(_pinnedBar != nullptr); + Expects(_pinnedBar != nullptr); + auto top = _topBar->bottomNoMargins(); Text *from = 0, *text = 0; bool serviceColor = false, hasForward = readyToForward(); ImagePtr preview; - p.fillRect(0, 0, width(), st::historyReplyHeight, st::historyPinnedBg); + p.fillRect(0, top, width(), st::historyReplyHeight, st::historyPinnedBg); - QRect rbar(rtlrect(st::msgReplyBarSkip + st::msgReplyBarPos.x(), st::msgReplyPadding.top() + st::msgReplyBarPos.y(), st::msgReplyBarSize.width(), st::msgReplyBarSize.height(), width())); + top += st::msgReplyPadding.top(); + QRect rbar(rtlrect(st::msgReplyBarSkip + st::msgReplyBarPos.x(), top + st::msgReplyBarPos.y(), st::msgReplyBarSize.width(), st::msgReplyBarSize.height(), width())); p.fillRect(rbar, st::msgInReplyBarColor); int32 left = st::msgReplyBarSkip + st::msgReplyBarSkip; @@ -8858,21 +8852,21 @@ void HistoryWidget::drawPinnedBar(Painter &p) { if (_pinnedBar->msg->getMedia() && _pinnedBar->msg->getMedia()->hasReplyPreview()) { ImagePtr replyPreview = _pinnedBar->msg->getMedia()->replyPreview(); if (!replyPreview->isNull()) { - QRect to(left, st::msgReplyPadding.top(), st::msgReplyBarSize.height(), st::msgReplyBarSize.height()); + QRect to(left, top, st::msgReplyBarSize.height(), st::msgReplyBarSize.height()); p.drawPixmap(to.x(), to.y(), replyPreview->pixSingle(replyPreview->width() / cIntRetinaFactor(), replyPreview->height() / cIntRetinaFactor(), to.width(), to.height(), ImageRoundRadius::Small)); } left += st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x(); } p.setPen(st::historyReplyNameFg); p.setFont(st::msgServiceNameFont); - p.drawText(left, st::msgReplyPadding.top() + st::msgServiceNameFont->ascent, lang(lng_pinned_message)); + p.drawText(left, top + st::msgServiceNameFont->ascent, lang(lng_pinned_message)); p.setPen(((_pinnedBar->msg->toHistoryMessage() && _pinnedBar->msg->toHistoryMessage()->emptyText()) || _pinnedBar->msg->serviceMsg()) ? st::historyComposeAreaFgService : st::historyComposeAreaFg); - _pinnedBar->text.drawElided(p, left, st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right()); + _pinnedBar->text.drawElided(p, left, top + st::msgServiceNameFont->height, width() - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right()); } else { p.setFont(st::msgDateFont); p.setPen(st::historyComposeAreaFgService); - p.drawText(left, st::msgReplyPadding.top() + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(lang(lng_profile_loading), width() - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right())); + p.drawText(left, top + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(lang(lng_profile_loading), width() - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right())); } } @@ -8889,32 +8883,31 @@ void HistoryWidget::paintEvent(QPaintEvent *e) { if (r != rect()) { p.setClipRect(r); } - bool hasTopBar = !App::main()->topBar()->isHidden(); auto ms = getms(); _historyDownShown.step(ms); auto progress = _a_show.current(ms, 1.); if (_a_show.animating()) { auto retina = cIntRetinaFactor(); - auto inCacheTop = hasTopBar ? st::topBarHeight : 0; auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft); auto coordUnder = fromLeft ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress); auto coordOver = fromLeft ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress); auto shadow = fromLeft ? (1. - progress) : progress; if (coordOver > 0) { - p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * retina, inCacheTop * retina, coordOver * retina, height() * retina)); + p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * retina, 0, coordOver * retina, height() * retina)); p.setOpacity(shadow); p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg); p.setOpacity(1); } - p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, height()), _cacheOver, QRect(0, inCacheTop * retina, _cacheOver.width(), height() * retina)); + p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, height()), _cacheOver, QRect(0, 0, _cacheOver.width(), height() * retina)); p.setOpacity(shadow); st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height())); return; } QRect fill(0, 0, width(), App::main()->height()); - int fromy = App::main()->backgroundFromY(), x = 0, y = 0; + auto fromy = App::main()->backgroundFromY(); + auto x = 0, y = 0; QPixmap cached = App::main()->cachedBackground(fill, x, y); if (cached.isNull()) { if (Window::Theme::Background()->tile()) { diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 3d9fb26b08..c9aaecafe0 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -37,6 +37,7 @@ class Result; } // namespace InlineBots namespace Ui { +class AbstractButton; class InnerDropdown; class DropdownMenu; class PlainShadow; @@ -50,6 +51,11 @@ class LinkButton; class RoundButton; } // namespace Ui +namespace Window { +class Controller; +class TopBarWidget; +} // namespace Window + class DragArea; class EmojiPan; class SilentToggle; @@ -534,7 +540,7 @@ class HistoryWidget : public TWidget, public RPCSender, private base::Subscriber Q_OBJECT public: - HistoryWidget(QWidget *parent); + HistoryWidget(QWidget *parent, gsl::not_null controller); void start(); @@ -554,7 +560,6 @@ public: bool paintTopBar(Painter &p, int decreaseWidth, TimeMs ms); QRect getMembersShowAreaGeometry() const; void setMembersShowAreaActive(bool active); - void topBarClick(); void loadMessages(); void loadMessagesDown(); @@ -843,6 +848,8 @@ private slots: void updateField(); private: + void topBarClick(); + void animationCallback(); void updateOverStates(QPoint pos); void recordStartCallback(); @@ -895,6 +902,8 @@ private: void hideSelectorControlsAnimated(); int countMembersDropdownHeightMax() const; + gsl::not_null _controller; + MsgId _replyToId = 0; Text _replyToName; int _replyToNameVersion = 0; @@ -1075,6 +1084,8 @@ private: MsgId _activeAnimMsgId = 0; + object_ptr _backAnimationButton = { nullptr }; + object_ptr _topBar; object_ptr _scroll; QPointer _list; History *_migrated = nullptr; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 349c1573a1..3ad48209f4 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -65,6 +65,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "boxes/calendarbox.h" #include "auth_session.h" #include "window/notifications_manager.h" +#include "window/window_controller.h" StackItemSection::StackItemSection(std::unique_ptr &&memento) : StackItem(nullptr) , _memento(std::move(memento)) { @@ -73,16 +74,15 @@ StackItemSection::StackItemSection(std::unique_ptr &&mem StackItemSection::~StackItemSection() { } -MainWidget::MainWidget(QWidget *parent) : TWidget(parent) +MainWidget::MainWidget(QWidget *parent, std::unique_ptr controller) : TWidget(parent) +, _controller(std::move(controller)) , _dialogsWidth(st::dialogsWidthMin) , _sideShadow(this, st::shadowFg) , _sideResizeArea(this) -, _dialogs(this) -, _history(this) -, _topBar(this) +, _dialogs(this, _controller.get()) +, _history(this, _controller.get()) , _playerPlaylist(this, Media::Player::Panel::Layout::OnlyPlaylist) , _playerPanel(this, Media::Player::Panel::Layout::Full) -, _mediaType(this, st::defaultDropdownMenu) , _api(new ApiWrap(this)) { Messenger::Instance().mtp()->setUpdatesHandler(rpcDone(&MainWidget::updateReceived)); Messenger::Instance().mtp()->setGlobalFailHandler(rpcFail(&MainWidget::updateFail)); @@ -104,7 +104,6 @@ MainWidget::MainWidget(QWidget *parent) : TWidget(parent) connect(&_failDifferenceTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeAfterFail())); connect(_api.get(), SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*))); connect(this, SIGNAL(peerUpdated(PeerData*)), _history, SLOT(peerUpdated(PeerData*))); - connect(_topBar, SIGNAL(clicked()), this, SLOT(onTopBarClick())); connect(_history, SIGNAL(historyShown(History*,MsgId)), this, SLOT(onHistoryShown(History*,MsgId))); connect(&updateNotifySettingTimer, SIGNAL(timeout()), this, SLOT(onUpdateNotifySettings())); subscribe(Media::Player::Updated(), [this](const AudioMsgId &audioId) { @@ -174,13 +173,9 @@ MainWidget::MainWidget(QWidget *parent) : TWidget(parent) } else { _history->show(); } - _topBar->hide(); orderWidgets(); - _mediaType->hide(); - _mediaType->setOrigin(Ui::PanelAnimation::Origin::TopRight); - _topBar->mediaTypeButton()->installEventFilter(_mediaType); _sideResizeArea->installEventFilter(this); _api->init(); @@ -1407,37 +1402,6 @@ void MainWidget::mediaOverviewUpdated(const Notify::PeerUpdate &update) { auto peer = update.peer; if (_overview && (_overview->peer() == peer || _overview->peer()->migrateFrom() == peer)) { _overview->mediaOverviewUpdated(update); - - int32 mask = 0; - History *h = peer ? App::historyLoaded((peer->migrateTo() ? peer->migrateTo() : peer)->id) : 0; - History *m = (peer && peer->migrateFrom()) ? App::historyLoaded(peer->migrateFrom()->id) : 0; - if (h) { - for (int32 i = 0; i < OverviewCount; ++i) { - if (!h->overview[i].isEmpty() || h->overviewCount(i) > 0 || i == _overview->type()) { - mask |= (1 << i); - } else if (m && (!m->overview[i].isEmpty() || m->overviewCount(i) > 0)) { - mask |= (1 << i); - } - } - } - if (mask != _mediaTypeMask) { - _mediaType->clearActions(); - for (int32 i = 0; i < OverviewCount; ++i) { - if (mask & (1 << i)) { - switch (i) { - case OverviewPhotos: _mediaType->addAction(lang(lng_media_type_photos), this, SLOT(onPhotosSelect())); break; - case OverviewVideos: _mediaType->addAction(lang(lng_media_type_videos), this, SLOT(onVideosSelect())); break; - case OverviewMusicFiles: _mediaType->addAction(lang(lng_media_type_songs), this, SLOT(onSongsSelect())); break; - case OverviewFiles: _mediaType->addAction(lang(lng_media_type_files), this, SLOT(onDocumentsSelect())); break; - case OverviewVoiceFiles: _mediaType->addAction(lang(lng_media_type_audios), this, SLOT(onAudiosSelect())); break; - case OverviewLinks: _mediaType->addAction(lang(lng_media_type_links), this, SLOT(onLinksSelect())); break; - } - } - } - _mediaTypeMask = mask; - _mediaType->move(width() - _mediaType->width(), st::topBarHeight); - _overview->updateTopBarSelection(); - } } } @@ -2298,7 +2262,6 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, Ui::Show } } if (onlyDialogs) { - _topBar->hide(); _history->hide(); if (!_a_show.animating()) { if (animationParams) { @@ -2310,7 +2273,6 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, Ui::Show } } else { if (noPeer) { - _topBar->hide(); updateControlsGeometry(); } else if (wasActivePeer != activePeer()) { if (activePeer()->isChannel()) { @@ -2340,7 +2302,6 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, Ui::Show } _dialogs->update(); } - topBar()->showAll(); } PeerData *MainWidget::ui_getPeerForMouseAction() { @@ -2385,15 +2346,8 @@ PeerData *MainWidget::overviewPeer() { return _overview ? _overview->peer() : 0; } -bool MainWidget::mediaTypeSwitch() { - if (!_overview) return false; - - for (int32 i = 0; i < OverviewCount; ++i) { - if (!(_mediaTypeMask & ~(1 << i))) { - return false; - } - } - return true; +bool MainWidget::showMediaTypeSwitch() const { + return _overview ? _overview->showMediaTypeSwitch() : false; } void MainWidget::saveSectionInStack() { @@ -2452,9 +2406,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool _wideSection->deleteLater(); _wideSection = nullptr; } - _overview.create(this, peer, type); - _mediaTypeMask = 0; - _topBar->show(); + _overview.create(this, _controller.get(), peer, type); updateControlsGeometry(); // Send a fake update. @@ -2609,7 +2561,6 @@ void MainWidget::showNewWideSection(const Window::SectionMemento *memento, bool _wideSection = nullptr; } _wideSection = std::move(newWideSection); - _topBar->hide(); updateControlsGeometry(); _history->finishAnimation(); _history->showHistory(0, 0); @@ -2672,7 +2623,6 @@ void MainWidget::showBackFromStack() { } void MainWidget::orderWidgets() { - _topBar->raise(); _dialogs->raise(); if (_player) { _player->raise(); @@ -2680,7 +2630,6 @@ void MainWidget::orderWidgets() { if (_playerVolume) { _playerVolume->raise(); } - _mediaType->raise(); _sideShadow->raise(); _sideResizeArea->raise(); _playerPlaylist->raise(); @@ -2696,7 +2645,6 @@ QRect MainWidget::historyRect() const { } QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) { - _topBar->stopAnim(); QPixmap result; if (_player) { _player->hideShadow(); @@ -2954,8 +2902,6 @@ void MainWidget::hideAll() { _overview->hide(); } _sideShadow->hide(); - _topBar->hide(); - _mediaType->hide(); if (_player) { _player->hide(); _playerHeight = 0; @@ -2986,7 +2932,6 @@ void MainWidget::showAll() { _history->hide(); if (_overview) _overview->hide(); if (_wideSection) _wideSection->hide(); - _topBar->hide(); } else if (_overview) { _overview->show(); } else if (_wideSection) { @@ -3000,10 +2945,8 @@ void MainWidget::showAll() { } if (!selectingPeer()) { if (_wideSection) { - _topBar->hide(); _dialogs->hide(); } else if (isSectionShown()) { - _topBar->show(); _dialogs->hide(); } } @@ -3028,11 +2971,6 @@ void MainWidget::showAll() { _history->show(); _history->updateControlsGeometry(); } - if (_wideSection) { - _topBar->hide(); - } else if (isSectionShown()) { - _topBar->show(); - } } if (_player) { _player->show(); @@ -3049,7 +2987,6 @@ void MainWidget::resizeEvent(QResizeEvent *e) { void MainWidget::updateControlsGeometry() { updateWindowAdaptiveLayout(); - auto topBarHeight = _topBar->isHidden() ? 0 : st::topBarHeight; if (!Adaptive::SmallColumn()) { _a_dialogsWidth.finish(); } @@ -3063,8 +3000,7 @@ void MainWidget::updateControlsGeometry() { _player->moveToLeft(0, 0); } _dialogs->setGeometry(0, _playerHeight, dialogsWidth, height() - _playerHeight); - _topBar->setGeometry(0, _playerHeight, dialogsWidth, st::topBarHeight); - _history->setGeometry(0, _playerHeight + topBarHeight, dialogsWidth, height() - _playerHeight - topBarHeight); + _history->setGeometry(0, _playerHeight, dialogsWidth, height() - _playerHeight); if (_hider) _hider->setGeometry(0, 0, dialogsWidth, height()); } else { accumulate_min(dialogsWidth, width() - st::windowMinWidth); @@ -3076,8 +3012,7 @@ void MainWidget::updateControlsGeometry() { _player->resizeToWidth(sectionWidth); _player->moveToLeft(dialogsWidth, 0); } - _topBar->setGeometryToLeft(dialogsWidth, _playerHeight, sectionWidth, st::topBarHeight); - _history->setGeometryToLeft(dialogsWidth, _playerHeight + topBarHeight, sectionWidth, height() - _playerHeight - topBarHeight); + _history->setGeometryToLeft(dialogsWidth, _playerHeight, sectionWidth, height() - _playerHeight); if (_hider) { _hider->setGeometryToLeft(dialogsWidth, 0, sectionWidth, height()); } @@ -3093,9 +3028,8 @@ void MainWidget::updateControlsGeometry() { return true; }; _sideResizeArea->setVisible(isSideResizeAreaVisible()); - _mediaType->moveToLeft(width() - _mediaType->width(), _playerHeight + st::topBarHeight); if (_wideSection) { - QRect wideSectionGeometry(_history->x(), _playerHeight, _history->width(), height() - _playerHeight); + auto wideSectionGeometry = QRect(_history->x(), _playerHeight, _history->width(), height() - _playerHeight); _wideSection->setGeometryWithTopMoved(wideSectionGeometry, _contentScrollAddToY); } if (_overview) _overview->setGeometry(_history->geometry()); @@ -3273,63 +3207,12 @@ void MainWidget::setMembersShowAreaActive(bool active) { } } -void MainWidget::onPhotosSelect() { - if (_overview) _overview->switchType(OverviewPhotos); - _mediaType->hideAnimated(); -} - -void MainWidget::onVideosSelect() { - if (_overview) _overview->switchType(OverviewVideos); - _mediaType->hideAnimated(); -} - -void MainWidget::onSongsSelect() { - if (_overview) _overview->switchType(OverviewMusicFiles); - _mediaType->hideAnimated(); -} - -void MainWidget::onDocumentsSelect() { - if (_overview) _overview->switchType(OverviewFiles); - _mediaType->hideAnimated(); -} - -void MainWidget::onAudiosSelect() { - if (_overview) _overview->switchType(OverviewVoiceFiles); - _mediaType->hideAnimated(); -} - -void MainWidget::onLinksSelect() { - if (_overview) _overview->switchType(OverviewLinks); - _mediaType->hideAnimated(); -} - -Window::TopBarWidget *MainWidget::topBar() { - return _topBar; -} - int MainWidget::backgroundFromY() const { - return (_topBar->isHidden() ? 0 : (-st::topBarHeight)) - _playerHeight; -} - -void MainWidget::onTopBarClick() { - if (_overview) { - _overview->topBarClick(); - } else if (!_wideSection) { - _history->topBarClick(); - } + return -_playerHeight; } void MainWidget::onHistoryShown(History *history, MsgId atMsgId) { - if ((!Adaptive::OneColumn() || !selectingPeer()) && (_overview || history)) { - _topBar->show(); - } else { - _topBar->hide(); - } updateControlsGeometry(); - if (_a_show.animating()) { - _topBar->hide(); - } - dlgUpdated(history ? history->peer : nullptr, atMsgId); } @@ -3988,11 +3871,11 @@ void MainWidget::onSelfParticipantUpdated(ChannelData *channel) { } bool MainWidget::contentOverlapped(const QRect &globalRect) { - return (_history->contentOverlapped(globalRect) || - _playerPanel->overlaps(globalRect) || - _playerPlaylist->overlaps(globalRect) || - (_playerVolume && _playerVolume->overlaps(globalRect)) || - _mediaType->overlaps(globalRect)); + return (_history->contentOverlapped(globalRect) + || (_overview && _overview->contentOverlapped(globalRect)) + || _playerPanel->overlaps(globalRect) + || _playerPlaylist->overlaps(globalRect) + || (_playerVolume && _playerVolume->overlaps(globalRect))); } void MainWidget::usernameResolveDone(QPair msgIdAndStartToken, const MTPcontacts_ResolvedPeer &result) { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 3ad2d5e724..d71c9daef1 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -46,6 +46,7 @@ class DropdownMenu; } // namespace Ui namespace Window { +class Controller; class PlayerWrapWidget; class TopBarWidget; class SectionMemento; @@ -142,7 +143,7 @@ class MainWidget : public TWidget, public RPCSender, private base::Subscriber { Q_OBJECT public: - MainWidget(QWidget *parent); + MainWidget(QWidget *parent, std::unique_ptr controller); bool needBackButton(); @@ -150,8 +151,6 @@ public: bool paintTopBar(Painter &, int decreaseWidth, TimeMs ms); QRect getMembersShowAreaGeometry() const; void setMembersShowAreaActive(bool active); - Window::TopBarWidget *topBar(); - int backgroundFromY() const; int contentScrollAddToY() const; @@ -204,8 +203,9 @@ public: PeerData *activePeer(); MsgId activeMsgId(); + int backgroundFromY() const; PeerData *overviewPeer(); - bool mediaTypeSwitch(); + bool showMediaTypeSwitch() const; void showWideSection(const Window::SectionMemento &memento); void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1); bool stackIsEmpty() const; @@ -374,13 +374,6 @@ public: bool contentOverlapped(const QRect &globalRect); - base::Observable &searchInPeerChanged() { - return _searchInPeerChanged; - } - base::Observable &historyPeerChanged() { - return _historyPeerChanged; - } - void rpcClear() override; bool isItemVisible(HistoryItem *item); @@ -444,20 +437,12 @@ public slots: void checkIdleFinish(); void updateOnlineDisplay(); - void onTopBarClick(); void onHistoryShown(History *history, MsgId atMsgId); void searchInPeer(PeerData *peer); void onUpdateNotifySettings(); - void onPhotosSelect(); - void onVideosSelect(); - void onSongsSelect(); - void onDocumentsSelect(); - void onAudiosSelect(); - void onLinksSelect(); - void onCacheBackground(); void onInviteImport(); @@ -522,6 +507,7 @@ private: void saveSectionInStack(); + std::unique_ptr _controller; bool _started = false; SelectedItemSet _toForward; @@ -584,9 +570,6 @@ private: void clearCachedBackground(); - base::Observable _searchInPeerChanged; - base::Observable _historyPeerChanged; - Animation _a_show; bool _showBack = false; QPixmap _cacheUnder, _cacheOver; @@ -600,7 +583,6 @@ private: object_ptr _history; object_ptr _wideSection = { nullptr }; object_ptr _overview = { nullptr }; - object_ptr _topBar; object_ptr _player = { nullptr }; object_ptr _playerVolume = { nullptr }; @@ -617,9 +599,6 @@ private: int _playerHeight = 0; int _contentScrollAddToY = 0; - object_ptr _mediaType; - int32 _mediaTypeMask = 0; - int32 updDate = 0; int32 updQts = -1; int32 updSeq = 0; diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index abd21c81e9..1386797bea 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -52,6 +52,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "window/window_main_menu.h" #include "core/task_queue.h" #include "auth_session.h" +#include "window/window_controller.h" ConnectingWidget::ConnectingWidget(QWidget *parent, const QString &text, const QString &reconnect) : TWidget(parent) , _reconnect(this, QString()) { @@ -350,7 +351,7 @@ void MainWindow::setupMain(const MTPUser *self) { t_assert(AuthSession::Exists()); - _main.create(bodyWidget()); + _main.create(bodyWidget(), std::make_unique(this)); _main->show(); updateControlsGeometry(); diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index f57bc75334..5dea00d22f 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -44,6 +44,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "observer_peer.h" #include "auth_session.h" #include "storage/file_download.h" +#include "ui/widgets/dropdown_menu.h" // flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html @@ -1895,13 +1896,23 @@ OverviewInner::~OverviewInner() { clear(); } -OverviewWidget::OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewType type) : TWidget(parent) +OverviewWidget::OverviewWidget(QWidget *parent, gsl::not_null controller, PeerData *peer, MediaOverviewType type) : TWidget(parent) +, _controller(controller) +, _topBar(this, _controller) , _scroll(this, st::settingsScroll, false) +, _mediaType(this, st::defaultDropdownMenu) , _topShadow(this, st::shadowFg) { _inner = _scroll->setOwnedWidget(object_ptr(this, _scroll, peer, type)); _scroll->move(0, 0); _inner->move(0, 0); + connect(_topBar, &Window::TopBarWidget::clicked, this, [this] { topBarClick(); }); + + _mediaType->hide(); + _mediaType->setOrigin(Ui::PanelAnimation::Origin::TopRight); + _topBar->mediaTypeButton()->installEventFilter(_mediaType); + + _topBar->show(); _scroll->show(); connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); @@ -1934,11 +1945,14 @@ void OverviewWidget::onScroll() { } void OverviewWidget::resizeEvent(QResizeEvent *e) { + _topBar->setGeometryToLeft(0, 0, width(), st::topBarHeight); + auto scrollAreaTop = _topBar->bottomNoMargins(); + _noDropResizeIndex = true; - int32 st = _scroll->scrollTop(); - _scroll->resize(size()); - int32 newScrollTop = _inner->resizeToWidth(width(), st, height()); - if (int32 addToY = App::main() ? App::main()->contentScrollAddToY() : 0) { + auto st = _scroll->scrollTop(); + _scroll->setGeometryToLeft(0, scrollAreaTop, width(), height() - scrollAreaTop); + auto newScrollTop = _inner->resizeToWidth(width(), st, height() - _topBar->height()); + if (auto addToY = App::main() ? App::main()->contentScrollAddToY() : 0) { newScrollTop += addToY; } if (newScrollTop != _scroll->scrollTop()) { @@ -1947,7 +1961,9 @@ void OverviewWidget::resizeEvent(QResizeEvent *e) { _noDropResizeIndex = false; _topShadow->resize(width() - ((!Adaptive::OneColumn() && !_inGrab) ? st::lineWidth : 0), st::lineWidth); - _topShadow->moveToLeft((!Adaptive::OneColumn() && !_inGrab) ? st::lineWidth : 0, 0); + _topShadow->moveToLeft((!Adaptive::OneColumn() && !_inGrab) ? st::lineWidth : 0, _topBar->bottomNoMargins()); + + _mediaType->moveToRight(0, scrollAreaTop); } void OverviewWidget::paintEvent(QPaintEvent *e) { @@ -1957,18 +1973,17 @@ void OverviewWidget::paintEvent(QPaintEvent *e) { auto progress = _a_show.current(getms(), 1.); if (_a_show.animating()) { auto retina = cIntRetinaFactor(); - auto inCacheTop = st::topBarHeight; auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft); auto coordUnder = fromLeft ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress); auto coordOver = fromLeft ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress); auto shadow = fromLeft ? (1. - progress) : progress; if (coordOver > 0) { - p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * retina, inCacheTop * retina, coordOver * retina, height() * retina)); + p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * retina, 0, coordOver * retina, height() * retina)); p.setOpacity(shadow); p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg); p.setOpacity(1); } - p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, height()), _cacheOver, QRect(0, inCacheTop * retina, _cacheOver.width(), height() * retina)); + p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, height()), _cacheOver, QRect(0, 0, _cacheOver.width(), height() * retina)); p.setOpacity(shadow); st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height())); return; @@ -1994,24 +2009,6 @@ void OverviewWidget::scrollReset() { } bool OverviewWidget::paintTopBar(Painter &p, int decreaseWidth) { - if (_a_show.animating()) { - auto progress = _a_show.current(1.); - auto retina = cIntRetinaFactor(); - auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft); - auto coordUnder = fromLeft ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress); - auto coordOver = fromLeft ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress); - auto shadow = fromLeft ? (1. - progress) : progress; - if (coordOver > 0) { - p.drawPixmap(QRect(0, 0, coordOver, st::topBarHeight), _cacheUnder, QRect(-coordUnder * retina, 0, coordOver * retina, st::topBarHeight * retina)); - p.setOpacity(shadow); - p.fillRect(0, 0, coordOver, st::topBarHeight, st::slideFadeOutBg); - p.setOpacity(1); - } - p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, st::topBarHeight), _cacheOver, QRect(0, 0, _cacheOver.width(), st::topBarHeight * retina)); - p.setOpacity(shadow); - st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), st::topBarHeight)); - return false; - } st::topBarBack.paint(p, (st::topBarArrowPadding.left() - st::topBarBack.width()) / 2, (st::topBarHeight - st::topBarBack.height()) / 2, width()); p.setFont(st::defaultLightButton.font); p.setPen(st::defaultLightButton.textFg); @@ -2053,7 +2050,7 @@ void OverviewWidget::switchType(MediaOverviewType type) { _header = _header.toUpper(); noSelectingScroll(); - App::main()->topBar()->showSelected(0); + _topBar->showSelected(0); updateTopBarSelection(); scrollReset(); @@ -2063,14 +2060,27 @@ void OverviewWidget::switchType(MediaOverviewType type) { activate(); } +bool OverviewWidget::showMediaTypeSwitch() const { + for (int32 i = 0; i < OverviewCount; ++i) { + if (!(_mediaTypeMask & ~(1 << i))) { + return false; + } + } + return true; +} + +bool OverviewWidget::contentOverlapped(const QRect &globalRect) { + return _mediaType->overlaps(globalRect); +} + void OverviewWidget::updateTopBarSelection() { int32 selectedForForward, selectedForDelete; _inner->getSelectionState(selectedForForward, selectedForDelete); _selCount = selectedForForward ? selectedForForward : selectedForDelete; _inner->setSelectMode(_selCount > 0); if (App::main()) { - App::main()->topBar()->showSelected(_selCount > 0 ? _selCount : 0, (selectedForDelete == selectedForForward)); - App::main()->topBar()->update(); + _topBar->showSelected(_selCount > 0 ? _selCount : 0, (selectedForDelete == selectedForForward)); + _topBar->update(); } if (App::wnd() && !Ui::isLayerShown()) { _inner->activate(); @@ -2122,11 +2132,12 @@ void OverviewWidget::showAnimated(Window::SlideDirection direction, const Window _cacheUnder = params.oldContentCache; show(); + _topBar->showAll(); _topShadow->setVisible(params.withTopBarShadow ? false : true); _cacheOver = App::main()->grabForShowAnimation(params); _topShadow->setVisible(params.withTopBarShadow ? true : false); - App::main()->topBar()->startAnim(); + _topBar->hide(); _scrollSetAfterShow = _scroll->scrollTop(); _scroll->hide(); @@ -2135,25 +2146,27 @@ void OverviewWidget::showAnimated(Window::SlideDirection direction, const Window } _a_show.start([this] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition()); - App::main()->topBar()->update(); + _backAnimationButton.create(this); + _backAnimationButton->setClickedCallback([this] { topBarClick(); }); + _backAnimationButton->setGeometry(_topBar->geometry()); + _backAnimationButton->show(); activate(); } void OverviewWidget::animationCallback() { update(); - App::main()->topBar()->update(); if (!_a_show.animating()) { _topShadow->show(); - _cacheUnder = _cacheOver = QPixmap(); - App::main()->topBar()->stopAnim(); - doneShow(); } } void OverviewWidget::doneShow() { + _topBar->animationFinished(); + _backAnimationButton.destroy(); + _topBar->show(); _scroll->show(); _scroll->scrollToY(_scrollSetAfterShow); activate(); @@ -2166,6 +2179,47 @@ void OverviewWidget::mediaOverviewUpdated(const Notify::PeerUpdate &update) { onScroll(); updateTopBarSelection(); } + int32 mask = 0; + History *h = update.peer ? App::historyLoaded(update.peer->migrateTo() ? update.peer->migrateTo() : update.peer) : nullptr; + History *m = (update.peer && update.peer->migrateFrom()) ? App::historyLoaded(update.peer->migrateFrom()->id) : 0; + if (h) { + for (int32 i = 0; i < OverviewCount; ++i) { + if (!h->overview[i].isEmpty() || h->overviewCount(i) > 0 || i == type()) { + mask |= (1 << i); + } else if (m && (!m->overview[i].isEmpty() || m->overviewCount(i) > 0)) { + mask |= (1 << i); + } + } + } + if (mask != _mediaTypeMask) { + auto typeLabel = [](MediaOverviewType type) -> QString { + switch (type) { + case OverviewPhotos: return lang(lng_media_type_photos); + case OverviewVideos: return lang(lng_media_type_videos); + case OverviewMusicFiles: return lang(lng_media_type_songs); + case OverviewFiles: return lang(lng_media_type_files); + case OverviewVoiceFiles: return lang(lng_media_type_audios); + case OverviewLinks: return lang(lng_media_type_links); + } + return QString(); + }; + _mediaType->clearActions(); + for (auto i = 0; i != OverviewCount; ++i) { + if (mask & (1 << i)) { + auto type = static_cast(i); + auto label = typeLabel(type); + if (!label.isEmpty()) { + _mediaType->addAction(label, [this, type] { + switchType(type); + _mediaType->hideAnimated(); + }); + } + } + } + _mediaTypeMask = mask; + _mediaType->move(width() - _mediaType->width(), st::topBarHeight); + updateTopBarSelection(); + } } void OverviewWidget::changingMsgId(HistoryItem *row, MsgId newId) { diff --git a/Telegram/SourceFiles/overviewwidget.h b/Telegram/SourceFiles/overviewwidget.h index ee9e299adf..20876fcc37 100644 --- a/Telegram/SourceFiles/overviewwidget.h +++ b/Telegram/SourceFiles/overviewwidget.h @@ -33,17 +33,24 @@ class Date; } // namespace Overview namespace Ui { +class AbstractButton; class PlainShadow; class PopupMenu; class IconButton; class FlatInput; class CrossButton; +class DropdownMenu; } // namespace Ui namespace Notify { struct PeerUpdate; } // namespace Notify +namespace Window { +class Controller; +class TopBarWidget; +} // namespace Window + class OverviewWidget; class OverviewInner : public TWidget, public Ui::AbstractTooltipShower, public RPCSender, private base::Subscriber { Q_OBJECT @@ -280,7 +287,7 @@ class OverviewWidget : public TWidget, public RPCSender { Q_OBJECT public: - OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewType type); + OverviewWidget(QWidget *parent, gsl::not_null controller, PeerData *peer, MediaOverviewType type); void clear(); @@ -288,13 +295,14 @@ public: void scrollReset(); bool paintTopBar(Painter &p, int decreaseWidth); - void topBarClick(); PeerData *peer() const; PeerData *migratePeer() const; MediaOverviewType type() const; void switchType(MediaOverviewType type); + bool showMediaTypeSwitch() const; void updateTopBarSelection(); + bool contentOverlapped(const QRect &globalRect); int32 lastWidth() const; int32 lastScrollTop() const; @@ -361,12 +369,20 @@ public slots: void onClearSelected(); private: + void topBarClick(); void animationCallback(); + gsl::not_null _controller; + + object_ptr _backAnimationButton = { nullptr }; + object_ptr _topBar; object_ptr _scroll; QPointer _inner; bool _noDropResizeIndex = false; + object_ptr _mediaType; + int32 _mediaTypeMask = 0; + QString _header; Animation _a_show; diff --git a/Telegram/SourceFiles/window/top_bar_widget.cpp b/Telegram/SourceFiles/window/top_bar_widget.cpp index 7e6ba28a46..310395a684 100644 --- a/Telegram/SourceFiles/window/top_bar_widget.cpp +++ b/Telegram/SourceFiles/window/top_bar_widget.cpp @@ -31,10 +31,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "ui/widgets/buttons.h" #include "ui/widgets/dropdown_menu.h" #include "dialogs/dialogs_layout.h" +#include "window/window_controller.h" namespace Window { -TopBarWidget::TopBarWidget(MainWidget *w) : TWidget(w) +TopBarWidget::TopBarWidget(QWidget *parent, gsl::not_null controller) : TWidget(parent) +, _controller(controller) , _clearSelection(this, lang(lng_selected_clear), st::topBarClearButton) , _forward(this, lang(lng_selected_forward), st::defaultActiveButton) , _delete(this, lang(lng_selected_delete), st::defaultActiveButton) @@ -51,12 +53,12 @@ TopBarWidget::TopBarWidget(MainWidget *w) : TWidget(w) _search->setClickedCallback([this] { onSearch(); }); _menuToggle->setClickedCallback([this] { showMenu(); }); - subscribe(w->searchInPeerChanged(), [this](PeerData *peer) { + subscribe(_controller->searchInPeerChanged(), [this](PeerData *peer) { _searchInPeer = peer; auto historyPeer = App::main() ? App::main()->historyPeer() : nullptr; _search->setForceRippled(historyPeer && historyPeer == _searchInPeer); }); - subscribe(w->historyPeerChanged(), [this](PeerData *peer) { + subscribe(_controller->historyPeerChanged(), [this](PeerData *peer) { _search->setForceRippled(peer && peer == _searchInPeer, Ui::IconButton::SetForceRippledWay::SkipAnimation); update(); }); @@ -143,11 +145,11 @@ bool TopBarWidget::eventFilter(QObject *obj, QEvent *e) { return true; case QEvent::Enter: - main()->setMembersShowAreaActive(true); + App::main()->setMembersShowAreaActive(true); break; case QEvent::Leave: - main()->setMembersShowAreaActive(false); + App::main()->setMembersShowAreaActive(false); break; } } @@ -178,7 +180,7 @@ void TopBarWidget::paintEvent(QPaintEvent *e) { if (!_search->isHidden()) { decreaseWidth += _search->width(); } - auto paintCounter = main()->paintTopBar(p, decreaseWidth, ms); + auto paintCounter = App::main()->paintTopBar(p, decreaseWidth, ms); p.restore(); if (paintCounter) { @@ -256,33 +258,12 @@ void TopBarWidget::updateControlsGeometry() { _search->moveToRight(_info->isHidden() ? _menuToggle->width() : _info->width(), otherButtonsTop); } -void TopBarWidget::startAnim() { - _info->hide(); - _clearSelection->hide(); - _delete->hide(); - _forward->hide(); - _mediaType->hide(); - _search->hide(); - _menuToggle->hide(); - _menu.destroy(); - if (_membersShowArea) { - _membersShowArea->hide(); - } - - _animating = true; -} - -void TopBarWidget::stopAnim() { - _animating = false; +void TopBarWidget::animationFinished() { updateMembersShowArea(); showAll(); } void TopBarWidget::showAll() { - if (_animating) { - updateControlsGeometry(); - return; - } auto historyPeer = App::main() ? App::main()->historyPeer() : nullptr; auto overviewPeer = App::main() ? App::main()->overviewPeer() : nullptr; @@ -290,7 +271,7 @@ void TopBarWidget::showAll() { _delete->setVisible(_canDelete); _forward->show(); - _mediaType->setVisible(App::main() ? App::main()->mediaTypeSwitch() : false); + _mediaType->setVisible(App::main() ? App::main()->showMediaTypeSwitch() : false); if (historyPeer && !overviewPeer) { if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) { _info->setPeer(historyPeer); @@ -330,7 +311,7 @@ void TopBarWidget::updateMembersShowArea() { }; if (!membersShowAreaNeeded()) { if (_membersShowArea) { - main()->setMembersShowAreaActive(false); + App::main()->setMembersShowAreaActive(false); _membersShowArea.destroy(); } return; @@ -397,8 +378,4 @@ Ui::RoundButton *TopBarWidget::mediaTypeButton() { return _mediaType; } -MainWidget *TopBarWidget::main() { - return static_cast(parentWidget()); -} - } // namespace Window diff --git a/Telegram/SourceFiles/window/top_bar_widget.h b/Telegram/SourceFiles/window/top_bar_widget.h index 0adbb8c5b8..b358537970 100644 --- a/Telegram/SourceFiles/window/top_bar_widget.h +++ b/Telegram/SourceFiles/window/top_bar_widget.h @@ -31,17 +31,17 @@ class DropdownMenu; namespace Window { +class Controller; + class TopBarWidget : public TWidget, private base::Subscriber { Q_OBJECT public: - TopBarWidget(MainWidget *w); + TopBarWidget(QWidget *parent, gsl::not_null controller); - void startAnim(); - void stopAnim(); void showAll(); void showSelected(int selectedCount, bool canDelete = false); - + void animationFinished(); void updateMembersShowArea(); Ui::RoundButton *mediaTypeButton(); @@ -71,14 +71,12 @@ private: void updateAdaptiveLayout(); int countSelectedButtonsTop(float64 selectedShown); - MainWidget *main(); + gsl::not_null _controller; PeerData *_searchInPeer = nullptr; int _selectedCount = 0; bool _canDelete = false; - bool _animating = false; - Animation _selectedShown; object_ptr _clearSelection; diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp new file mode 100644 index 0000000000..23282d8418 --- /dev/null +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -0,0 +1,22 @@ +/* +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 "window/window_controller.h" + diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h new file mode 100644 index 0000000000..f033054cb3 --- /dev/null +++ b/Telegram/SourceFiles/window/window_controller.h @@ -0,0 +1,50 @@ +/* +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 + +namespace Window { + +class Controller { +public: + Controller(MainWindow *window) : _window(window) { + } + + // This is needed for History TopBar updating when searchInPeer + // is changed in the DialogsWidget of the current window. + base::Observable &searchInPeerChanged() { + return _searchInPeerChanged; + } + + // 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. + base::Observable &historyPeerChanged() { + return _historyPeerChanged; + } + +private: + gsl::not_null _window; + base::Observable _searchInPeerChanged; + base::Observable _historyPeerChanged; + +}; + +} // namespace Window diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 01f08e354d..876cdcb688 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -426,6 +426,8 @@ <(src_loc)/ui/special_buttons.h <(src_loc)/ui/twidget.cpp <(src_loc)/ui/twidget.h +<(src_loc)/window/window_controller.cpp +<(src_loc)/window/window_controller.h <(src_loc)/window/main_window.cpp <(src_loc)/window/main_window.h <(src_loc)/window/notifications_manager.cpp @@ -439,12 +441,13 @@ <(src_loc)/window/section_memento.h <(src_loc)/window/section_widget.cpp <(src_loc)/window/section_widget.h -<(src_loc)/window/window_slide_animation.cpp -<(src_loc)/window/window_slide_animation.h <(src_loc)/window/top_bar_widget.cpp <(src_loc)/window/top_bar_widget.h <(src_loc)/window/window_main_menu.cpp <(src_loc)/window/window_main_menu.h +<(src_loc)/window/window_slide_animation.cpp +<(src_loc)/window/window_slide_animation.h +<(src_loc)/window/window_title.h <(src_loc)/window/themes/window_theme.cpp <(src_loc)/window/themes/window_theme.h <(src_loc)/window/themes/window_theme_editor.cpp @@ -455,7 +458,6 @@ <(src_loc)/window/themes/window_theme_preview.h <(src_loc)/window/themes/window_theme_warning.cpp <(src_loc)/window/themes/window_theme_warning.h -<(src_loc)/window/window_title.h <(src_loc)/apiwrap.cpp <(src_loc)/apiwrap.h <(src_loc)/app.cpp