From f56df0e1d9836c48209f5e5bd60f6d442078be7c Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 24 Apr 2019 14:15:10 +0400 Subject: [PATCH] Show folder using slide animation. --- .../dialogs/dialogs_inner_widget.cpp | 586 ++++++++---------- .../dialogs/dialogs_inner_widget.h | 131 ++-- .../SourceFiles/dialogs/dialogs_widget.cpp | 436 ++++++++----- Telegram/SourceFiles/dialogs/dialogs_widget.h | 122 ++-- Telegram/SourceFiles/mainwidget.h | 4 +- .../SourceFiles/ui/widgets/input_fields.cpp | 5 + .../SourceFiles/ui/widgets/input_fields.h | 2 + .../SourceFiles/window/window_controller.cpp | 28 + .../SourceFiles/window/window_controller.h | 7 +- 9 files changed, 720 insertions(+), 601 deletions(-) diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 05d28e27ec..c842690879 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_indexed_list.h" #include "dialogs/dialogs_layout.h" +#include "dialogs/dialogs_widget.h" #include "dialogs/dialogs_search_from_controllers.h" //#include "history/feed/history_feed_section.h" // #feed #include "history/history.h" @@ -41,6 +42,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_chat_helpers.h" #include "styles/style_window.h" +namespace Dialogs { namespace { constexpr auto kHashtagResultsLimit = 5; @@ -48,32 +50,33 @@ constexpr auto kStartReorderThreshold = 30; } // namespace -struct DialogsInner::ImportantSwitch { - Dialogs::RippleRow row; +struct InnerWidget::ImportantSwitch { + RippleRow row; }; -struct DialogsInner::HashtagResult { +struct InnerWidget::HashtagResult { HashtagResult(const QString &tag) : tag(tag) { } QString tag; - Dialogs::RippleRow row; + RippleRow row; }; -struct DialogsInner::PeerSearchResult { +struct InnerWidget::PeerSearchResult { PeerSearchResult(not_null peer) : peer(peer) { } not_null peer; - Dialogs::RippleRow row; + RippleRow row; }; -DialogsInner::DialogsInner(QWidget *parent, not_null controller) +InnerWidget::InnerWidget( + QWidget *parent, + not_null controller) : RpWidget(parent) , _controller(controller) , _pinnedShiftAnimation([=](crl::time now) { return pinnedShiftAnimationCallback(now); }) , _addContactLnk(this, lang(lng_add_contact_button)) -, _closeOpenedFolder(this, st::dialogsCancelSearchInPeer) , _cancelSearchInChat(this, st::dialogsCancelSearchInPeer) , _cancelSearchFromUser(this, st::dialogsCancelSearchInPeer) { @@ -85,8 +88,6 @@ DialogsInner::DialogsInner(QWidget *parent, not_null contro _importantSwitch = std::make_unique(); } connect(_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); - _closeOpenedFolder->setClickedCallback([=] { cancelFolder(); }); - _closeOpenedFolder->hide(); _cancelSearchInChat->setClickedCallback([=] { cancelSearchInChat(); }); _cancelSearchInChat->hide(); _cancelSearchFromUser->setClickedCallback([=] { @@ -135,14 +136,14 @@ DialogsInner::DialogsInner(QWidget *parent, not_null contro session().data().sendActionAnimationUpdated( ) | rpl::start_with_next([=]( const Data::Session::SendActionAnimationUpdate &update) { - using RowPainter = Dialogs::Layout::RowPainter; + using RowPainter = Layout::RowPainter; const auto updateRect = RowPainter::sendActionAnimationRect( update.width, update.height, width(), update.textUpdated); updateDialogRow( - Dialogs::RowDescriptor(update.history, FullMsgId()), + RowDescriptor(update.history, FullMsgId()), updateRect, UpdateRowSection::Default | UpdateRowSection::Filtered); }, lifetime()); @@ -151,19 +152,12 @@ DialogsInner::DialogsInner(QWidget *parent, not_null contro ) | rpl::filter([=](Data::Folder *folder) { return (folder == _openedFolder); }) | rpl::start_with_next([=] { - const auto mode = Global::DialogsMode(); - if (_openedFolder - && _openedFolder->chatsList()->indexed(mode)->empty()) { - _openedFolder->updateChatListSortPosition(); - cancelFolder(); - } else { - refresh(); - } + refresh(); }, lifetime()); subscribe(Window::Theme::Background(), [=](const Window::Theme::BackgroundUpdate &data) { if (data.paletteChanged()) { - Dialogs::Layout::clearUnreadBadgesCache(); + Layout::clearUnreadBadgesCache(); } }); @@ -201,8 +195,8 @@ DialogsInner::DialogsInner(QWidget *parent, not_null contro _controller->activeChatEntryValue( ) | rpl::combine_previous( ) | rpl::start_with_next([=]( - Dialogs::RowDescriptor previous, - Dialogs::RowDescriptor next) { + RowDescriptor previous, + RowDescriptor next) { updateDialogRow(previous); updateDialogRow(next); }, lifetime()); @@ -211,11 +205,11 @@ DialogsInner::DialogsInner(QWidget *parent, not_null contro setupShortcuts(); } -AuthSession &DialogsInner::session() const { +AuthSession &InnerWidget::session() const { return _controller->session(); } -void DialogsInner::handleChatMigration(not_null chat) { +void InnerWidget::handleChatMigration(not_null chat) { const auto channel = chat->migrateTo(); if (!channel) { return; @@ -230,15 +224,13 @@ void DialogsInner::handleChatMigration(not_null chat) { } } -int DialogsInner::dialogsOffset() const { - return _openedFolder - ? openedFolderSkip() - : _importantSwitch +int InnerWidget::dialogsOffset() const { + return _importantSwitch ? st::dialogsImportantBarHeight : 0; } -int DialogsInner::proxyPromotedCount() const { +int InnerWidget::proxyPromotedCount() const { auto result = 0; for (const auto row : *shownDialogs()) { if (row->entry()->fixedOnTopIndex()) { @@ -250,19 +242,19 @@ int DialogsInner::proxyPromotedCount() const { return result; } -int DialogsInner::pinnedOffset() const { +int InnerWidget::pinnedOffset() const { return dialogsOffset() + proxyPromotedCount() * st::dialogsRowHeight; } -int DialogsInner::filteredOffset() const { +int InnerWidget::filteredOffset() const { return _hashtagResults.size() * st::mentionHeight; } -int DialogsInner::peerSearchOffset() const { +int InnerWidget::peerSearchOffset() const { return filteredOffset() + (_filterResults.size() * st::dialogsRowHeight) + st::searchedBarHeight; } -int DialogsInner::searchedOffset() const { +int InnerWidget::searchedOffset() const { auto result = peerSearchOffset() + (_peerSearchResults.empty() ? 0 : ((_peerSearchResults.size() * st::dialogsRowHeight) + st::searchedBarHeight)); if (_searchInChat) { result += searchInChatSkip(); @@ -270,7 +262,7 @@ int DialogsInner::searchedOffset() const { return result; } -int DialogsInner::searchInChatSkip() const { +int InnerWidget::searchInChatSkip() const { auto result = st::searchedBarHeight + st::dialogsSearchInHeight; if (_searchFromUser) { result += st::lineWidth + st::dialogsSearchInHeight; @@ -278,40 +270,20 @@ int DialogsInner::searchInChatSkip() const { return result; } -int DialogsInner::openedFolderSkip() const { - return st::dialogsSearchInHeight; -} - -bool DialogsInner::openFolder(not_null folder) { - return changeOpenedFolder(folder); -} - -bool DialogsInner::cancelFolder() { - return changeOpenedFolder(nullptr); -} - -bool DialogsInner::changeOpenedFolder(Data::Folder *folder) { +void InnerWidget::changeOpenedFolder(Data::Folder *folder) { if (_openedFolder == folder) { - return false; + return; } stopReorderPinned(); clearSelection(); _openedFolder = folder; - _closeOpenedFolder->setVisible(folder != nullptr); - if (folder) { - _openedFolderText.setText( - st::msgNameStyle, - folder->chatListName(), - Ui::DialogTextOptions()); - } refresh(); if (_loadMoreCallback) { _loadMoreCallback(); } - return true; } -void DialogsInner::paintEvent(QPaintEvent *e) { +void InnerWidget::paintEvent(QPaintEvent *e) { Painter p(this); const auto r = e->rect(); @@ -322,17 +294,11 @@ void DialogsInner::paintEvent(QPaintEvent *e) { auto fullWidth = width(); auto dialogsClip = r; auto ms = crl::now(); - if (_openedFolder) { - const auto skip = openedFolderSkip(); - paintOpenedFolder(p); - dialogsClip.translate(0, -skip); - p.translate(0, skip); - } - if (_state == State::Default) { + if (_state == WidgetState::Default) { auto rows = shownDialogs(); if (!_openedFolder && _importantSwitch) { auto selected = isPressed() ? _importantSwitchPressed : _importantSwitchSelected; - Dialogs::Layout::paintImportantSwitch(p, Global::DialogsMode(), fullWidth, selected); + Layout::paintImportantSwitch(p, Global::DialogsMode(), fullWidth, selected); dialogsClip.translate(0, -st::dialogsImportantBarHeight); p.translate(0, st::dialogsImportantBarHeight); } @@ -343,10 +309,10 @@ void DialogsInner::paintEvent(QPaintEvent *e) { : (isPressed() ? (_pressed ? _pressed->key() - : Dialogs::Key()) + : Key()) : (_selected ? _selected->key() - : Dialogs::Key())); + : Key())); if (otherStart) { auto reorderingPinned = (_aboveIndex >= 0 && !_pinnedRows.empty()); auto &list = rows->all(); @@ -355,7 +321,7 @@ void DialogsInner::paintEvent(QPaintEvent *e) { } const auto promoted = proxyPromotedCount(); - const auto paintDialog = [&](not_null row) { + const auto paintDialog = [&](not_null row) { const auto pinned = row->pos() - promoted; const auto count = _pinnedRows.size(); const auto xadd = 0; @@ -367,7 +333,7 @@ void DialogsInner::paintEvent(QPaintEvent *e) { } const auto isActive = (row->key() == active); const auto isSelected = (row->key() == selected); - Dialogs::Layout::RowPainter::paint( + Layout::RowPainter::paint( p, row, fullWidth, @@ -423,7 +389,7 @@ void DialogsInner::paintEvent(QPaintEvent *e) { p.setPen(st::noContactsColor); p.drawText(QRect(0, 0, fullWidth, st::noContactsHeight - (session().data().contactsLoaded().current() ? st::noContactsFont->height : 0)), lang(session().data().contactsLoaded().current() ? lng_no_chats : lng_contacts_loading), style::al_center); } - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { if (!_hashtagResults.empty()) { auto from = floorclamp(r.y(), st::mentionHeight, 0, _hashtagResults.size()); auto to = ceilclamp(r.y() + r.height(), st::mentionHeight, 0, _hashtagResults.size()); @@ -484,7 +450,7 @@ void DialogsInner::paintEvent(QPaintEvent *e) { : (from == (isPressed() ? _filteredPressed : _filteredSelected)); - Dialogs::Layout::RowPainter::paint( + Layout::RowPainter::paint( p, _filterResults[from], fullWidth, @@ -574,7 +540,7 @@ void DialogsInner::paintEvent(QPaintEvent *e) { : (from == (isPressed() ? _searchedPressed : _searchedSelected)); - Dialogs::Layout::RowPainter::paint( + Layout::RowPainter::paint( p, result.get(), fullWidth, @@ -589,9 +555,9 @@ void DialogsInner::paintEvent(QPaintEvent *e) { } } -bool DialogsInner::isSearchResultActive( - not_null result, - const Dialogs::RowDescriptor &entry) const { +bool InnerWidget::isSearchResultActive( + not_null result, + const RowDescriptor &entry) const { const auto item = result->item(); const auto peer = item->history()->peer; return (item->fullId() == entry.fullId) @@ -601,7 +567,7 @@ bool DialogsInner::isSearchResultActive( || (uniqueSearchResults() && peer == entry.key.peer()); } -void DialogsInner::paintPeerSearchResult( +void InnerWidget::paintPeerSearchResult( Painter &p, not_null result, int fullWidth, @@ -622,7 +588,7 @@ void DialogsInner::paintPeerSearchResult( QRect rectForName(nameleft, st::dialogsPadding.y() + st::dialogsNameTop, namewidth, st::msgNameFont->height); // draw chat icon - if (auto chatTypeIcon = Dialogs::Layout::ChatTypeIcon(peer, active, selected)) { + if (auto chatTypeIcon = Layout::ChatTypeIcon(peer, active, selected)) { chatTypeIcon->paint(p, rectForName.topLeft(), fullWidth); rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip); } @@ -657,7 +623,7 @@ void DialogsInner::paintPeerSearchResult( peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); } -void DialogsInner::paintSearchInChat(Painter &p) const { +void InnerWidget::paintSearchInChat(Painter &p) const { auto height = searchInChatSkip(); auto top = st::searchedBarHeight; @@ -682,7 +648,7 @@ void DialogsInner::paintSearchInChat(Painter &p) const { //} else if (const auto feed = _searchInChat.feed()) { // #feed // paintSearchInFeed(p, feed, top, fullWidth, _searchInChatText); } else { - Unexpected("Empty Dialogs::Key in paintSearchInChat."); + Unexpected("Empty Key in paintSearchInChat."); } if (const auto from = _searchFromUser) { top += st::dialogsSearchInHeight + st::lineWidth; @@ -693,7 +659,7 @@ void DialogsInner::paintSearchInChat(Painter &p) const { } } template -void DialogsInner::paintSearchInFilter( +void InnerWidget::paintSearchInFilter( Painter &p, PaintUserpic paintUserpic, int top, @@ -730,18 +696,7 @@ void DialogsInner::paintSearchInFilter( width()); } -void DialogsInner::paintOpenedFolder(Painter &p) const { - const auto paintUserpic = [&](Painter & p, int x, int y, int size) { - _openedFolder->paintUserpicLeft(p, x, y, width(), size); - }; - const auto top = 0; - const auto fullRect = QRect(0, top, width(), openedFolderSkip() - top); - p.fillRect(fullRect, st::dialogsBg); - p.setPen(st::dialogsNameFg); - paintSearchInFilter(p, paintUserpic, top, nullptr, _openedFolderText); -} - -void DialogsInner::paintSearchInPeer( +void InnerWidget::paintSearchInPeer( Painter &p, not_null peer, int top, @@ -749,11 +704,11 @@ void DialogsInner::paintSearchInPeer( const auto paintUserpic = [&](Painter &p, int x, int y, int size) { peer->paintUserpicLeft(p, x, y, width(), size); }; - const auto icon = Dialogs::Layout::ChatTypeIcon(peer, false, false); + const auto icon = Layout::ChatTypeIcon(peer, false, false); paintSearchInFilter(p, paintUserpic, top, icon, text); } -void DialogsInner::paintSearchInSaved( +void InnerWidget::paintSearchInSaved( Painter &p, int top, const Text &text) const { @@ -763,7 +718,7 @@ void DialogsInner::paintSearchInSaved( paintSearchInFilter(p, paintUserpic, top, nullptr, text); } -//void DialogsInner::paintSearchInFeed( // #feed +//void InnerWidget::paintSearchInFeed( // #feed // Painter &p, // not_null feed, // int top, @@ -771,14 +726,14 @@ void DialogsInner::paintSearchInSaved( // const auto paintUserpic = [&](Painter &p, int x, int y, int size) { // feed->paintUserpicLeft(p, x, y, width(), size); // }; -// const auto icon = Dialogs::Layout::FeedTypeIcon(feed, false, false); +// const auto icon = Layout::FeedTypeIcon(feed, false, false); // paintSearchInFilter(p, paintUserpic, top, icon, text); //} // -void DialogsInner::activate() { +void InnerWidget::activate() { } -void DialogsInner::mouseMoveEvent(QMouseEvent *e) { +void InnerWidget::mouseMoveEvent(QMouseEvent *e) { const auto globalPosition = e->globalPos(); if (!_lastMousePosition) { _lastMousePosition = globalPosition; @@ -790,8 +745,8 @@ void DialogsInner::mouseMoveEvent(QMouseEvent *e) { selectByMouse(globalPosition); } -void DialogsInner::clearIrrelevantState() { - if (_state == State::Default) { +void InnerWidget::clearIrrelevantState() { + if (_state == WidgetState::Default) { _hashtagSelected = -1; setHashtagPressed(-1); _hashtagDeleteSelected = _hashtagDeletePressed = false; @@ -801,7 +756,7 @@ void DialogsInner::clearIrrelevantState() { setPeerSearchPressed(-1); _searchedSelected = -1; setSearchedPressed(-1); - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { _importantSwitchSelected = false; setImportantSwitchPressed(false); _selected = nullptr; @@ -809,7 +764,7 @@ void DialogsInner::clearIrrelevantState() { } } -void DialogsInner::selectByMouse(QPoint globalPosition) { +void InnerWidget::selectByMouse(QPoint globalPosition) { const auto local = mapFromGlobal(globalPosition); if (updateReorderPinned(local)) { return; @@ -820,8 +775,8 @@ void DialogsInner::selectByMouse(QPoint globalPosition) { const auto w = width(); const auto mouseY = local.y(); clearIrrelevantState(); - if (_state == State::Default) { - const auto switchTop = _openedFolder ? openedFolderSkip() : 0; + if (_state == WidgetState::Default) { + const auto switchTop = 0; const auto switchBottom = dialogsOffset(); const auto importantSwitchSelected = _importantSwitch && !_openedFolder @@ -839,7 +794,7 @@ void DialogsInner::selectByMouse(QPoint globalPosition) { updateSelectedRow(); setCursor((_selected || _importantSwitchSelected) ? style::cur_pointer : style::cur_default); } - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { auto wasSelected = isSelected(); if (_hashtagResults.empty()) { _hashtagSelected = -1; @@ -899,7 +854,7 @@ void DialogsInner::selectByMouse(QPoint globalPosition) { } } -void DialogsInner::mousePressEvent(QMouseEvent *e) { +void InnerWidget::mousePressEvent(QMouseEvent *e) { selectByMouse(e->globalPos()); _pressButton = e->button(); @@ -953,8 +908,8 @@ void DialogsInner::mousePressEvent(QMouseEvent *e) { } } -void DialogsInner::checkReorderPinnedStart(QPoint localPosition) { - if (!_pressed || _dragging || _state != State::Default) { +void InnerWidget::checkReorderPinnedStart(QPoint localPosition) { + if (!_pressed || _dragging || _state != WidgetState::Default) { return; } else if (qAbs(localPosition.y() - _dragStart.y()) < ConvertScale(kStartReorderThreshold)) { @@ -965,7 +920,7 @@ void DialogsInner::checkReorderPinnedStart(QPoint localPosition) { _dragging = nullptr; } else { const auto &order = session().data().pinnedChatsOrder(_openedFolder); - _pinnedOnDragStart = base::flat_set{ + _pinnedOnDragStart = base::flat_set{ order.begin(), order.end() }; @@ -975,7 +930,7 @@ void DialogsInner::checkReorderPinnedStart(QPoint localPosition) { } } -int DialogsInner::shownPinnedCount() const { +int InnerWidget::shownPinnedCount() const { auto result = 0; for (const auto row : *shownDialogs()) { if (row->entry()->fixedOnTopIndex()) { @@ -988,7 +943,7 @@ int DialogsInner::shownPinnedCount() const { return result; } -int DialogsInner::countPinnedIndex(Dialogs::Row *ofRow) { +int InnerWidget::countPinnedIndex(Row *ofRow) { if (!ofRow || !ofRow->entry()->isPinnedDialog()) { return -1; } @@ -1006,7 +961,7 @@ int DialogsInner::countPinnedIndex(Dialogs::Row *ofRow) { return -1; } -void DialogsInner::savePinnedOrder() { +void InnerWidget::savePinnedOrder() { const auto &newOrder = session().data().pinnedChatsOrder(_openedFolder); if (newOrder.size() != _pinnedOnDragStart.size()) { return; // Something has changed in the set of pinned chats. @@ -1019,7 +974,7 @@ void DialogsInner::savePinnedOrder() { session().api().savePinnedOrder(_openedFolder); } -void DialogsInner::finishReorderPinned() { +void InnerWidget::finishReorderPinned() { auto wasDragging = (_dragging != nullptr); if (wasDragging) { savePinnedOrder(); @@ -1036,12 +991,12 @@ void DialogsInner::finishReorderPinned() { } } -void DialogsInner::stopReorderPinned() { +void InnerWidget::stopReorderPinned() { _pinnedShiftAnimation.stop(); finishReorderPinned(); } -int DialogsInner::updateReorderIndexGetCount() { +int InnerWidget::updateReorderIndexGetCount() { auto index = countPinnedIndex(_dragging); if (index < 0) { finishReorderPinned(); @@ -1066,7 +1021,7 @@ int DialogsInner::updateReorderIndexGetCount() { return count; } -bool DialogsInner::updateReorderPinned(QPoint localPosition) { +bool InnerWidget::updateReorderPinned(QPoint localPosition) { checkReorderPinnedStart(localPosition); auto pinnedCount = updateReorderIndexGetCount(); if (pinnedCount < 2) { @@ -1122,7 +1077,7 @@ bool DialogsInner::updateReorderPinned(QPoint localPosition) { return true; } -bool DialogsInner::pinnedShiftAnimationCallback(crl::time now) { +bool InnerWidget::pinnedShiftAnimationCallback(crl::time now) { if (anim::Disabled()) { now += st::stickersRowDuration; } @@ -1173,11 +1128,11 @@ bool DialogsInner::pinnedShiftAnimationCallback(crl::time now) { return animating; } -void DialogsInner::mouseReleaseEvent(QMouseEvent *e) { +void InnerWidget::mouseReleaseEvent(QMouseEvent *e) { mousePressReleased(e->globalPos(), e->button()); } -void DialogsInner::mousePressReleased( +void InnerWidget::mousePressReleased( QPoint globalPosition, Qt::MouseButton button) { auto wasDragging = (_dragging != nullptr); @@ -1228,7 +1183,7 @@ void DialogsInner::mousePressReleased( } } -void DialogsInner::setImportantSwitchPressed(bool pressed) { +void InnerWidget::setImportantSwitchPressed(bool pressed) { if (_importantSwitchPressed != pressed) { if (_importantSwitchPressed) { _importantSwitch->row.stopLastRipple(); @@ -1237,7 +1192,7 @@ void DialogsInner::setImportantSwitchPressed(bool pressed) { } } -void DialogsInner::setPressed(Dialogs::Row *pressed) { +void InnerWidget::setPressed(Row *pressed) { if (_pressed != pressed) { if (_pressed) { _pressed->stopLastRipple(); @@ -1246,48 +1201,47 @@ void DialogsInner::setPressed(Dialogs::Row *pressed) { } } -void DialogsInner::setHashtagPressed(int pressed) { +void InnerWidget::setHashtagPressed(int pressed) { if (base::in_range(_hashtagPressed, 0, _hashtagResults.size())) { _hashtagResults[_hashtagPressed]->row.stopLastRipple(); } _hashtagPressed = pressed; } -void DialogsInner::setFilteredPressed(int pressed) { +void InnerWidget::setFilteredPressed(int pressed) { if (base::in_range(_filteredPressed, 0, _filterResults.size())) { _filterResults[_filteredPressed]->stopLastRipple(); } _filteredPressed = pressed; } -void DialogsInner::setPeerSearchPressed(int pressed) { +void InnerWidget::setPeerSearchPressed(int pressed) { if (base::in_range(_peerSearchPressed, 0, _peerSearchResults.size())) { _peerSearchResults[_peerSearchPressed]->row.stopLastRipple(); } _peerSearchPressed = pressed; } -void DialogsInner::setSearchedPressed(int pressed) { +void InnerWidget::setSearchedPressed(int pressed) { if (base::in_range(_searchedPressed, 0, _searchResults.size())) { _searchResults[_searchedPressed]->stopLastRipple(); } _searchedPressed = pressed; } -void DialogsInner::resizeEvent(QResizeEvent *e) { +void InnerWidget::resizeEvent(QResizeEvent *e) { _addContactLnk->move((width() - _addContactLnk->width()) / 2, (st::noContactsHeight + st::noContactsFont->height) / 2); const auto widthForCancelButton = qMax(width(), st::columnMinimalWidthLeft); const auto left = widthForCancelButton - st::dialogsSearchInSkip - _cancelSearchInChat->width(); const auto top = (st::dialogsSearchInHeight - st::dialogsCancelSearchInPeer.height) / 2; - _closeOpenedFolder->moveToLeft(left, top); _cancelSearchInChat->moveToLeft(left, st::searchedBarHeight + top); _cancelSearchFromUser->moveToLeft(left, st::searchedBarHeight + st::dialogsSearchInHeight + st::lineWidth + top); } -void DialogsInner::dialogRowReplaced( - Dialogs::Row *oldRow, - Dialogs::Row *newRow) { - if (_state == State::Filtered) { +void InnerWidget::dialogRowReplaced( + Row *oldRow, + Row *newRow) { + if (_state == WidgetState::Filtered) { for (auto i = _filterResults.begin(); i != _filterResults.end();) { if (*i == oldRow) { // this row is shown in filtered and maybe is in contacts! if (newRow) { @@ -1316,22 +1270,22 @@ void DialogsInner::dialogRowReplaced( } } -void DialogsInner::refreshDialog(Dialogs::Key key) { +void InnerWidget::refreshDialog(Key key) { if (const auto history = key.history()) { if (history->peer->loadedStatus != PeerData::LoadedStatus::FullLoaded) { LOG(("API Error: " - "DialogsInner::refreshDialog() called for a non loaded peer!" + "InnerWidget::refreshDialog() called for a non loaded peer!" )); return; } } const auto result = session().data().refreshChatListEntry(key); - const auto changed = (Global::DialogsMode() == Dialogs::Mode::Important) + const auto changed = (Global::DialogsMode() == Mode::Important) ? result.importantChanged : result.changed; - const auto moved = (Global::DialogsMode() == Dialogs::Mode::Important) + const auto moved = (Global::DialogsMode() == Mode::Important) ? result.importantMoved : result.moved; @@ -1345,7 +1299,7 @@ void DialogsInner::refreshDialog(Dialogs::Key key) { if (changed) { refresh(); - } else if (_state == State::Default && from != to) { + } else if (_state == WidgetState::Default && from != to) { update( 0, std::min(from, to), @@ -1354,7 +1308,7 @@ void DialogsInner::refreshDialog(Dialogs::Key key) { } } -void DialogsInner::removeDialog(Dialogs::Key key) { +void InnerWidget::removeDialog(Key key) { if (key == _menuRow.key && _menu) { InvokeQueued(this, [=] { _menu = nullptr; }); } @@ -1369,7 +1323,7 @@ void DialogsInner::removeDialog(Dialogs::Key key) { session().notifications().clearFromHistory(history); Local::removeSavedPeer(history->peer); } - const auto i = ranges::find(_filterResults, key, &Dialogs::Row::key); + const auto i = ranges::find(_filterResults, key, &Row::key); if (i != _filterResults.end()) { if (_filteredSelected == (i - _filterResults.begin()) && (i + 1) == _filterResults.end()) { @@ -1384,10 +1338,10 @@ void DialogsInner::removeDialog(Dialogs::Key key) { refresh(); } -void DialogsInner::repaintDialogRow( - Dialogs::Mode list, - not_null row) { - if (_state == State::Default) { +void InnerWidget::repaintDialogRow( + Mode list, + not_null row) { + if (_state == WidgetState::Default) { if (Global::DialogsMode() == list) { auto position = row->pos(); auto top = dialogsOffset(); @@ -1396,8 +1350,8 @@ void DialogsInner::repaintDialogRow( } update(0, top + position * st::dialogsRowHeight, width(), st::dialogsRowHeight); } - } else if (_state == State::Filtered) { - if (list == Dialogs::Mode::All) { + } else if (_state == WidgetState::Filtered) { + if (list == Mode::All) { for (auto i = 0, l = int(_filterResults.size()); i != l; ++i) { if (_filterResults[i]->key() == row->key()) { update( @@ -1412,12 +1366,12 @@ void DialogsInner::repaintDialogRow( } } -void DialogsInner::repaintDialogRow(Dialogs::RowDescriptor row) { +void InnerWidget::repaintDialogRow(RowDescriptor row) { updateDialogRow(row); } -void DialogsInner::updateSearchResult(not_null peer) { - if (_state == State::Filtered) { +void InnerWidget::updateSearchResult(not_null peer) { + if (_state == WidgetState::Filtered) { if (!_peerSearchResults.empty()) { auto index = 0, add = peerSearchOffset(); for (const auto &result : _peerSearchResults) { @@ -1431,8 +1385,8 @@ void DialogsInner::updateSearchResult(not_null peer) { } } -void DialogsInner::updateDialogRow( - Dialogs::RowDescriptor row, +void InnerWidget::updateDialogRow( + RowDescriptor row, QRect updateRect, UpdateRowSections sections) { if (updateRect.isEmpty()) { @@ -1442,7 +1396,7 @@ void DialogsInner::updateDialogRow( if (const auto peer = row.key.peer()) { if (const auto from = peer->migrateFrom()) { if (const auto migrated = from->owner().historyLoaded(from)) { - row = Dialogs::RowDescriptor( + row = RowDescriptor( migrated, FullMsgId(0, -row.fullId.msg)); } @@ -1457,7 +1411,7 @@ void DialogsInner::updateDialogRow( updateRect.width(), updateRect.height()); }; - if (_state == State::Default) { + if (_state == WidgetState::Default) { if (sections & UpdateRowSection::Default) { if (const auto dialog = shownDialogs()->getRow(row.key)) { const auto position = dialog->pos(); @@ -1468,7 +1422,7 @@ void DialogsInner::updateDialogRow( updateRow(top + position * st::dialogsRowHeight); } } - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { if ((sections & UpdateRowSection::Filtered) && !_filterResults.empty()) { const auto add = filteredOffset(); @@ -1510,12 +1464,12 @@ void DialogsInner::updateDialogRow( } } -void DialogsInner::enterEventHook(QEvent *e) { +void InnerWidget::enterEventHook(QEvent *e) { setMouseTracking(true); } -void DialogsInner::updateSelectedRow(Dialogs::Key key) { - if (_state == State::Default) { +void InnerWidget::updateSelectedRow(Key key) { + if (_state == WidgetState::Default) { if (key) { const auto entry = key.entry(); if (!entry->inChatList(Global::DialogsMode())) { @@ -1530,10 +1484,9 @@ void DialogsInner::updateSelectedRow(Dialogs::Key key) { } else if (_selected) { update(0, dialogsOffset() + _selected->pos() * st::dialogsRowHeight, width(), st::dialogsRowHeight); } else if (_importantSwitchSelected) { - const auto switchTop = _openedFolder ? openedFolderSkip() : 0; - update(0, switchTop, width(), st::dialogsImportantBarHeight); + update(0, 0, width(), st::dialogsImportantBarHeight); } - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { if (key) { for (auto i = 0, l = int(_filterResults.size()); i != l; ++i) { if (_filterResults[i]->key() == key) { @@ -1553,22 +1506,22 @@ void DialogsInner::updateSelectedRow(Dialogs::Key key) { } } -not_null DialogsInner::shownDialogs() const { +not_null InnerWidget::shownDialogs() const { const auto mode = Global::DialogsMode(); return session().data().chatsList(_openedFolder)->indexed(mode); } -void DialogsInner::leaveEventHook(QEvent *e) { +void InnerWidget::leaveEventHook(QEvent *e) { setMouseTracking(false); clearSelection(); } -void DialogsInner::dragLeft() { +void InnerWidget::dragLeft() { setMouseTracking(false); clearSelection(); } -void DialogsInner::clearSelection() { +void InnerWidget::clearSelection() { _mouseSelection = false; _lastMousePosition = std::nullopt; if (_importantSwitchSelected @@ -1585,7 +1538,7 @@ void DialogsInner::clearSelection() { } } -void DialogsInner::fillSupportSearchMenu(not_null menu) { +void InnerWidget::fillSupportSearchMenu(not_null menu) { const auto all = session().settings().supportAllSearchResults(); const auto text = all ? "Only one from chat" : "Show all messages"; menu->addAction(text, [=] { @@ -1594,19 +1547,19 @@ void DialogsInner::fillSupportSearchMenu(not_null menu) { }); } -void DialogsInner::contextMenuEvent(QContextMenuEvent *e) { +void InnerWidget::contextMenuEvent(QContextMenuEvent *e) { _menu = nullptr; if (e->reason() == QContextMenuEvent::Mouse) { selectByMouse(e->globalPos()); } - const auto row = [&]() -> Dialogs::RowDescriptor { - if (_state == State::Default) { + const auto row = [&]() -> RowDescriptor { + if (_state == WidgetState::Default) { if (_selected) { return { _selected->key(), FullMsgId() }; } - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { if (base::in_range(_filteredSelected, 0, _filterResults.size())) { return { _filterResults[_filteredSelected]->key(), FullMsgId() }; } else if (session().supportMode() @@ -1617,7 +1570,7 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) { }; } } - return Dialogs::RowDescriptor(); + return RowDescriptor(); }(); if (!row.key) return; @@ -1664,7 +1617,7 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) { } } -void DialogsInner::onParentGeometryChanged() { +void InnerWidget::onParentGeometryChanged() { const auto globalPosition = QCursor::pos(); if (rect().contains(mapFromGlobal(globalPosition))) { setMouseTracking(true); @@ -1674,7 +1627,7 @@ void DialogsInner::onParentGeometryChanged() { } } -void DialogsInner::applyFilterUpdate(QString newFilter, bool force) { +void InnerWidget::applyFilterUpdate(QString newFilter, bool force) { const auto mentionsSearch = (newFilter == qstr("@")); const auto words = mentionsSearch ? QStringList(newFilter) @@ -1685,11 +1638,11 @@ void DialogsInner::applyFilterUpdate(QString newFilter, bool force) { if (_filter.isEmpty() && !_searchFromUser) { clearFilter(); } else { - _state = State::Filtered; + _state = WidgetState::Filtered; _waitingForSearch = true; _filterResults.clear(); _filterResultsGlobal.clear(); - const auto append = [&](not_null list) { + const auto append = [&](not_null list) { const auto results = list->filtered(words); _filterResults.insert( end(_filterResults), @@ -1708,12 +1661,12 @@ void DialogsInner::applyFilterUpdate(QString newFilter, bool force) { } clearMouseSelection(true); } - if (_state != State::Default) { + if (_state != WidgetState::Default) { emit searchMessages(); } } -void DialogsInner::onHashtagFilterUpdate(QStringRef newFilter) { +void InnerWidget::onHashtagFilterUpdate(QStringRef newFilter) { if (newFilter.isEmpty() || newFilter.at(0) != '#' || _searchInChat) { _hashtagFilter = QString(); if (!_hashtagResults.empty()) { @@ -1743,11 +1696,11 @@ void DialogsInner::onHashtagFilterUpdate(QStringRef newFilter) { clearMouseSelection(true); } -DialogsInner::~DialogsInner() { +InnerWidget::~InnerWidget() { clearSearchResults(); } -void DialogsInner::clearSearchResults(bool clearPeerSearchResults) { +void InnerWidget::clearSearchResults(bool clearPeerSearchResults) { if (clearPeerSearchResults) _peerSearchResults.clear(); _searchResults.clear(); _searchedCount = _searchedMigratedCount = 0; @@ -1756,17 +1709,17 @@ void DialogsInner::clearSearchResults(bool clearPeerSearchResults) { _lastSearchId = _lastSearchMigratedId = 0; } -PeerData *DialogsInner::updateFromParentDrag(QPoint globalPosition) { +PeerData *InnerWidget::updateFromParentDrag(QPoint globalPosition) { selectByMouse(globalPosition); - const auto getPeerFromRow = [](Dialogs::Row *row) -> PeerData* { + const auto getPeerFromRow = [](Row *row) -> PeerData* { if (const auto history = row ? row->history() : nullptr) { return history->peer; } return nullptr; }; - if (_state == State::Default) { + if (_state == WidgetState::Default) { return getPeerFromRow(_selected); - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { if (base::in_range(_filteredSelected, 0, _filterResults.size())) { return getPeerFromRow(_filterResults[_filteredSelected]); } else if (base::in_range(_peerSearchSelected, 0, _peerSearchResults.size())) { @@ -1778,15 +1731,19 @@ PeerData *DialogsInner::updateFromParentDrag(QPoint globalPosition) { return nullptr; } -void DialogsInner::setLoadMoreCallback(Fn callback) { +void InnerWidget::setLoadMoreCallback(Fn callback) { _loadMoreCallback = std::move(callback); } -rpl::producer<> DialogsInner::listBottomReached() const { +auto InnerWidget::chosenRow() const -> rpl::producer { + return _chosenRow.events(); +} + +rpl::producer<> InnerWidget::listBottomReached() const { return _listBottomReached.events(); } -void DialogsInner::visibleTopBottomUpdated( +void InnerWidget::visibleTopBottomUpdated( int visibleTop, int visibleBottom) { _visibleTop = visibleTop; @@ -1799,7 +1756,7 @@ void DialogsInner::visibleTopBottomUpdated( } } -void DialogsInner::itemRemoved(not_null item) { +void InnerWidget::itemRemoved(not_null item) { int wasCount = _searchResults.size(); for (auto i = _searchResults.begin(); i != _searchResults.end();) { if ((*i)->item() == item) { @@ -1818,14 +1775,12 @@ void DialogsInner::itemRemoved(not_null item) { } } -bool DialogsInner::uniqueSearchResults() const { - return session().supportMode() - && !session().settings().supportAllSearchResults() - && !_searchInChat; +bool InnerWidget::uniqueSearchResults() const { + return _controller->uniqueChatsInSearchResults(); } -bool DialogsInner::hasHistoryInResults(not_null history) const { - using Result = std::unique_ptr; +bool InnerWidget::hasHistoryInResults(not_null history) const { + using Result = std::unique_ptr; const auto inSearchResults = ranges::find( _searchResults, history, @@ -1837,7 +1792,7 @@ bool DialogsInner::hasHistoryInResults(not_null history) const { const auto inFilteredResults = ranges::find( _filterResults, history.get(), - [](Dialogs::Row *row) { return row->history(); } + [](Row *row) { return row->history(); } ) != end(_filterResults); if (inFilteredResults) { return true; @@ -1853,16 +1808,16 @@ bool DialogsInner::hasHistoryInResults(not_null history) const { return false; } -bool DialogsInner::searchReceived( +bool InnerWidget::searchReceived( const QVector &messages, - DialogsSearchRequestType type, + SearchRequestType type, int fullCount) { const auto uniquePeers = uniqueSearchResults(); - if (type == DialogsSearchFromStart || type == DialogsSearchPeerFromStart) { + if (type == SearchRequestType::FromStart || type == SearchRequestType::PeerFromStart) { clearSearchResults(false); } - auto isGlobalSearch = (type == DialogsSearchFromStart || type == DialogsSearchFromOffset); - auto isMigratedSearch = (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset); + auto isGlobalSearch = (type == SearchRequestType::FromStart || type == SearchRequestType::FromOffset); + auto isMigratedSearch = (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset); TimeId lastDateFound = 0; for (const auto &message : messages) { @@ -1877,7 +1832,7 @@ bool DialogsInner::searchReceived( const auto history = item->history(); if (!uniquePeers || !hasHistoryInResults(history)) { _searchResults.push_back( - std::make_unique( + std::make_unique( _searchInChat, item)); if (uniquePeers && !history->unreadCountKnown()) { @@ -1909,8 +1864,8 @@ bool DialogsInner::searchReceived( if (_waitingForSearch && (!_searchResults.empty() || !_searchInMigrated - || type == DialogsSearchMigratedFromStart - || type == DialogsSearchMigratedFromOffset)) { + || type == SearchRequestType::MigratedFromStart + || type == SearchRequestType::MigratedFromOffset)) { _waitingForSearch = false; } @@ -1919,11 +1874,11 @@ bool DialogsInner::searchReceived( return lastDateFound != 0; } -void DialogsInner::peerSearchReceived( +void InnerWidget::peerSearchReceived( const QString &query, const QVector &my, const QVector &result) { - if (_state != State::Filtered) { + if (_state != WidgetState::Filtered) { return; } @@ -1945,7 +1900,7 @@ void DialogsInner::peerSearchReceived( if (alreadyAdded(peer)) { continue; } - auto row = std::make_unique( + auto row = std::make_unique( peer->owner().history(peer), _filterResults.size()); const auto [i, ok] = _filterResultsGlobal.emplace( @@ -1954,7 +1909,7 @@ void DialogsInner::peerSearchReceived( _filterResults.push_back(i->second.get()); } else { LOG(("API Error: " - "user %1 was not loaded in DialogsInner::peopleReceived()" + "user %1 was not loaded in InnerWidget::peopleReceived()" ).arg(peer->id)); } } @@ -1969,27 +1924,27 @@ void DialogsInner::peerSearchReceived( peer)); } else { LOG(("API Error: " - "user %1 was not loaded in DialogsInner::peopleReceived()" + "user %1 was not loaded in InnerWidget::peopleReceived()" ).arg(peer->id)); } } refresh(); } -void DialogsInner::notify_historyMuteUpdated(History *history) { +void InnerWidget::notify_historyMuteUpdated(History *history) { if (!_importantSwitch || !history->inChatList()) { return; } refreshDialog(history); } -Data::Folder *DialogsInner::shownFolder() const { +Data::Folder *InnerWidget::shownFolder() const { return _openedFolder; } -void DialogsInner::refresh(bool toTop) { - auto h = _openedFolder ? openedFolderSkip() : 0; - if (_state == State::Default) { +void InnerWidget::refresh(bool toTop) { + auto h = 0; + if (_state == WidgetState::Default) { if (shownDialogs()->empty()) { h = st::noContactsHeight; if (session().data().contactsLoaded().current()) { @@ -2001,7 +1956,7 @@ void DialogsInner::refresh(bool toTop) { h = dialogsOffset() + shownDialogs()->size() * st::dialogsRowHeight; if (!_addContactLnk->isHidden()) _addContactLnk->hide(); } - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { if (!_addContactLnk->isHidden()) _addContactLnk->hide(); if (_waitingForSearch) { h = searchedOffset() + (_searchResults.size() * st::dialogsRowHeight) + ((_searchResults.empty() && !_searchInChat) ? -st::searchedBarHeight : 0); @@ -2016,19 +1971,19 @@ void DialogsInner::refresh(bool toTop) { loadPeerPhotos(); } _controller->dialogsListDisplayForced().set( - _openedFolder || _searchInChat || !_filter.isEmpty(), + _searchInChat || !_filter.isEmpty(), true); update(); } -void DialogsInner::clearMouseSelection(bool clearSelection) { +void InnerWidget::clearMouseSelection(bool clearSelection) { _mouseSelection = false; _lastMousePosition = std::nullopt; if (clearSelection) { - if (_state == State::Default) { + if (_state == WidgetState::Default) { _selected = nullptr; _importantSwitchSelected = false; - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { _filteredSelected = _peerSearchSelected = _searchedSelected @@ -2038,15 +1993,15 @@ void DialogsInner::clearMouseSelection(bool clearSelection) { } } -DialogsInner::State DialogsInner::state() const { +WidgetState InnerWidget::state() const { return _state; } -bool DialogsInner::hasFilteredResults() const { +bool InnerWidget::hasFilteredResults() const { return !_filterResults.empty() && _hashtagResults.empty(); } -void DialogsInner::searchInChat(Dialogs::Key key, UserData *from) { +void InnerWidget::searchInChat(Key key, UserData *from) { _searchInMigrated = nullptr; if (const auto peer = key.peer()) { if (const auto migrateTo = peer->migrateTo()) { @@ -2073,11 +2028,11 @@ void DialogsInner::searchInChat(Dialogs::Key key, UserData *from) { _cancelSearchFromUser->hide(); } _controller->dialogsListDisplayForced().set( - _openedFolder || _searchInChat || !_filter.isEmpty(), + _searchInChat || !_filter.isEmpty(), true); } -void DialogsInner::refreshSearchInChatLabel() { +void InnerWidget::refreshSearchInChatLabel() { const auto dialog = [&] { if (const auto peer = _searchInChat.peer()) { if (peer->isSelf()) { @@ -2112,13 +2067,13 @@ void DialogsInner::refreshSearchInChatLabel() { } } -void DialogsInner::clearFilter() { - if (_state == State::Filtered || _searchInChat) { +void InnerWidget::clearFilter() { + if (_state == WidgetState::Filtered || _searchInChat) { if (_searchInChat) { - _state = State::Filtered; + _state = WidgetState::Filtered; _waitingForSearch = true; } else { - _state = State::Default; + _state = WidgetState::Default; } _hashtagResults.clear(); _filterResults.clear(); @@ -2133,9 +2088,9 @@ void DialogsInner::clearFilter() { } } -void DialogsInner::selectSkip(int32 direction) { +void InnerWidget::selectSkip(int32 direction) { clearMouseSelection(); - if (_state == State::Default) { + if (_state == WidgetState::Default) { if (_importantSwitchSelected) { if (!shownDialogs()->empty() && direction > 0) { _selected = *shownDialogs()->cbegin(); @@ -2169,7 +2124,7 @@ void DialogsInner::selectSkip(int32 direction) { int fromY = _importantSwitchSelected ? 0 : (dialogsOffset() + _selected->pos() * st::dialogsRowHeight); emit mustScrollTo(fromY, fromY + st::dialogsRowHeight); } - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { if (_hashtagResults.empty() && _filterResults.empty() && _peerSearchResults.empty() && _searchResults.empty()) return; if ((_hashtagSelected < 0 || _hashtagSelected >= _hashtagResults.size()) && (_filteredSelected < 0 || _filteredSelected >= _filterResults.size()) && @@ -2220,13 +2175,13 @@ void DialogsInner::selectSkip(int32 direction) { update(); } -void DialogsInner::scrollToEntry(const Dialogs::RowDescriptor &entry) { +void InnerWidget::scrollToEntry(const RowDescriptor &entry) { int32 fromY = -1; - if (_state == State::Default) { + if (_state == WidgetState::Default) { if (auto row = shownDialogs()->getRow(entry.key)) { fromY = dialogsOffset() + row->pos() * st::dialogsRowHeight; } - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { for (int32 i = 0, c = _searchResults.size(); i < c; ++i) { if (isSearchResultActive(_searchResults[i].get(), entry)) { fromY = searchedOffset() + i * st::dialogsRowHeight; @@ -2247,10 +2202,10 @@ void DialogsInner::scrollToEntry(const Dialogs::RowDescriptor &entry) { } } -void DialogsInner::selectSkipPage(int32 pixels, int32 direction) { +void InnerWidget::selectSkipPage(int32 pixels, int32 direction) { clearMouseSelection(); int toSkip = pixels / int(st::dialogsRowHeight); - if (_state == State::Default) { + if (_state == WidgetState::Default) { if (!_selected) { if (direction > 0 && !shownDialogs()->empty()) { _selected = *shownDialogs()->cbegin(); @@ -2282,13 +2237,13 @@ void DialogsInner::selectSkipPage(int32 pixels, int32 direction) { update(); } -void DialogsInner::loadPeerPhotos() { +void InnerWidget::loadPeerPhotos() { if (!parentWidget()) return; auto yFrom = _visibleTop; auto yTo = _visibleTop + (_visibleBottom - _visibleTop) * (PreloadHeightsCount + 1); session().downloader().clearPriorities(); - if (_state == State::Default) { + if (_state == WidgetState::Default) { auto otherStart = shownDialogs()->size() * st::dialogsRowHeight; if (yFrom < otherStart) { for (auto i = shownDialogs()->cfind(yFrom, st::dialogsRowHeight), end = shownDialogs()->cend(); i != end; ++i) { @@ -2302,7 +2257,7 @@ void DialogsInner::loadPeerPhotos() { yFrom -= otherStart; } yTo -= otherStart; - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { int32 from = (yFrom - filteredOffset()) / st::dialogsRowHeight; if (from < 0) from = 0; if (from < _filterResults.size()) { @@ -2337,18 +2292,18 @@ void DialogsInner::loadPeerPhotos() { } } -bool DialogsInner::switchImportantChats() { +bool InnerWidget::switchImportantChats() { if (!_importantSwitchSelected || !_importantSwitch - || (_state != State::Default)) { + || (_state != WidgetState::Default)) { return false; } clearSelection(); - if (Global::DialogsMode() == Dialogs::Mode::All) { - Global::SetDialogsMode(Dialogs::Mode::Important); + if (Global::DialogsMode() == Mode::All) { + Global::SetDialogsMode(Mode::Important); } else { - Global::SetDialogsMode(Dialogs::Mode::All); + Global::SetDialogsMode(Mode::All); } Local::writeUserSettings(); refresh(); @@ -2356,8 +2311,8 @@ bool DialogsInner::switchImportantChats() { return true; } -bool DialogsInner::chooseHashtag() { - if (_state != State::Filtered) { +bool InnerWidget::chooseHashtag() { + if (_state != WidgetState::Filtered) { return false; } else if ((_hashtagSelected < 0) || (_hashtagSelected >= _hashtagResults.size())) { @@ -2384,20 +2339,21 @@ bool DialogsInner::chooseHashtag() { return true; } -DialogsInner::ChosenRow DialogsInner::computeChosenRow() const { +ChosenRow InnerWidget::computeChosenRow() const { auto msgId = ShowAtUnreadMsgId; - if (_state == State::Default) { + if (_state == WidgetState::Default) { if (_selected) { return { _selected->key(), Data::UnreadMessagePosition }; } - } else if (_state == State::Filtered) { + } else if (_state == WidgetState::Filtered) { if (base::in_range(_filteredSelected, 0, _filterResults.size())) { return { _filterResults[_filteredSelected]->key(), - Data::UnreadMessagePosition + Data::UnreadMessagePosition, + true }; } else if (base::in_range(_peerSearchSelected, 0, _peerSearchResults.size())) { return { @@ -2422,7 +2378,7 @@ DialogsInner::ChosenRow DialogsInner::computeChosenRow() const { return ChosenRow(); } -bool DialogsInner::chooseRow() { +bool InnerWidget::chooseRow() { if (switchImportantChats()) { return true; } else if (chooseHashtag()) { @@ -2433,21 +2389,6 @@ bool DialogsInner::chooseRow() { if (IsServerMsgId(chosen.message.fullId.msg)) { Local::saveRecentSearchHashtags(_filter); } - const auto openSearchResult = !App::main()->selectingPeer() - && (_state == State::Filtered) - && base::in_range(_filteredSelected, 0, _filterResults.size()); - if (const auto history = chosen.key.history()) { - App::main()->choosePeer( - history->peer->id, - (uniqueSearchResults() - ? ShowAtUnreadMsgId - : chosen.message.fullId.msg)); - } else if (const auto folder = chosen.key.folder()) { - openFolder(folder); - } - if (openSearchResult && !session().supportMode()) { - emit clearSearchQuery(); - } updateSelectedRow(); _mouseSelection = false; _lastMousePosition = std::nullopt; @@ -2457,38 +2398,41 @@ bool DialogsInner::chooseRow() { = _peerSearchSelected = _searchedSelected = -1; + + _chosenRow.fire_copy(chosen); + return true; } return false; } -Dialogs::RowDescriptor DialogsInner::chatListEntryBefore( - const Dialogs::RowDescriptor &which) const { +RowDescriptor InnerWidget::chatListEntryBefore( + const RowDescriptor &which) const { if (!which.key) { - return Dialogs::RowDescriptor(); + return RowDescriptor(); } - if (_state == State::Default) { + if (_state == WidgetState::Default) { if (const auto row = shownDialogs()->getRow(which.key)) { const auto i = shownDialogs()->cfind(row); if (i != shownDialogs()->cbegin()) { - return Dialogs::RowDescriptor( + return RowDescriptor( (*(i - 1))->key(), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } const auto whichHistory = which.key.history(); const auto whichFullId = which.fullId; if (!whichHistory) { - return Dialogs::RowDescriptor(); + return RowDescriptor(); } if (!_searchResults.empty()) { for (auto b = _searchResults.cbegin(), i = b + 1, e = _searchResults.cend(); i != e; ++i) { if (isSearchResultActive(i->get(), which)) { const auto j = i - 1; - return Dialogs::RowDescriptor( + return RowDescriptor( (*j)->item()->history(), (*j)->item()->fullId()); } @@ -2496,13 +2440,13 @@ Dialogs::RowDescriptor DialogsInner::chatListEntryBefore( if (isSearchResultActive(_searchResults[0].get(), which)) { if (_peerSearchResults.empty()) { if (_filterResults.empty()) { - return Dialogs::RowDescriptor(); + return RowDescriptor(); } - return Dialogs::RowDescriptor( + return RowDescriptor( _filterResults.back()->key(), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } - return Dialogs::RowDescriptor( + return RowDescriptor( session().data().history(_peerSearchResults.back()->peer), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } @@ -2510,171 +2454,171 @@ Dialogs::RowDescriptor DialogsInner::chatListEntryBefore( if (!_peerSearchResults.empty() && _peerSearchResults[0]->peer == whichHistory->peer) { if (_filterResults.empty()) { - return Dialogs::RowDescriptor(); + return RowDescriptor(); } - return Dialogs::RowDescriptor( + return RowDescriptor( _filterResults.back()->key(), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } if (!_peerSearchResults.empty()) { for (auto b = _peerSearchResults.cbegin(), i = b + 1, e = _peerSearchResults.cend(); i != e; ++i) { if ((*i)->peer == whichHistory->peer) { - return Dialogs::RowDescriptor( + return RowDescriptor( session().data().history((*(i - 1))->peer), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } } } if (_filterResults.empty() || _filterResults[0]->key() == which.key) { - return Dialogs::RowDescriptor(); + return RowDescriptor(); } for (auto b = _filterResults.cbegin(), i = b + 1, e = _filterResults.cend(); i != e; ++i) { if ((*i)->key() == which.key) { - return Dialogs::RowDescriptor( + return RowDescriptor( (*(i - 1))->key(), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } -Dialogs::RowDescriptor DialogsInner::chatListEntryAfter( - const Dialogs::RowDescriptor &which) const { +RowDescriptor InnerWidget::chatListEntryAfter( + const RowDescriptor &which) const { if (!which.key) { - return Dialogs::RowDescriptor(); + return RowDescriptor(); } - if (_state == State::Default) { + if (_state == WidgetState::Default) { if (const auto row = shownDialogs()->getRow(which.key)) { const auto i = shownDialogs()->cfind(row) + 1; if (i != shownDialogs()->cend()) { - return Dialogs::RowDescriptor( + return RowDescriptor( (*i)->key(), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } const auto whichHistory = which.key.history(); const auto whichFullId = which.fullId; if (!whichHistory) { - return Dialogs::RowDescriptor(); + return RowDescriptor(); } for (auto i = _searchResults.cbegin(), e = _searchResults.cend(); i != e; ++i) { if (isSearchResultActive(i->get(), which)) { if (++i != e) { - return Dialogs::RowDescriptor( + return RowDescriptor( (*i)->item()->history(), (*i)->item()->fullId()); } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } } for (auto i = _peerSearchResults.cbegin(), e = _peerSearchResults.cend(); i != e; ++i) { if ((*i)->peer == whichHistory->peer) { ++i; if (i != e) { - return Dialogs::RowDescriptor( + return RowDescriptor( session().data().history((*i)->peer), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } else if (!_searchResults.empty()) { - return Dialogs::RowDescriptor( + return RowDescriptor( _searchResults.front()->item()->history(), _searchResults.front()->item()->fullId()); } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } } for (auto i = _filterResults.cbegin(), e = _filterResults.cend(); i != e; ++i) { if ((*i)->key() == which.key) { ++i; if (i != e) { - return Dialogs::RowDescriptor( + return RowDescriptor( (*i)->key(), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } else if (!_peerSearchResults.empty()) { - return Dialogs::RowDescriptor( + return RowDescriptor( session().data().history(_peerSearchResults.front()->peer), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } else if (!_searchResults.empty()) { - return Dialogs::RowDescriptor( + return RowDescriptor( _searchResults.front()->item()->history(), _searchResults.front()->item()->fullId()); } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } -Dialogs::RowDescriptor DialogsInner::chatListEntryFirst() const { - if (_state == State::Default) { +RowDescriptor InnerWidget::chatListEntryFirst() const { + if (_state == WidgetState::Default) { const auto i = shownDialogs()->cbegin(); if (i != shownDialogs()->cend()) { - return Dialogs::RowDescriptor( + return RowDescriptor( (*i)->key(), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } else if (!_filterResults.empty()) { - return Dialogs::RowDescriptor( + return RowDescriptor( _filterResults.front()->key(), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } else if (!_peerSearchResults.empty()) { - return Dialogs::RowDescriptor( + return RowDescriptor( session().data().history(_peerSearchResults.front()->peer), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } else if (!_searchResults.empty()) { - return Dialogs::RowDescriptor( + return RowDescriptor( _searchResults.front()->item()->history(), _searchResults.front()->item()->fullId()); } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } -Dialogs::RowDescriptor DialogsInner::chatListEntryLast() const { - if (_state == State::Default) { +RowDescriptor InnerWidget::chatListEntryLast() const { + if (_state == WidgetState::Default) { const auto i = shownDialogs()->cend(); if (i != shownDialogs()->cbegin()) { - return Dialogs::RowDescriptor( + return RowDescriptor( (*(i - 1))->key(), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } else if (!_searchResults.empty()) { - return Dialogs::RowDescriptor( + return RowDescriptor( _searchResults.back()->item()->history(), _searchResults.back()->item()->fullId()); } else if (!_peerSearchResults.empty()) { - return Dialogs::RowDescriptor( + return RowDescriptor( session().data().history(_peerSearchResults.back()->peer), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } else if (!_filterResults.empty()) { - return Dialogs::RowDescriptor( + return RowDescriptor( _filterResults.back()->key(), FullMsgId(NoChannel, ShowAtUnreadMsgId)); } - return Dialogs::RowDescriptor(); + return RowDescriptor(); } -int32 DialogsInner::lastSearchDate() const { +int32 InnerWidget::lastSearchDate() const { return _lastSearchDate; } -PeerData *DialogsInner::lastSearchPeer() const { +PeerData *InnerWidget::lastSearchPeer() const { return _lastSearchPeer; } -MsgId DialogsInner::lastSearchId() const { +MsgId InnerWidget::lastSearchId() const { return _lastSearchId; } -MsgId DialogsInner::lastSearchMigratedId() const { +MsgId InnerWidget::lastSearchMigratedId() const { return _lastSearchMigratedId; } -void DialogsInner::setupShortcuts() { +void InnerWidget::setupShortcuts() { Shortcuts::Requests( ) | rpl::filter([=] { return isActiveWindow() && !Ui::isLayerShown(); @@ -2754,8 +2698,8 @@ void DialogsInner::setupShortcuts() { }, lifetime()); } -Dialogs::RowDescriptor DialogsInner::computeJump( - const Dialogs::RowDescriptor &to, +RowDescriptor InnerWidget::computeJump( + const RowDescriptor &to, JumpSkip skip) { auto result = to; if (session().supportMode() && result.key) { @@ -2780,7 +2724,7 @@ Dialogs::RowDescriptor DialogsInner::computeJump( return result; } -bool DialogsInner::jumpToDialogRow(Dialogs::RowDescriptor to) { +bool InnerWidget::jumpToDialogRow(RowDescriptor to) { if (to == chatListEntryLast()) { _listBottomReached.fire({}); } @@ -2789,3 +2733,5 @@ bool DialogsInner::jumpToDialogRow(Dialogs::RowDescriptor to) { } return _controller->jumpToChatListEntry(to); } + +} // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index 27626dc8b8..b7d48823a7 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -7,18 +7,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "dialogs/dialogs_widget.h" #include "dialogs/dialogs_key.h" #include "data/data_messages.h" #include "ui/effects/animations.h" #include "ui/rp_widget.h" #include "base/flags.h" -namespace Dialogs { -class Row; -class FakeRow; -class IndexedList; -} // namespace Dialogs +class AuthSession; namespace Ui { class IconButton; @@ -30,18 +25,44 @@ namespace Window { class Controller; } // namespace Window -class DialogsInner +namespace Dialogs { + +class Row; +class FakeRow; +class IndexedList; + +struct ChosenRow { + Key key; + Data::MessagePosition message; + bool filteredRow = false; +}; + +enum class SearchRequestType { + FromStart, + FromOffset, + PeerFromStart, + PeerFromOffset, + MigratedFromStart, + MigratedFromOffset, +}; + +enum class WidgetState { + Default, + Filtered, +}; + +class InnerWidget : public Ui::RpWidget , public RPCSender , private base::Subscriber { Q_OBJECT public: - DialogsInner(QWidget *parent, not_null controller); + InnerWidget(QWidget *parent, not_null controller); bool searchReceived( const QVector &result, - DialogsSearchRequestType type, + SearchRequestType type, int fullCount); void peerSearchReceived( const QString &query, @@ -50,15 +71,14 @@ public: void activate(); - bool openFolder(not_null folder); - bool cancelFolder(); + void changeOpenedFolder(Data::Folder *folder); void selectSkip(int32 direction); void selectSkipPage(int32 pixels, int32 direction); - void refreshDialog(Dialogs::Key key); - void removeDialog(Dialogs::Key key); - void repaintDialogRow(Dialogs::Mode list, not_null row); - void repaintDialogRow(Dialogs::RowDescriptor row); + void refreshDialog(Key key); + void removeDialog(Key key); + void repaintDialogRow(Mode list, not_null row); + void repaintDialogRow(RowDescriptor row); void dragLeft(); @@ -67,7 +87,7 @@ public: bool chooseRow(); - void scrollToEntry(const Dialogs::RowDescriptor &entry); + void scrollToEntry(const RowDescriptor &entry); Data::Folder *shownFolder() const; int32 lastSearchDate() const; @@ -75,17 +95,13 @@ public: MsgId lastSearchId() const; MsgId lastSearchMigratedId() const; - enum class State { - Default, - Filtered, - }; - State state() const; + WidgetState state() const; bool waitingForSearch() const { return _waitingForSearch; } bool hasFilteredResults() const; - void searchInChat(Dialogs::Key key, UserData *from); + void searchInChat(Key key, UserData *from); void applyFilterUpdate(QString newFilter, bool force = false); void onHashtagFilterUpdate(QStringRef newFilter); @@ -97,9 +113,11 @@ public: base::Observable searchFromUserChanged; + rpl::producer chosenRow() const; + void notify_historyMuteUpdated(History *history); - ~DialogsInner(); + ~InnerWidget(); public slots: void onParentGeometryChanged(); @@ -109,7 +127,6 @@ signals: void mustScrollTo(int scrollToTop, int scrollToBottom); void dialogMoved(int movedFrom, int movedTo); void searchMessages(); - void clearSearchQuery(); void cancelSearchInChat(); void completeHashtag(QString tag); void refreshHashtags(); @@ -140,21 +157,16 @@ private: NextOrOriginal, }; - struct ChosenRow { - Dialogs::Key key; - Data::MessagePosition message; - }; - AuthSession &session() const; - void dialogRowReplaced(Dialogs::Row *oldRow, Dialogs::Row *newRow); + void dialogRowReplaced(Row *oldRow, Row *newRow); bool switchImportantChats(); bool chooseHashtag(); ChosenRow computeChosenRow() const; bool isSearchResultActive( - not_null result, - const Dialogs::RowDescriptor &entry) const; + not_null result, + const RowDescriptor &entry) const; void clearMouseSelection(bool clearSelection = false); void mousePressReleased(QPoint globalPosition, Qt::MouseButton button); @@ -162,7 +174,7 @@ private: void selectByMouse(QPoint globalPosition); void loadPeerPhotos(); void setImportantSwitchPressed(bool pressed); - void setPressed(Dialogs::Row *pressed); + void setPressed(Row *pressed); void setHashtagPressed(int pressed); void setFilteredPressed(int pressed); void setPeerSearchPressed(int pressed); @@ -187,17 +199,15 @@ private: bool hasHistoryInResults(not_null history) const; void setupShortcuts(); - Dialogs::RowDescriptor computeJump( - const Dialogs::RowDescriptor &to, + RowDescriptor computeJump( + const RowDescriptor &to, JumpSkip skip); - bool jumpToDialogRow(Dialogs::RowDescriptor to); + bool jumpToDialogRow(RowDescriptor to); - Dialogs::RowDescriptor chatListEntryBefore( - const Dialogs::RowDescriptor &which) const; - Dialogs::RowDescriptor chatListEntryAfter( - const Dialogs::RowDescriptor &which) const; - Dialogs::RowDescriptor chatListEntryFirst() const; - Dialogs::RowDescriptor chatListEntryLast() const; + RowDescriptor chatListEntryBefore(const RowDescriptor &which) const; + RowDescriptor chatListEntryAfter(const RowDescriptor &which) const; + RowDescriptor chatListEntryFirst() const; + RowDescriptor chatListEntryLast() const; void itemRemoved(not_null item); enum class UpdateRowSection { @@ -212,7 +222,7 @@ private: void updateSearchResult(not_null peer); void updateDialogRow( - Dialogs::RowDescriptor row, + RowDescriptor row, QRect updateRect = QRect(), UpdateRowSections sections = UpdateRowSection::All); void fillSupportSearchMenu(not_null menu); @@ -224,7 +234,6 @@ private: int peerSearchOffset() const; int searchedOffset() const; int searchInChatSkip() const; - int openedFolderSkip() const; void paintPeerSearchResult( Painter &p, @@ -232,7 +241,6 @@ private: int fullWidth, bool active, bool selected) const; - void paintOpenedFolder(Painter &p) const; void paintSearchInChat(Painter &p) const; void paintSearchInPeer( Painter &p, @@ -259,9 +267,9 @@ private: void clearSelection(); void clearSearchResults(bool clearPeerSearchResults = true); - void updateSelectedRow(Dialogs::Key key = Dialogs::Key()); + void updateSelectedRow(Key key = Key()); - not_null shownDialogs() const; + not_null shownDialogs() const; void checkReorderPinnedStart(QPoint localPosition); int shownPinnedCount() const; @@ -269,13 +277,11 @@ private: bool updateReorderPinned(QPoint localPosition); void finishReorderPinned(); void stopReorderPinned(); - int countPinnedIndex(Dialogs::Row *ofRow); + int countPinnedIndex(Row *ofRow); void savePinnedOrder(); bool pinnedShiftAnimationCallback(crl::time now); void handleChatMigration(not_null chat); - bool changeOpenedFolder(Data::Folder *folder); - not_null _controller; bool _mouseSelection = false; @@ -283,15 +289,14 @@ private: Qt::MouseButton _pressButton = Qt::LeftButton; Data::Folder *_openedFolder = nullptr; - Text _openedFolderText; std::unique_ptr _importantSwitch; bool _importantSwitchSelected = false; bool _importantSwitchPressed = false; - Dialogs::Row *_selected = nullptr; - Dialogs::Row *_pressed = nullptr; + Row *_selected = nullptr; + Row *_pressed = nullptr; - Dialogs::Row *_dragging = nullptr; + Row *_dragging = nullptr; int _draggingIndex = -1; int _aboveIndex = -1; QPoint _dragStart; @@ -301,7 +306,7 @@ private: }; std::vector _pinnedRows; Ui::Animations::Basic _pinnedShiftAnimation; - base::flat_set _pinnedOnDragStart; + base::flat_set _pinnedOnDragStart; // Remember the last currently dragged row top shift for updating area. int _aboveTopShift = -1; @@ -316,10 +321,10 @@ private: bool _hashtagDeleteSelected = false; bool _hashtagDeletePressed = false; - std::vector> _filterResults; + std::vector> _filterResults; base::flat_map< not_null, - std::unique_ptr> _filterResultsGlobal; + std::unique_ptr> _filterResultsGlobal; int _filteredSelected = -1; int _filteredPressed = -1; @@ -330,7 +335,7 @@ private: int _peerSearchSelected = -1; int _peerSearchPressed = -1; - std::vector> _searchResults; + std::vector> _searchResults; int _searchedCount = 0; int _searchedMigratedCount = 0; int _searchedSelected = -1; @@ -341,23 +346,25 @@ private: MsgId _lastSearchId = 0; MsgId _lastSearchMigratedId = 0; - State _state = State::Default; + WidgetState _state = WidgetState::Default; object_ptr _addContactLnk; - object_ptr _closeOpenedFolder; object_ptr _cancelSearchInChat; object_ptr _cancelSearchFromUser; - Dialogs::Key _searchInChat; + Key _searchInChat; History *_searchInMigrated = nullptr; UserData *_searchFromUser = nullptr; Text _searchInChatText; Text _searchFromUserText; - Dialogs::RowDescriptor _menuRow; + RowDescriptor _menuRow; Fn _loadMoreCallback; rpl::event_stream<> _listBottomReached; + rpl::event_stream _chosenRow; base::unique_qptr _menu; }; + +} // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 286dfd9e20..ae863fd026 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -41,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_history.h" #include "styles/style_window.h" +namespace Dialogs { namespace { QString SwitchToChooseFromQuery() { @@ -49,7 +50,7 @@ QString SwitchToChooseFromQuery() { } // namespace -class DialogsWidget::BottomButton : public Ui::RippleButton { +class Widget::BottomButton : public Ui::RippleButton { public: BottomButton( QWidget *parent, @@ -76,7 +77,7 @@ private: }; -DialogsWidget::BottomButton::BottomButton( +Widget::BottomButton::BottomButton( QWidget *parent, const QString &text, const style::FlatButton &st, @@ -90,18 +91,18 @@ DialogsWidget::BottomButton::BottomButton( resize(st::columnMinimalWidthLeft, _st.height); } -void DialogsWidget::BottomButton::setText(const QString &text) { +void Widget::BottomButton::setText(const QString &text) { _text = text.toUpper(); update(); } -void DialogsWidget::BottomButton::radialAnimationCallback() { +void Widget::BottomButton::radialAnimationCallback() { if (!anim::Disabled() && width() < st::columnMinimalWidthLeft) { update(); } } -void DialogsWidget::BottomButton::onStateChanged(State was, StateChangeSource source) { +void Widget::BottomButton::onStateChanged(State was, StateChangeSource source) { RippleButton::onStateChanged(was, source); if ((was & StateFlag::Disabled) != (state() & StateFlag::Disabled)) { _loading = isDisabled() @@ -116,7 +117,7 @@ void DialogsWidget::BottomButton::onStateChanged(State was, StateChangeSource so update(); } -void DialogsWidget::BottomButton::paintEvent(QPaintEvent *e) { +void Widget::BottomButton::paintEvent(QPaintEvent *e) { Painter p(this); const auto over = isOver() && !isDisabled(); @@ -147,21 +148,22 @@ void DialogsWidget::BottomButton::paintEvent(QPaintEvent *e) { } } -DialogsWidget::DialogsWidget(QWidget *parent, not_null controller) +Widget::Widget(QWidget *parent, not_null controller) : Window::AbstractSectionWidget(parent, controller) -, _mainMenuToggle(this, st::dialogsMenuToggle) -, _filter(this, st::dialogsFilter, langFactory(lng_dlg_filter)) +, _searchControls(this) +, _mainMenuToggle(_searchControls, st::dialogsMenuToggle) +, _filter(_searchControls, st::dialogsFilter, langFactory(lng_dlg_filter)) , _chooseFromUser( - this, + _searchControls, object_ptr(this, st::dialogsSearchFrom)) , _jumpToDate( - this, + _searchControls, object_ptr(this, st::dialogsCalendar)) -, _cancelSearch(this, st::dialogsCancelSearch) -, _lockUnlock(this, st::dialogsLock) +, _cancelSearch(_searchControls, st::dialogsCancelSearch) +, _lockUnlock(_searchControls, st::dialogsLock) , _scroll(this, st::dialogsScroll) , _scrollToTop(_scroll, st::dialogsToUp) { - _inner = _scroll->setOwnedWidget(object_ptr(this, controller)); + _inner = _scroll->setOwnedWidget(object_ptr(this, controller)); rpl::combine( session().api().dialogsLoadMayBlockByDate(), @@ -174,7 +176,6 @@ DialogsWidget::DialogsWidget(QWidget *parent, not_null cont connect(_inner, SIGNAL(mustScrollTo(int,int)), _scroll, SLOT(scrollToY(int,int))); connect(_inner, SIGNAL(dialogMoved(int,int)), this, SLOT(onDialogMoved(int,int))); connect(_inner, SIGNAL(searchMessages()), this, SLOT(onNeedSearchMessages())); - connect(_inner, SIGNAL(clearSearchQuery()), this, SLOT(onCancel())); connect(_inner, SIGNAL(completeHashtag(QString)), this, SLOT(onCompleteHashtag(QString))); connect(_inner, SIGNAL(refreshHashtags()), this, SLOT(onFilterCursorMoved())); connect(_inner, SIGNAL(cancelSearchInChat()), this, SLOT(onCancelSearchInChat())); @@ -182,6 +183,24 @@ DialogsWidget::DialogsWidget(QWidget *parent, not_null cont setSearchInChat(_searchInChat, user); applyFilterUpdate(true); }); + _inner->chosenRow( + ) | rpl::start_with_next([=](const ChosenRow &row) { + const auto openSearchResult = !App::main()->selectingPeer() + && row.filteredRow; + if (const auto history = row.key.history()) { + App::main()->choosePeer( + history->peer->id, + (controller->uniqueChatsInSearchResults() + ? ShowAtUnreadMsgId + : row.message.fullId.msg)); + } else if (const auto folder = row.key.folder()) { + controller->openFolder(folder); + } + if (openSearchResult && !session().supportMode()) { + onCancel(); + } + }, lifetime()); + connect(_scroll, SIGNAL(geometryChanged()), _inner, SLOT(onParentGeometryChanged())); connect(_scroll, SIGNAL(scrolled()), this, SLOT(onListScroll())); @@ -238,9 +257,8 @@ DialogsWidget::DialogsWidget(QWidget *parent, not_null cont connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages())); _inner->setLoadMoreCallback([=] { - using State = DialogsInner::State; const auto state = _inner->state(); - if (state == State::Filtered + if (state == WidgetState::Filtered && (!_inner->waitingForSearch() || (_searchInMigrated && _searchFull @@ -266,9 +284,18 @@ DialogsWidget::DialogsWidget(QWidget *parent, not_null cont setupConnectingWidget(); setupSupportMode(); setupScrollUpButton(); + + changeOpenedFolder( + controller->openedFolder().current(), + anim::type::instant); + + controller->openedFolder().changes( + ) | rpl::start_with_next([=](Data::Folder *folder) { + changeOpenedFolder(folder, anim::type::normal); + }, lifetime()); } -void DialogsWidget::setupScrollUpButton() { +void Widget::setupScrollUpButton() { _scrollToTop->setClickedCallback([=] { if (_scrollToAnimation.animating()) { return; @@ -284,7 +311,7 @@ void DialogsWidget::setupScrollUpButton() { updateScrollUpVisibility(); } -void DialogsWidget::updateScrollUpVisibility() { +void Widget::updateScrollUpVisibility() { if (_scrollToAnimation.animating()) { return; } @@ -293,7 +320,7 @@ void DialogsWidget::updateScrollUpVisibility() { _scroll->scrollTop() > st::historyToDownShownAfter); } -void DialogsWidget::startScrollUpButtonAnimation(bool shown) { +void Widget::startScrollUpButtonAnimation(bool shown) { const auto smallColumn = (width() < st::columnMinimalWidthLeft); shown &= !smallColumn; if (_scrollToTopIsShown == shown) { @@ -307,7 +334,7 @@ void DialogsWidget::startScrollUpButtonAnimation(bool shown) { smallColumn ? 0 : st::historyToDownDuration); } -void DialogsWidget::updateScrollUpPosition() { +void Widget::updateScrollUpPosition() { // _scrollToTop is a child widget of _scroll, not me. auto top = anim::interpolate( 0, @@ -323,13 +350,13 @@ void DialogsWidget::updateScrollUpPosition() { } } -void DialogsWidget::setupConnectingWidget() { +void Widget::setupConnectingWidget() { _connecting = std::make_unique( this, Window::AdaptiveIsOneColumn()); } -void DialogsWidget::setupSupportMode() { +void Widget::setupSupportMode() { if (!session().supportMode()) { return; } @@ -347,7 +374,73 @@ void DialogsWidget::setupSupportMode() { }, lifetime()); } -void DialogsWidget::checkUpdateStatus() { +void Widget::updateControlsVisibility(bool fast) { + updateLoadMoreChatsVisibility(); + _scroll->show(); + if (_forwardCancel) { + _forwardCancel->show(); + } + if (_openedFolder && _filter->hasFocus()) { + setFocus(); + } + if (_updateTelegram) { + _updateTelegram->show(); + } + _searchControls->setVisible(!_openedFolder); + if (!_openedFolder) { + if (hasFocus()) { + _filter->setFocus(); + _filter->finishAnimations(); + } + updateLockUnlockVisibility(); + updateJumpToDateVisibility(fast); + updateSearchFromVisibility(fast); + } + _connecting->setForceHidden(false); +} + +void Widget::changeOpenedFolder(Data::Folder *folder, anim::type animated) { + _a_show.stop(); + if (animated == anim::type::normal) { + _showDirection = folder + ? Window::SlideDirection::FromRight + : Window::SlideDirection::FromLeft; + _showAnimationType = ShowAnimation::Internal; + _connecting->setForceHidden(true); + _cacheUnder = grabForFolderSlideAnimation(); + } + _openedFolder = folder; + updateControlsVisibility(true); + _inner->changeOpenedFolder(folder); + if (animated == anim::type::normal) { + _connecting->setForceHidden(true); + _cacheOver = grabForFolderSlideAnimation(); + _connecting->setForceHidden(false); + startSlideAnimation(); + } +} + +QPixmap Widget::grabForFolderSlideAnimation() { + const auto hidden = _scrollToTop->isHidden(); + if (!hidden) { + _scrollToTop->hide(); + } + + const auto top = _forwardCancel ? _forwardCancel->height() : 0; + const auto rect = QRect( + 0, + top, + width(), + (_updateTelegram ? _updateTelegram->y() : height()) - top); + auto result = Ui::GrabWidget(this, rect); + + if (!hidden) { + _scrollToTop->show(); + } + return result; +} + +void Widget::checkUpdateStatus() { Expects(!Core::UpdaterDisabled()); using Checker = Core::UpdateChecker; @@ -371,12 +464,16 @@ void DialogsWidget::checkUpdateStatus() { updateControlsGeometry(); } -void DialogsWidget::activate() { - _filter->setFocus(); +void Widget::activate() { + if (_openedFolder) { + setFocus(); + } else { + _filter->setFocus(); + } _inner->activate(); } -void DialogsWidget::refreshDialog(Dialogs::Key key) { +void Widget::refreshDialog(Key key) { const auto creating = !key.entry()->inChatList(); _inner->refreshDialog(key); const auto history = key.history(); @@ -390,17 +487,17 @@ void DialogsWidget::refreshDialog(Dialogs::Key key) { } } -void DialogsWidget::repaintDialogRow( - Dialogs::Mode list, - not_null row) { +void Widget::repaintDialogRow( + Mode list, + not_null row) { _inner->repaintDialogRow(list, row); } -void DialogsWidget::repaintDialogRow(Dialogs::RowDescriptor row) { +void Widget::repaintDialogRow(RowDescriptor row) { _inner->repaintDialogRow(row); } -void DialogsWidget::jumpToTop() { +void Widget::jumpToTop() { if (session().supportMode()) { return; } @@ -410,7 +507,7 @@ void DialogsWidget::jumpToTop() { } } -void DialogsWidget::scrollToTop() { +void Widget::scrollToTop() { _scrollToAnimation.stop(); auto scrollTop = _scroll->scrollTop(); const auto scrollTo = 0; @@ -434,7 +531,7 @@ void DialogsWidget::scrollToTop() { anim::sineInOut); } -void DialogsWidget::startWidthAnimation() { +void Widget::startWidthAnimation() { if (!_widthAnimationCache.isNull()) { return; } @@ -457,7 +554,7 @@ void DialogsWidget::startWidthAnimation() { _scroll->hide(); } -void DialogsWidget::stopWidthAnimation() { +void Widget::stopWidthAnimation() { _widthAnimationCache = QPixmap(); if (!_a_show.animating()) { _scroll->show(); @@ -465,13 +562,14 @@ void DialogsWidget::stopWidthAnimation() { update(); } -void DialogsWidget::showFast() { +void Widget::showFast() { show(); updateForwardBar(); } -void DialogsWidget::showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms) { +void Widget::showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms) { _showDirection = direction; + _showAnimationType = ShowAnimation::External; _a_show.stop(); @@ -480,64 +578,63 @@ void DialogsWidget::showAnimated(Window::SlideDirection direction, const Window: updateForwardBar(); _cacheOver = App::main()->grabForShowAnimation(params); - _scroll->hide(); - _mainMenuToggle->hide(); - if (_forwardCancel) _forwardCancel->hide(); - _filter->hide(); - _cancelSearch->hide(anim::type::instant); - _jumpToDate->hide(anim::type::instant); - _chooseFromUser->hide(anim::type::instant); - _lockUnlock->hide(); + if (_updateTelegram) { + _updateTelegram->hide(); + } _connecting->setForceHidden(true); + startSlideAnimation(); +} + +void Widget::startSlideAnimation() { + _scroll->hide(); + if (_forwardCancel) { + _forwardCancel->hide(); + } + _searchControls->hide(); int delta = st::slideShift; if (_showDirection == Window::SlideDirection::FromLeft) { std::swap(_cacheUnder, _cacheOver); } - _a_show.start([this] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition()); + _a_show.start([=] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition()); } -bool DialogsWidget::wheelEventFromFloatPlayer(QEvent *e) { +bool Widget::wheelEventFromFloatPlayer(QEvent *e) { return _scroll->viewportEvent(e); } -QRect DialogsWidget::rectForFloatPlayer() const { +QRect Widget::rectForFloatPlayer() const { return mapToGlobal(_scroll->geometry()); } -void DialogsWidget::animationCallback() { +void Widget::animationCallback() { update(); if (!_a_show.animating()) { _cacheUnder = _cacheOver = QPixmap(); - _scroll->show(); - _mainMenuToggle->show(); - if (_forwardCancel) _forwardCancel->show(); - _filter->show(); - _connecting->setForceHidden(false); - updateLockUnlockVisibility(); - updateJumpToDateVisibility(true); - updateSearchFromVisibility(true); + updateControlsVisibility(true); applyFilterUpdate(); if (App::wnd()) App::wnd()->setInnerFocus(); } } -void DialogsWidget::onCancel() { - if (_inner->cancelFolder()) { +void Widget::onCancel() { + if (controller()->openedFolder().current()) { + controller()->closeFolder(); return; } - if (!onCancelSearch() || (!_searchInChat && !App::main()->selectingPeer())) { + if (!onCancelSearch() + || (!_searchInChat && !App::main()->selectingPeer())) { emit cancelled(); } } -void DialogsWidget::notify_historyMuteUpdated(History *history) { +void Widget::notify_historyMuteUpdated(History *history) { _inner->notify_historyMuteUpdated(history); } -void DialogsWidget::refreshLoadMoreButton(bool mayBlock, bool isBlocked) { +void Widget::refreshLoadMoreButton(bool mayBlock, bool isBlocked) { if (!mayBlock) { _loadMoreChats.destroy(); updateControlsGeometry(); @@ -560,7 +657,7 @@ void DialogsWidget::refreshLoadMoreButton(bool mayBlock, bool isBlocked) { _loadMoreChats->setText(loading ? "Loading..." : "Load more"); } -void DialogsWidget::loadMoreBlockedByDate() { +void Widget::loadMoreBlockedByDate() { if (!_loadMoreChats || _loadMoreChats->isDisabled() || _loadMoreChats->isHidden()) { @@ -569,7 +666,7 @@ void DialogsWidget::loadMoreBlockedByDate() { session().api().requestMoreBlockedByDateDialogs(); } -void DialogsWidget::onDraggingScrollDelta(int delta) { +void Widget::onDraggingScrollDelta(int delta) { _draggingScrollDelta = _scroll ? delta : 0; if (_draggingScrollDelta) { if (!_draggingScrollTimer) { @@ -583,12 +680,12 @@ void DialogsWidget::onDraggingScrollDelta(int delta) { } } -void DialogsWidget::onDraggingScrollTimer() { +void Widget::onDraggingScrollTimer() { auto delta = (_draggingScrollDelta > 0) ? qMin(_draggingScrollDelta * 3 / 20 + 1, int32(MaxScrollSpeed)) : qMax(_draggingScrollDelta * 3 / 20 - 1, -int32(MaxScrollSpeed)); _scroll->scrollToY(_scroll->scrollTop() + delta); } -bool DialogsWidget::onSearchMessages(bool searchCache) { +bool Widget::onSearchMessages(bool searchCache) { auto result = false; auto q = _filter->getLastText().trimmed(); if (q.isEmpty() && !_searchFromUser) { @@ -605,8 +702,8 @@ bool DialogsWidget::onSearchMessages(bool searchCache) { MTP::cancel(base::take(_searchRequest)); searchReceived( _searchInChat - ? DialogsSearchPeerFromStart - : DialogsSearchFromStart, + ? SearchRequestType::PeerFromStart + : SearchRequestType::FromStart, i.value(), 0); result = true; @@ -637,8 +734,8 @@ bool DialogsWidget::onSearchMessages(bool searchCache) { MTP_int(0), MTP_int(0), MTP_int(0)), - rpcDone(&DialogsWidget::searchReceived, DialogsSearchPeerFromStart), - rpcFail(&DialogsWidget::searchFailed, DialogsSearchPeerFromStart)); + rpcDone(&Widget::searchReceived, SearchRequestType::PeerFromStart), + rpcFail(&Widget::searchFailed, SearchRequestType::PeerFromStart)); //} else if (const auto feed = _searchInChat.feed()) { // #feed // _searchRequest = MTP::send( // MTPchannels_SearchFeed( @@ -648,8 +745,8 @@ bool DialogsWidget::onSearchMessages(bool searchCache) { // MTP_inputPeerEmpty(), // MTP_int(0), // MTP_int(SearchPerPage)), - // rpcDone(&DialogsWidget::searchReceived, DialogsSearchFromStart), - // rpcFail(&DialogsWidget::searchFailed, DialogsSearchFromStart)); + // rpcDone(&Widget::searchReceived, SearchRequestType::FromStart), + // rpcFail(&Widget::searchFailed, SearchRequestType::FromStart)); } else { _searchRequest = MTP::send( MTPmessages_SearchGlobal( @@ -658,8 +755,8 @@ bool DialogsWidget::onSearchMessages(bool searchCache) { MTP_inputPeerEmpty(), MTP_int(0), MTP_int(SearchPerPage)), - rpcDone(&DialogsWidget::searchReceived, DialogsSearchFromStart), - rpcFail(&DialogsWidget::searchFailed, DialogsSearchFromStart)); + rpcDone(&Widget::searchReceived, SearchRequestType::FromStart), + rpcFail(&Widget::searchFailed, SearchRequestType::FromStart)); } _searchQueries.insert(_searchRequest, _searchQuery); } @@ -679,8 +776,8 @@ bool DialogsWidget::onSearchMessages(bool searchCache) { MTPcontacts_Search( MTP_string(_peerSearchQuery), MTP_int(SearchPeopleLimit)), - rpcDone(&DialogsWidget::peerSearchReceived), - rpcFail(&DialogsWidget::peopleFailed)); + rpcDone(&Widget::peerSearchReceived), + rpcFail(&Widget::peopleFailed)); _peerSearchQueries.insert(_peerSearchRequest, _peerSearchQuery); } } else { @@ -697,30 +794,30 @@ bool DialogsWidget::onSearchMessages(bool searchCache) { return result; } -bool DialogsWidget::searchForPeersRequired(const QString &query) const { +bool Widget::searchForPeersRequired(const QString &query) const { if (_searchInChat || query.isEmpty()) { return false; } return (query[0] != '#'); } -void DialogsWidget::onNeedSearchMessages() { +void Widget::onNeedSearchMessages() { if (!onSearchMessages(true)) { _searchTimer.start(AutoSearchTimeout); } } -void DialogsWidget::onChooseByDrag() { +void Widget::onChooseByDrag() { _inner->chooseRow(); } -void DialogsWidget::showMainMenu() { +void Widget::showMainMenu() { App::wnd()->showMainMenu(); } -void DialogsWidget::searchMessages( +void Widget::searchMessages( const QString &query, - Dialogs::Key inChat) { + Key inChat) { auto inChatChanged = [&] { if (inChat == _searchInChat) { return false; @@ -746,7 +843,7 @@ void DialogsWidget::searchMessages( } } -void DialogsWidget::onSearchMore() { +void Widget::onSearchMore() { if (!_searchRequest) { if (!_searchFull) { auto offsetDate = _inner->lastSearchDate(); @@ -773,8 +870,8 @@ void DialogsWidget::onSearchMore() { MTP_int(0), MTP_int(0), MTP_int(0)), - rpcDone(&DialogsWidget::searchReceived, offsetId ? DialogsSearchPeerFromOffset : DialogsSearchPeerFromStart), - rpcFail(&DialogsWidget::searchFailed, offsetId ? DialogsSearchPeerFromOffset : DialogsSearchPeerFromStart)); + rpcDone(&Widget::searchReceived, offsetId ? SearchRequestType::PeerFromOffset : SearchRequestType::PeerFromStart), + rpcFail(&Widget::searchFailed, offsetId ? SearchRequestType::PeerFromOffset : SearchRequestType::PeerFromStart)); //} else if (const auto feed = _searchInChat.feed()) { // #feed // _searchRequest = MTP::send( // MTPchannels_SearchFeed( @@ -786,8 +883,8 @@ void DialogsWidget::onSearchMore() { // : MTP_inputPeerEmpty(), // MTP_int(offsetId), // MTP_int(SearchPerPage)), - // rpcDone(&DialogsWidget::searchReceived, offsetId ? DialogsSearchFromOffset : DialogsSearchFromStart), - // rpcFail(&DialogsWidget::searchFailed, offsetId ? DialogsSearchFromOffset : DialogsSearchFromStart)); + // rpcDone(&Widget::searchReceived, offsetId ? SearchRequestType::FromOffset : SearchRequestType::FromStart), + // rpcFail(&Widget::searchFailed, offsetId ? SearchRequestType::FromOffset : SearchRequestType::FromStart)); } else { _searchRequest = MTP::send( MTPmessages_SearchGlobal( @@ -798,8 +895,8 @@ void DialogsWidget::onSearchMore() { : MTP_inputPeerEmpty(), MTP_int(offsetId), MTP_int(SearchPerPage)), - rpcDone(&DialogsWidget::searchReceived, offsetId ? DialogsSearchFromOffset : DialogsSearchFromStart), - rpcFail(&DialogsWidget::searchFailed, offsetId ? DialogsSearchFromOffset : DialogsSearchFromStart)); + rpcDone(&Widget::searchReceived, offsetId ? SearchRequestType::FromOffset : SearchRequestType::FromStart), + rpcFail(&Widget::searchFailed, offsetId ? SearchRequestType::FromOffset : SearchRequestType::FromStart)); } if (!offsetId) { _searchQueries.insert(_searchRequest, _searchQuery); @@ -826,20 +923,19 @@ void DialogsWidget::onSearchMore() { MTP_int(0), MTP_int(0), MTP_int(0)), - rpcDone(&DialogsWidget::searchReceived, offsetMigratedId ? DialogsSearchMigratedFromOffset : DialogsSearchMigratedFromStart), - rpcFail(&DialogsWidget::searchFailed, offsetMigratedId ? DialogsSearchMigratedFromOffset : DialogsSearchMigratedFromStart)); + rpcDone(&Widget::searchReceived, offsetMigratedId ? SearchRequestType::MigratedFromOffset : SearchRequestType::MigratedFromStart), + rpcFail(&Widget::searchFailed, offsetMigratedId ? SearchRequestType::MigratedFromOffset : SearchRequestType::MigratedFromStart)); } } } -void DialogsWidget::searchReceived( - DialogsSearchRequestType type, +void Widget::searchReceived( + SearchRequestType type, const MTPmessages_Messages &result, mtpRequestId requestId) { - using State = DialogsInner::State; const auto state = _inner->state(); - if (state == State::Filtered) { - if (type == DialogsSearchFromStart || type == DialogsSearchPeerFromStart) { + if (state == WidgetState::Filtered) { + if (type == SearchRequestType::FromStart || type == SearchRequestType::PeerFromStart) { auto i = _searchQueries.find(requestId); if (i != _searchQueries.cend()) { _searchCache[i.value()] = result; @@ -859,7 +955,7 @@ void DialogsWidget::searchReceived( } auto &msgs = d.vmessages.v; if (!_inner->searchReceived(msgs, type, msgs.size())) { - if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + if (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset) { _searchFullMigrated = true; } else { _searchFull = true; @@ -876,7 +972,7 @@ void DialogsWidget::searchReceived( } auto &msgs = d.vmessages.v; if (!_inner->searchReceived(msgs, type, d.vcount.v)) { - if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + if (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset) { _searchFullMigrated = true; } else { _searchFull = true; @@ -892,12 +988,12 @@ void DialogsWidget::searchReceived( } else { LOG(("API Error: " "received messages.channelMessages when no channel " - "was passed! (DialogsWidget::searchReceived)")); + "was passed! (Widget::searchReceived)")); } } else { LOG(("API Error: " "received messages.channelMessages when no channel " - "was passed! (DialogsWidget::searchReceived)")); + "was passed! (Widget::searchReceived)")); } if (_searchRequest != 0) { // Don't apply cached data! @@ -906,7 +1002,7 @@ void DialogsWidget::searchReceived( } auto &msgs = d.vmessages.v; if (!_inner->searchReceived(msgs, type, d.vcount.v)) { - if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + if (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset) { _searchFullMigrated = true; } else { _searchFull = true; @@ -915,8 +1011,8 @@ void DialogsWidget::searchReceived( } break; case mtpc_messages_messagesNotModified: { - LOG(("API Error: received messages.messagesNotModified! (DialogsWidget::searchReceived)")); - if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + LOG(("API Error: received messages.messagesNotModified! (Widget::searchReceived)")); + if (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset) { _searchFullMigrated = true; } else { _searchFull = true; @@ -930,13 +1026,12 @@ void DialogsWidget::searchReceived( } } -void DialogsWidget::peerSearchReceived( +void Widget::peerSearchReceived( const MTPcontacts_Found &result, mtpRequestId requestId) { - using State = DialogsInner::State; const auto state = _inner->state(); auto q = _peerSearchQuery; - if (state == State::Filtered) { + if (state == WidgetState::Filtered) { auto i = _peerSearchQueries.find(requestId); if (i != _peerSearchQueries.cend()) { q = i.value(); @@ -959,15 +1054,15 @@ void DialogsWidget::peerSearchReceived( } } -bool DialogsWidget::searchFailed( - DialogsSearchRequestType type, +bool Widget::searchFailed( + SearchRequestType type, const RPCError &error, mtpRequestId requestId) { if (MTP::isDefaultHandledError(error)) return false; if (_searchRequest == requestId) { _searchRequest = 0; - if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) { + if (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset) { _searchFullMigrated = true; } else { _searchFull = true; @@ -976,7 +1071,7 @@ bool DialogsWidget::searchFailed( return true; } -bool DialogsWidget::peopleFailed(const RPCError &error, mtpRequestId req) { +bool Widget::peopleFailed(const RPCError &error, mtpRequestId req) { if (MTP::isDefaultHandledError(error)) return false; if (_peerSearchRequest == req) { @@ -986,7 +1081,7 @@ bool DialogsWidget::peopleFailed(const RPCError &error, mtpRequestId req) { return true; } -void DialogsWidget::dragEnterEvent(QDragEnterEvent *e) { +void Widget::dragEnterEvent(QDragEnterEvent *e) { using namespace Storage; if (App::main()->selectingPeer()) return; @@ -1007,7 +1102,7 @@ void DialogsWidget::dragEnterEvent(QDragEnterEvent *e) { _chooseByDragTimer.stop(); } -void DialogsWidget::dragMoveEvent(QDragMoveEvent *e) { +void Widget::dragMoveEvent(QDragMoveEvent *e) { if (_scroll->geometry().contains(e->pos())) { if (_dragForward) { updateDragInScroll(true); @@ -1027,7 +1122,7 @@ void DialogsWidget::dragMoveEvent(QDragMoveEvent *e) { e->accept(); } -void DialogsWidget::dragLeaveEvent(QDragLeaveEvent *e) { +void Widget::dragLeaveEvent(QDragLeaveEvent *e) { if (_dragForward) { updateDragInScroll(false); } else { @@ -1037,7 +1132,7 @@ void DialogsWidget::dragLeaveEvent(QDragLeaveEvent *e) { e->accept(); } -void DialogsWidget::updateDragInScroll(bool inScroll) { +void Widget::updateDragInScroll(bool inScroll) { if (_dragInScroll != inScroll) { _dragInScroll = inScroll; if (_dragInScroll) { @@ -1048,7 +1143,7 @@ void DialogsWidget::updateDragInScroll(bool inScroll) { } } -void DialogsWidget::dropEvent(QDropEvent *e) { +void Widget::dropEvent(QDropEvent *e) { _chooseByDragTimer.stop(); if (_scroll->geometry().contains(e->pos())) { if (auto peer = _inner->updateFromParentDrag(mapToGlobal(e->pos()))) { @@ -1059,7 +1154,7 @@ void DialogsWidget::dropEvent(QDropEvent *e) { } } -void DialogsWidget::onListScroll() { +void Widget::onListScroll() { const auto scrollTop = _scroll->scrollTop(); _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); updateScrollUpVisibility(); @@ -1068,7 +1163,7 @@ void DialogsWidget::onListScroll() { _scrollToTop->update(); } -void DialogsWidget::applyFilterUpdate(bool force) { +void Widget::applyFilterUpdate(bool force) { if (_a_show.animating() && !force) { return; } @@ -1079,10 +1174,7 @@ void DialogsWidget::applyFilterUpdate(bool force) { clearSearchCache(); } _cancelSearch->toggle(!filterText.isEmpty(), anim::type::normal); - if (_loadMoreChats) { - _loadMoreChats->setVisible(filterText.isEmpty()); - updateControlsGeometry(); - } + updateLoadMoreChatsVisibility(); updateJumpToDateVisibility(); if (filterText.isEmpty()) { @@ -1102,13 +1194,13 @@ void DialogsWidget::applyFilterUpdate(bool force) { _lastFilterText = filterText; } -void DialogsWidget::searchInChat(Dialogs::Key chat) { +void Widget::searchInChat(Key chat) { onCancelSearch(); setSearchInChat(chat); applyFilterUpdate(true); } -void DialogsWidget::setSearchInChat(Dialogs::Key chat, UserData *from) { +void Widget::setSearchInChat(Key chat, UserData *from) { _searchInMigrated = nullptr; if (const auto peer = chat.peer()) { if (const auto migrateTo = peer->migrateTo()) { @@ -1138,7 +1230,7 @@ void DialogsWidget::setSearchInChat(Dialogs::Key chat, UserData *from) { _filter->setFocus(); } -void DialogsWidget::clearSearchCache() { +void Widget::clearSearchCache() { _searchCache.clear(); _searchQueries.clear(); _searchQuery = QString(); @@ -1146,16 +1238,16 @@ void DialogsWidget::clearSearchCache() { MTP::cancel(base::take(_searchRequest)); } -void DialogsWidget::showJumpToDate() { +void Widget::showJumpToDate() { if (_searchInChat) { this->controller()->showJumpToDate(_searchInChat, QDate()); } } -void DialogsWidget::showSearchFrom() { +void Widget::showSearchFrom() { if (const auto peer = _searchInChat.peer()) { const auto chat = _searchInChat; - Dialogs::ShowSearchFromBox( + ShowSearchFromBox( controller(), peer, crl::guard(this, [=](not_null user) { @@ -1167,7 +1259,7 @@ void DialogsWidget::showSearchFrom() { } } -void DialogsWidget::onFilterCursorMoved(int from, int to) { +void Widget::onFilterCursorMoved(int from, int to) { if (to < 0) to = _filter->cursorPosition(); QString t = _filter->getLastText(); QStringRef r; @@ -1183,7 +1275,7 @@ void DialogsWidget::onFilterCursorMoved(int from, int to) { _inner->onHashtagFilterUpdate(r); } -void DialogsWidget::onCompleteHashtag(QString tag) { +void Widget::onCompleteHashtag(QString tag) { QString t = _filter->getLastText(), r; int cur = _filter->cursorPosition(); for (int start = cur; start > 0;) { @@ -1210,18 +1302,34 @@ void DialogsWidget::onCompleteHashtag(QString tag) { applyFilterUpdate(true); } -void DialogsWidget::resizeEvent(QResizeEvent *e) { +void Widget::resizeEvent(QResizeEvent *e) { updateControlsGeometry(); } -void DialogsWidget::updateLockUnlockVisibility() { - if (!_a_show.animating()) { - _lockUnlock->setVisible(Global::LocalPasscode()); +void Widget::updateLockUnlockVisibility() { + if (_a_show.animating()) { + return; + } + const auto hidden = !Global::LocalPasscode(); + if (_lockUnlock->isHidden() != hidden) { + _lockUnlock->setVisible(!hidden); + updateControlsGeometry(); } - updateControlsGeometry(); } -void DialogsWidget::updateJumpToDateVisibility(bool fast) { +void Widget::updateLoadMoreChatsVisibility() { + if (_a_show.animating() || !_loadMoreChats) { + return; + } + const auto hidden = (_openedFolder != nullptr) + || !_filter->getLastText().isEmpty(); + if (_loadMoreChats->isHidden() != hidden) { + _loadMoreChats->setVisible(!hidden); + updateControlsGeometry(); + } +} + +void Widget::updateJumpToDateVisibility(bool fast) { if (_a_show.animating()) return; _jumpToDate->toggle( @@ -1229,7 +1337,7 @@ void DialogsWidget::updateJumpToDateVisibility(bool fast) { fast ? anim::type::instant : anim::type::normal); } -void DialogsWidget::updateSearchFromVisibility(bool fast) { +void Widget::updateSearchFromVisibility(bool fast) { auto visible = [&] { if (const auto peer = _searchInChat.peer()) { if (peer->isChat() || peer->isMegagroup()) { @@ -1251,7 +1359,7 @@ void DialogsWidget::updateSearchFromVisibility(bool fast) { } } -void DialogsWidget::updateControlsGeometry() { +void Widget::updateControlsGeometry() { auto filterAreaTop = 0; if (_forwardCancel) { _forwardCancel->moveToLeft(0, filterAreaTop); @@ -1263,13 +1371,15 @@ void DialogsWidget::updateControlsGeometry() { auto filterRight = (Global::LocalPasscode() ? (st::dialogsFilterPadding.x() + _lockUnlock->width()) : st::dialogsFilterSkip) + st::dialogsFilterPadding.x(); auto filterWidth = qMax(width(), st::columnMinimalWidthLeft) - filterLeft - filterRight; auto filterAreaHeight = st::dialogsFilterPadding.y() + _mainMenuToggle->height() + st::dialogsFilterPadding.y(); - auto filterTop = filterAreaTop + (filterAreaHeight - _filter->height()) / 2; + _searchControls->setGeometry(0, filterAreaTop, width(), filterAreaHeight); + + auto filterTop = (filterAreaHeight - _filter->height()) / 2; filterLeft = anim::interpolate(filterLeft, smallLayoutWidth, smallLayoutRatio); _filter->setGeometryToLeft(filterLeft, filterTop, filterWidth, _filter->height()); auto mainMenuLeft = anim::interpolate(st::dialogsFilterPadding.x(), (smallLayoutWidth - _mainMenuToggle->width()) / 2, smallLayoutRatio); - _mainMenuToggle->moveToLeft(mainMenuLeft, filterAreaTop + st::dialogsFilterPadding.y()); + _mainMenuToggle->moveToLeft(mainMenuLeft, st::dialogsFilterPadding.y()); auto right = filterLeft + filterWidth; - _lockUnlock->moveToLeft(right + st::dialogsFilterPadding.x(), filterAreaTop + st::dialogsFilterPadding.y()); + _lockUnlock->moveToLeft(right + st::dialogsFilterPadding.x(), st::dialogsFilterPadding.y()); _cancelSearch->moveToLeft(right - _cancelSearch->width(), _filter->y()); right -= _jumpToDate->width(); _jumpToDate->moveToLeft(right, _filter->y()); right -= _chooseFromUser->width(); _chooseFromUser->moveToLeft(right, _filter->y()); @@ -1307,7 +1417,7 @@ void DialogsWidget::updateControlsGeometry() { } } -void DialogsWidget::updateForwardBar() { +void Widget::updateForwardBar() { auto selecting = App::main()->selectingPeer(); auto oneColumnSelecting = (Adaptive::OneColumn() && selecting); if (!oneColumnSelecting == !_forwardCancel) { @@ -1324,15 +1434,18 @@ void DialogsWidget::updateForwardBar() { update(); } -void DialogsWidget::keyPressEvent(QKeyEvent *e) { +void Widget::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape) { - e->ignore(); + if (_openedFolder) { + controller()->closeFolder(); + } else { + e->ignore(); + } } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { if (!_inner->chooseRow()) { - using State = DialogsInner::State; const auto state = _inner->state(); - if (state == State::Default - || (state == State::Filtered + if (state == WidgetState::Default + || (state == WidgetState::Filtered && (!_inner->waitingForSearch() || _inner->hasFilteredResults()))) { _inner->selectSkip(1); _inner->chooseRow(); @@ -1353,7 +1466,7 @@ void DialogsWidget::keyPressEvent(QKeyEvent *e) { } } -void DialogsWidget::paintEvent(QPaintEvent *e) { +void Widget::paintEvent(QPaintEvent *e) { if (App::wnd() && App::wnd()->contentOverlapped(this, e)) return; Painter p(this); @@ -1363,20 +1476,23 @@ void DialogsWidget::paintEvent(QPaintEvent *e) { } auto progress = _a_show.value(1.); if (_a_show.animating()) { + const auto top = (_showAnimationType == ShowAnimation::Internal) + ? (_forwardCancel ? _forwardCancel->height() : 0) + : 0; 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, _cacheUnder.height() / retina), _cacheUnder, QRect(-coordUnder * retina, 0, coordOver * retina, _cacheUnder.height())); + p.drawPixmap(QRect(0, top, coordOver, _cacheUnder.height() / retina), _cacheUnder, QRect(-coordUnder * retina, 0, coordOver * retina, _cacheUnder.height())); p.setOpacity(shadow); - p.fillRect(0, 0, coordOver, _cacheUnder.height() / retina, st::slideFadeOutBg); + p.fillRect(0, top, coordOver, _cacheUnder.height() / retina, st::slideFadeOutBg); p.setOpacity(1); } - p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, _cacheOver.height() / retina), _cacheOver, QRect(0, 0, _cacheOver.width(), _cacheOver.height())); + p.drawPixmap(QRect(coordOver, top, _cacheOver.width() / retina, _cacheOver.height() / retina), _cacheOver, QRect(0, 0, _cacheOver.width(), _cacheOver.height())); p.setOpacity(shadow); - st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), _cacheOver.height() / retina)); + st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), top, st::slideShadow.width(), _cacheOver.height() / retina)); return; } auto aboveTop = 0; @@ -1404,15 +1520,15 @@ void DialogsWidget::paintEvent(QPaintEvent *e) { } } -void DialogsWidget::scrollToEntry(const Dialogs::RowDescriptor &entry) { +void Widget::scrollToEntry(const RowDescriptor &entry) { _inner->scrollToEntry(entry); } -void DialogsWidget::removeDialog(Dialogs::Key key) { +void Widget::removeDialog(Key key) { _inner->removeDialog(key); } -bool DialogsWidget::onCancelSearch() { +bool Widget::onCancelSearch() { bool clearing = !_filter->getLastText().isEmpty(); if (_searchRequest) { MTP::cancel(_searchRequest); @@ -1428,7 +1544,7 @@ bool DialogsWidget::onCancelSearch() { Unexpected("Empty key in onCancelSearch()."); } } - setSearchInChat(Dialogs::Key()); + setSearchInChat(Key()); clearing = true; } _inner->clearFilter(); @@ -1438,7 +1554,7 @@ bool DialogsWidget::onCancelSearch() { return clearing; } -void DialogsWidget::onCancelSearchInChat() { +void Widget::onCancelSearchInChat() { if (_searchRequest) { MTP::cancel(_searchRequest); _searchRequest = 0; @@ -1453,7 +1569,7 @@ void DialogsWidget::onCancelSearchInChat() { Unexpected("Empty key in onCancelSearchInPeer()."); } } - setSearchInChat(Dialogs::Key()); + setSearchInChat(Key()); } _inner->clearFilter(); _filter->clear(); @@ -1464,11 +1580,13 @@ void DialogsWidget::onCancelSearchInChat() { } } -void DialogsWidget::onDialogMoved(int movedFrom, int movedTo) { +void Widget::onDialogMoved(int movedFrom, int movedTo) { int32 st = _scroll->scrollTop(); if (st > movedTo && st < movedFrom) { _scroll->scrollToY(st + st::dialogsRowHeight); } } -DialogsWidget::~DialogsWidget() = default; +Widget::~Widget() = default; + +} // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index 009b5e23a6..cd20691bb0 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -13,16 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_key.h" #include "ui/special_buttons.h" -class DialogsInner; class AuthSession; -namespace Dialogs { -struct RowDescriptor; -class Row; -class FakeRow; -class Key; -} // namespace Dialogs - namespace Ui { class IconButton; class PopupMenu; @@ -39,29 +31,30 @@ class Controller; class ConnectionState; } // namespace Window -enum DialogsSearchRequestType { - DialogsSearchFromStart, - DialogsSearchFromOffset, - DialogsSearchPeerFromStart, - DialogsSearchPeerFromOffset, - DialogsSearchMigratedFromStart, - DialogsSearchMigratedFromOffset, -}; +namespace Dialogs { -class DialogsWidget : public Window::AbstractSectionWidget, public RPCSender { +struct RowDescriptor; +class Row; +class FakeRow; +class Key; +struct ChosenRow; +class InnerWidget; +enum class SearchRequestType; + +class Widget : public Window::AbstractSectionWidget, public RPCSender { Q_OBJECT public: - DialogsWidget(QWidget *parent, not_null controller); + Widget(QWidget *parent, not_null controller); void updateDragInScroll(bool inScroll); - void searchInChat(Dialogs::Key chat); + void searchInChat(Key chat); - void refreshDialog(Dialogs::Key key); - void removeDialog(Dialogs::Key key); - void repaintDialogRow(Dialogs::Mode list, not_null row); - void repaintDialogRow(Dialogs::RowDescriptor row); + void refreshDialog(Key key); + void removeDialog(Key key); + void repaintDialogRow(Mode list, not_null row); + void repaintDialogRow(RowDescriptor row); void jumpToTop(); @@ -74,9 +67,9 @@ public: void showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms); void showFast(); - void scrollToEntry(const Dialogs::RowDescriptor &entry); + void scrollToEntry(const RowDescriptor &entry); - void searchMessages(const QString &query, Dialogs::Key inChat = {}); + void searchMessages(const QString &query, Key inChat = {}); void onSearchMore(); // Float player interface. @@ -85,7 +78,7 @@ public: void notify_historyMuteUpdated(History *history); - ~DialogsWidget(); + ~Widget(); signals: void cancelled(); @@ -121,9 +114,14 @@ protected: void paintEvent(QPaintEvent *e) override; private: + enum class ShowAnimation { + External, + Internal, + }; + void animationCallback(); void searchReceived( - DialogsSearchRequestType type, + SearchRequestType type, const MTPmessages_Messages &result, mtpRequestId requestId); void peerSearchReceived( @@ -133,59 +131,67 @@ private: void setupSupportMode(); void setupConnectingWidget(); bool searchForPeersRequired(const QString &query) const; - void setSearchInChat(Dialogs::Key chat, UserData *from = nullptr); + void setSearchInChat(Key chat, UserData *from = nullptr); void showJumpToDate(); void showSearchFrom(); void showMainMenu(); void clearSearchCache(); + void updateControlsVisibility(bool fast = false); void updateLockUnlockVisibility(); + void updateLoadMoreChatsVisibility(); void updateJumpToDateVisibility(bool fast = false); void updateSearchFromVisibility(bool fast = false); void updateControlsGeometry(); void updateForwardBar(); void checkUpdateStatus(); + void changeOpenedFolder(Data::Folder *folder, anim::type animated); + QPixmap grabForFolderSlideAnimation(); + void startSlideAnimation(); void applyFilterUpdate(bool force = false); void refreshLoadMoreButton(bool mayBlock, bool isBlocked); void loadMoreBlockedByDate(); - bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req); + bool searchFailed(SearchRequestType type, const RPCError &error, mtpRequestId req); bool peopleFailed(const RPCError &error, mtpRequestId req); - bool _dragInScroll = false; - bool _dragForward = false; - QTimer _chooseByDragTimer; - - object_ptr _forwardCancel = { nullptr }; - object_ptr _mainMenuToggle; - object_ptr _filter; - object_ptr> _chooseFromUser; - object_ptr> _jumpToDate; - object_ptr _cancelSearch; - object_ptr _lockUnlock; - object_ptr _scroll; - QPointer _inner; - class BottomButton; - object_ptr _updateTelegram = { nullptr }; - object_ptr _loadMoreChats = { nullptr }; - std::unique_ptr _connecting; - - Ui::Animations::Simple _scrollToAnimation; - Ui::Animations::Simple _a_show; - Window::SlideDirection _showDirection; - QPixmap _cacheUnder, _cacheOver; - - Ui::Animations::Simple _scrollToTopShown; - bool _scrollToTopIsShown = false; - object_ptr _scrollToTop; - void scrollToTop(); void setupScrollUpButton(); void updateScrollUpVisibility(); void startScrollUpButtonAnimation(bool shown); void updateScrollUpPosition(); - Dialogs::Key _searchInChat; + bool _dragInScroll = false; + bool _dragForward = false; + QTimer _chooseByDragTimer; + + object_ptr _forwardCancel = { nullptr }; + object_ptr _searchControls; + object_ptr _mainMenuToggle; + object_ptr _filter; + object_ptr> _chooseFromUser; + object_ptr> _jumpToDate; + object_ptr _cancelSearch; + object_ptr _lockUnlock; + object_ptr _scroll; + QPointer _inner; + class BottomButton; + object_ptr _updateTelegram = { nullptr }; + object_ptr _loadMoreChats = { nullptr }; + std::unique_ptr _connecting; + + Ui::Animations::Simple _scrollToAnimation; + Ui::Animations::Simple _a_show; + Window::SlideDirection _showDirection = Window::SlideDirection(); + QPixmap _cacheUnder, _cacheOver; + ShowAnimation _showAnimationType = ShowAnimation::External; + + Ui::Animations::Simple _scrollToTopShown; + bool _scrollToTopIsShown = false; + object_ptr _scrollToTop; + + Data::Folder *_openedFolder = nullptr; + Key _searchInChat; History *_searchInMigrated = nullptr; UserData *_searchFromUser = nullptr; QString _lastFilterText; @@ -220,3 +226,5 @@ private: int _draggingScrollDelta = 0; }; + +} // namespace Dialogs diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index b055f255a7..b4e571f6a7 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -18,7 +18,6 @@ class AuthSession; struct HistoryMessageMarkupButton; class MainWindow; class ConfirmBox; -class DialogsWidget; class HistoryWidget; class StackItem; struct FileLoadResult; @@ -35,6 +34,7 @@ namespace Dialogs { struct RowDescriptor; class Row; class Key; +class Widget; } // namespace Dialogs namespace Media { @@ -459,7 +459,7 @@ private: object_ptr _thirdShadow = { nullptr }; object_ptr _firstColumnResizeArea = { nullptr }; object_ptr _thirdColumnResizeArea = { nullptr }; - object_ptr _dialogs; + object_ptr _dialogs; object_ptr _history; object_ptr _mainSection = { nullptr }; object_ptr _thirdSection = { nullptr }; diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.cpp b/Telegram/SourceFiles/ui/widgets/input_fields.cpp index 54444826ff..cd94847a18 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.cpp +++ b/Telegram/SourceFiles/ui/widgets/input_fields.cpp @@ -997,6 +997,11 @@ QRect FlatInput::getTextRect() const { return rect().marginsRemoved(_textMrg + QMargins(-2, -1, -2, -1)); } +void FlatInput::finishAnimations() { + _placeholderFocusedAnimation.stop(); + _placeholderVisibleAnimation.stop(); +} + void FlatInput::paintEvent(QPaintEvent *e) { Painter p(this); diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.h b/Telegram/SourceFiles/ui/widgets/input_fields.h index e8c04fe4e1..29d1586f6a 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.h +++ b/Telegram/SourceFiles/ui/widgets/input_fields.h @@ -56,6 +56,8 @@ public: void setPlaceholder(Fn placeholderFactory); QRect placeholderRect() const; + void finishAnimations(); + void setTextMrg(const QMargins &textMrg); QRect getTextRect() const; diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index a5f5bd1d4b..9d2778746b 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -108,6 +108,16 @@ Controller::Controller( Ui::show(Box(peer)); } }); + + session->data().chatsListChanges( + ) | rpl::filter([=](Data::Folder *folder) { + return (folder != nullptr) + && (folder == _openedFolder.current()) + && folder->chatsList()->indexed(Global::DialogsMode())->empty(); + }) | rpl::start_with_next([=](Data::Folder *folder) { + folder->updateChatListSortPosition(); + closeFolder(); + }, lifetime()); } void Controller::showEditPeerBox(PeerData *peer) { @@ -137,6 +147,24 @@ void Controller::initSupportMode() { }, lifetime()); } +bool Controller::uniqueChatsInSearchResults() const { + return session().supportMode() + && !session().settings().supportAllSearchResults() + && !searchInChat.current(); +} + +void Controller::openFolder(not_null folder) { + _openedFolder = folder.get(); +} + +void Controller::closeFolder() { + _openedFolder = nullptr; +} + +const rpl::variable &Controller::openedFolder() const { + return _openedFolder; +} + void Controller::setActiveChatEntry(Dialogs::RowDescriptor row) { _activeChatEntry = row; if (session().supportMode()) { diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h index 14c3ad7547..2896f4cade 100644 --- a/Telegram/SourceFiles/window/window_controller.h +++ b/Telegram/SourceFiles/window/window_controller.h @@ -150,8 +150,12 @@ public: } // This is needed for History TopBar updating when searchInChat - // is changed in the DialogsWidget of the current window. + // is changed in the Dialogs::Widget of the current window. rpl::variable searchInChat; + bool uniqueChatsInSearchResults() const; + void openFolder(not_null folder); + void closeFolder(); + const rpl::variable &openedFolder() const; void setActiveChatEntry(Dialogs::RowDescriptor row); void setActiveChatEntry(Dialogs::Key key); @@ -304,6 +308,7 @@ private: Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr; PeerData *_showEditPeer = nullptr; + rpl::variable _openedFolder; rpl::lifetime _lifetime;