diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 6767c52f9..bae1e94e7 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -64,6 +64,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_controller.h" #include "window/window_session_controller.h" #include "window/window_peer_menu.h" +#include "ui/effects/loading_element.h" #include "ui/widgets/multi_select.h" #include "ui/widgets/menu/menu_add_action_callback_factory.h" #include "ui/empty_userpic.h" @@ -936,7 +937,17 @@ void InnerWidget::paintEvent(QPaintEvent *e) { } const auto showUnreadInSearchResults = uniqueSearchResults(); - if (!_searchResults.empty()) { + if (_searchResults.empty()) { + if (_loadingAnimation) { + const auto text = tr::lng_contacts_loading(tr::now); + p.fillRect(0, 0, fullWidth, st::searchedBarHeight, st::searchedBarBg); + p.setFont(st::searchedBarFont); + p.setPen(st::searchedBarFg); + p.drawTextLeft(st::searchedBarPosition.x(), st::searchedBarPosition.y(), width(), text); + p.translate(0, st::searchedBarHeight); + top += st::searchedBarHeight; + } + } else { const auto text = showUnreadInSearchResults ? u"Search results"_q : tr::lng_search_found_results( @@ -1442,7 +1453,7 @@ void InnerWidget::selectByMouse(QPoint globalPosition) { updateSelectedRow(); } } - if (!_waitingForSearch && !_searchResults.empty()) { + if (!_searchResults.empty()) { auto skip = searchedOffset(); auto searchedSelected = (mouseY >= skip) ? ((mouseY - skip) / _st->height) : -1; if (searchedSelected < 0 || searchedSelected >= _searchResults.size()) { @@ -2602,7 +2613,6 @@ void InnerWidget::applySearchState(SearchState state) { clearFilter(); } else { setState(WidgetState::Filtered); - _waitingForSearch = true; _filterResults.clear(); _filterResultsGlobal.clear(); const auto append = [&](not_null list) { @@ -2986,13 +2996,6 @@ void InnerWidget::searchReceived( } else { _searchedCount = fullCount; } - if (_waitingForSearch - && (!_searchResults.empty() - || !_searchInMigrated - || type == SearchRequestType::MigratedFromStart - || type == SearchRequestType::MigratedFromOffset)) { - _waitingForSearch = false; - } refresh(); } @@ -3090,8 +3093,8 @@ void InnerWidget::refresh(bool toTop) { h = searchedOffset() + st::recentPeersEmptyHeightMin; _searchEmpty->setMinimalHeight(st::recentPeersEmptyHeightMin); _searchEmpty->move(0, h - st::recentPeersEmptyHeightMin); - } else if (_waitingForSearch) { - h = searchedOffset() + (_searchResults.size() * _st->height) + ((_searchResults.empty() && !_searchState.inChat) ? -st::searchedBarHeight : 0); + } else if (_loadingAnimation) { + h = searchedOffset() + _loadingAnimation->height(); } else { h = searchedOffset() + (_searchResults.size() * _st->height); } @@ -3127,8 +3130,21 @@ void InnerWidget::refreshEmpty() { } else if (_searchEmpty) { _searchEmpty->show(); } + + if (!_searchLoading || !empty) { + _loadingAnimation.destroy(); + } else if (!_loadingAnimation) { + _loadingAnimation = Ui::CreateLoadingDialogRowWidget( + this, + *_st, + 2); + _loadingAnimation->resizeToWidth(width()); + _loadingAnimation->move(0, searchedOffset()); + _loadingAnimation->show(); + } } else { _searchEmpty.destroy(); + _loadingAnimation.destroy(); } const auto data = &session().data(); @@ -3207,6 +3223,10 @@ void InnerWidget::resizeEmpty() { _searchEmpty->resizeToWidth(width()); _searchEmpty->move(0, searchedOffset()); } + if (_loadingAnimation) { + _loadingAnimation->resizeToWidth(width()); + _loadingAnimation->move(0, searchedOffset()); + } } void InnerWidget::clearMouseSelection(bool clearSelection) { @@ -3269,7 +3289,6 @@ void InnerWidget::clearFilter() { if (_state == WidgetState::Filtered || _searchState.inChat) { if (_searchState.inChat) { setState(WidgetState::Filtered); - _waitingForSearch = true; } else { setState(WidgetState::Default); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index a7e3ae619..b41a4aeb3 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -141,9 +141,6 @@ public: [[nodiscard]] not_null st() const { return _st; } - [[nodiscard]] bool waitingForSearch() const { - return _waitingForSearch; - } [[nodiscard]] bool hasFilteredResults() const; void applySearchState(SearchState state); @@ -467,7 +464,6 @@ private: int _filteredSelected = -1; int _filteredPressed = -1; - bool _waitingForSearch = false; EmptyState _emptyState = EmptyState::None; QString _peerSearchQuery; @@ -485,6 +481,7 @@ private: WidgetState _state = WidgetState::Default; + object_ptr _loadingAnimation = { nullptr }; object_ptr _searchEmpty = { nullptr }; SearchState _searchEmptyState; object_ptr _empty = { nullptr }; diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 67155eb3d..fa1c71a5f 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -448,7 +448,7 @@ Widget::Widget( _inner->setLoadMoreCallback([=] { const auto state = _inner->state(); if (state == WidgetState::Filtered - && (!_inner->waitingForSearch() + && (!_searchFull || (_searchInMigrated && _searchFull && !_searchFullMigrated))) { @@ -1936,7 +1936,7 @@ void Widget::submit() { const auto state = _inner->state(); if (state == WidgetState::Default || (state == WidgetState::Filtered - && (!_inner->waitingForSearch() || _inner->hasFilteredResults()))) { + && _inner->hasFilteredResults())) { _inner->selectSkip(1); _inner->chooseRow(); } else { diff --git a/Telegram/SourceFiles/ui/effects/loading_element.cpp b/Telegram/SourceFiles/ui/effects/loading_element.cpp index 5e30157c2..5cc2e5e90 100644 --- a/Telegram/SourceFiles/ui/effects/loading_element.cpp +++ b/Telegram/SourceFiles/ui/effects/loading_element.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rect.h" #include "ui/rp_widget.h" #include "styles/style_basic.h" +#include "styles/style_dialogs.h" #include "styles/style_widgets.h" namespace Ui { @@ -63,10 +64,28 @@ void LoadingText::paint(QPainter &p, int width) { h / 2); } +[[nodiscard]] const style::PeerListItem &PeerListItemFromDialogRow( + rpl::lifetime &lifetime, + const style::DialogRow &st) { + using namespace style; + const auto item = lifetime.make_state(PeerListItem{ + .height = st.height, + .photoPosition = QPoint(st.padding.left(), st.padding.top()), + .namePosition = QPoint(st.nameLeft, st.nameTop), + .nameStyle = st::semiboldTextStyle, + .statusPosition = QPoint(st.textLeft, st.textTop), + .photoSize = st.photoSize, + }); + return *item; +} + class LoadingPeerListItem final : public LoadingElement { public: LoadingPeerListItem(const style::PeerListItem &st) : _st(st) { } + LoadingPeerListItem(const style::DialogRow &st) + : _st(PeerListItemFromDialogRow(_lifetime, st)) { + } [[nodiscard]] int height() const override { return _st.height; @@ -114,6 +133,7 @@ public: } private: + rpl::lifetime _lifetime; const style::PeerListItem &_st; }; @@ -220,4 +240,15 @@ object_ptr CreateLoadingPeerListItemWidget( st); } +object_ptr CreateLoadingDialogRowWidget( + not_null parent, + const style::DialogRow &st, + int lines) { + return CreateLoadingElementWidget( + parent, + lines, + rpl::single(false), + st); +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/effects/loading_element.h b/Telegram/SourceFiles/ui/effects/loading_element.h index ab3b0d17e..757250f0a 100644 --- a/Telegram/SourceFiles/ui/effects/loading_element.h +++ b/Telegram/SourceFiles/ui/effects/loading_element.h @@ -13,6 +13,7 @@ class object_ptr; namespace style { struct FlatLabel; struct PeerListItem; +struct DialogRow; } // namespace style namespace Ui { @@ -30,4 +31,9 @@ object_ptr CreateLoadingPeerListItemWidget( const style::PeerListItem &st, int lines); +object_ptr CreateLoadingDialogRowWidget( + not_null parent, + const style::DialogRow &st, + int lines); + } // namespace Ui