diff --git a/Telegram/SourceFiles/history/history_search_controller.cpp b/Telegram/SourceFiles/history/history_search_controller.cpp index 9f52087fb..55ebea5b1 100644 --- a/Telegram/SourceFiles/history/history_search_controller.cpp +++ b/Telegram/SourceFiles/history/history_search_controller.cpp @@ -299,6 +299,41 @@ rpl::producer SearchController::simpleIdsSlice( }; } +auto SearchController::saveState() -> SavedState { + auto result = SavedState(); + if (_current != _cache.end()) { + result.query = _current->first; + result.peerList = std::move(_current->second->peerData.list); + if (auto &migrated = _current->second->migratedData) { + result.migratedList = std::move(migrated->list); + } + } + return result; +} + +void SearchController::restoreState(SavedState &&state) { + if (!state.query.peerId) { + return; + } + + auto it = _cache.find(state.query); + if (it == _cache.end()) { + it = _cache.emplace( + state.query, + std::make_unique(state.query)).first; + } + auto replace = Data(it->second->peerData.peer); + replace.list = std::move(state.peerList); + it->second->peerData = std::move(replace); + if (auto &migrated = state.migratedList) { + Assert(it->second->migratedData.has_value()); + auto replace = Data(it->second->migratedData->peer); + replace.list = std::move(*migrated); + it->second->migratedData = std::move(replace); + } + _current = it; +} + void SearchController::requestMore( const SparseIdsSliceBuilder::AroundData &key, const Query &query, @@ -341,6 +376,10 @@ void DelayedSearchController::setQuery(const Query &query) { void DelayedSearchController::setQuery( const Query &query, TimeMs delay) { + if (currentQuery() == query) { + _timer.cancel(); + return; + } if (_controller.hasInCache(query)) { setQueryFast(query); } else { diff --git a/Telegram/SourceFiles/history/history_search_controller.h b/Telegram/SourceFiles/history/history_search_controller.h index f0a7fe251..e366e7253 100644 --- a/Telegram/SourceFiles/history/history_search_controller.h +++ b/Telegram/SourceFiles/history/history_search_controller.h @@ -50,6 +50,7 @@ SearchResult ParseSearchResult( class SearchController : private MTP::Sender { public: + using IdsList = Storage::SparseIdsList; struct Query { using MediaType = Storage::SharedMediaType; @@ -68,6 +69,11 @@ public: } }; + struct SavedState { + Query query; + IdsList peerList; + base::optional migratedList; + }; void setQuery(const Query &query); bool hasInCache(const Query &query) const; @@ -82,13 +88,16 @@ public: int limitBefore, int limitAfter); + SavedState saveState(); + void restoreState(SavedState &&state); + private: struct Data { explicit Data(not_null peer) : peer(peer) { } not_null peer; - Storage::SparseIdsList list; + IdsList list; base::flat_map< SparseIdsSliceBuilder::AroundData, rpl::lifetime> requests; @@ -133,6 +142,8 @@ public: DelayedSearchController(); using Query = SearchController::Query; + using SavedState = SearchController::SavedState; + void setQuery(const Query &query); void setQuery(const Query &query, TimeMs delay); void setQueryFast(const Query &query); @@ -155,6 +166,14 @@ public: return _sourceChanges.events(); } + SavedState saveState() { + return _controller.saveState(); + } + + void restoreState(SavedState &&state) { + _controller.restoreState(std::move(state)); + } + private: SearchController _controller; Query _nextQuery; diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 3a61edbc2..615d77b67 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -88,17 +88,18 @@ infoLayerMediaSearch: SearchFieldRow(infoMediaSearch) { fieldCancelSkip: 46px; } infoTopBarSearchRow: SearchFieldRow(infoLayerMediaSearch) { + height: 52px; padding: margins(0px, 12px, 8px, 10px); fieldCancel: CrossButton(contactsSearchCancel) { - width: 50px; + width: 51px; height: 52px; cross: CrossAnimation { - size: 38px; - skip: 12px; + size: 42px; + skip: 14px; stroke: 2px; minScale: 0.3; } - crossPosition: point(3px, 8px); + crossPosition: point(1px, 6px); } } diff --git a/Telegram/SourceFiles/info/info_content_widget.h b/Telegram/SourceFiles/info/info_content_widget.h index c78e2d9fb..411d136f5 100644 --- a/Telegram/SourceFiles/info/info_content_widget.h +++ b/Telegram/SourceFiles/info/info_content_widget.h @@ -143,11 +143,18 @@ public: int scrollTop() const { return _scrollTop; } + void setSearchFieldQuery(const QString &query) { + _searchFieldQuery = query; + } + QString searchFieldQuery() const { + return _searchFieldQuery; + } private: const PeerId _peerId = 0; const PeerId _migratedPeerId = 0; int _scrollTop = 0; + QString _searchFieldQuery; }; diff --git a/Telegram/SourceFiles/info/info_controller.cpp b/Telegram/SourceFiles/info/info_controller.cpp index a1fc156a1..c482e25b2 100644 --- a/Telegram/SourceFiles/info/info_controller.cpp +++ b/Telegram/SourceFiles/info/info_controller.cpp @@ -24,6 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "history/history_shared_media.h" #include "info/info_content_widget.h" #include "info/info_memento.h" +#include "info/media/info_media_widget.h" namespace Info { namespace { @@ -50,7 +51,7 @@ Controller::Controller( : nullptr) , _window(window) , _section(memento->section()) { - updateSearchControllers(); + updateSearchControllers(memento); } Wrap Controller::wrap() const { @@ -71,12 +72,13 @@ bool Controller::validateMementoPeer( && memento->migratedPeerId() == migratedPeerId(); } -void Controller::setSection(const Section §ion) { - _section = section; - updateSearchControllers(); +void Controller::setSection(not_null memento) { + _section = memento->section(); + updateSearchControllers(memento); } -void Controller::updateSearchControllers() { +void Controller::updateSearchControllers( + not_null memento) { auto isMedia = (_section.type() == Section::Type::Media); auto mediaType = isMedia ? _section.mediaType() @@ -85,16 +87,21 @@ void Controller::updateSearchControllers() { && SharedMediaAllowSearch(mediaType); // auto hasCommonGroupsSearch // = (_section.type() == Section::Type::CommonGroups); + auto searchQuery = memento->searchFieldQuery(); if (isMedia) { _searchController = std::make_unique(); - _searchController->setQueryFast(produceSearchQuery()); + auto mediaMemento = dynamic_cast(memento.get()); + Assert(mediaMemento != nullptr); + _searchController->restoreState( + mediaMemento->searchState()); } else { _searchController = nullptr; } if (hasMediaSearch) { _searchFieldController - = std::make_unique(); + = std::make_unique( + searchQuery); _searchFieldController->queryValue() | rpl::start_with_next([=](QString &&query) { _searchController->setQuery( @@ -105,12 +112,25 @@ void Controller::updateSearchControllers() { } } +void Controller::saveSearchState(not_null memento) { + if (_searchFieldController) { + memento->setSearchFieldQuery( + _searchFieldController->query()); + } + if (_searchController) { + auto mediaMemento = dynamic_cast( + memento.get()); + Assert(mediaMemento != nullptr); + mediaMemento->setSearchState(_searchController->saveState()); + } +} + auto Controller::produceSearchQuery( - QString &&query) const -> SearchQuery { + const QString &query) const -> SearchQuery { auto result = SearchQuery(); result.type = _section.mediaType(); result.peerId = _peer->id; - result.query = std::move(query); + result.query = query; result.migratedPeerId = _migrated ? _migrated->id : PeerId(0); return result; } diff --git a/Telegram/SourceFiles/info/info_controller.h b/Telegram/SourceFiles/info/info_controller.h index a87f0b901..e4bd45dd7 100644 --- a/Telegram/SourceFiles/info/info_controller.h +++ b/Telegram/SourceFiles/info/info_controller.h @@ -97,7 +97,7 @@ public: Wrap wrap() const; rpl::producer wrapValue() const; - void setSection(const Section §ion); + void setSection(not_null memento); bool hasStackHistory() const; not_null window() const { @@ -114,6 +114,8 @@ public: return _searchController->sourceChanged(); } + void saveSearchState(not_null memento); + rpl::lifetime &lifetime() { return _lifetime; } @@ -123,9 +125,8 @@ public: private: using SearchQuery = Api::DelayedSearchController::Query; - void updateSearchControllers(); - SearchQuery produceSearchQuery( - QString &&query = QString()) const; + void updateSearchControllers(not_null memento); + SearchQuery produceSearchQuery(const QString &query) const; not_null _widget; not_null _peer; diff --git a/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp b/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp index 8de94662b..1222336d3 100644 --- a/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp @@ -189,7 +189,7 @@ bool InnerWidget::showInternal(not_null memento) { void InnerWidget::switchToTab(Memento &&memento) { // Save state of the tab before setSection() call. - _controller->setSection(memento.section()); + _controller->setSection(&memento); _list = setupList(); restoreState(&memento); _list->show(); diff --git a/Telegram/SourceFiles/info/media/info_media_widget.cpp b/Telegram/SourceFiles/info/media/info_media_widget.cpp index 71275f0ab..981b9aa26 100644 --- a/Telegram/SourceFiles/info/media/info_media_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_widget.cpp @@ -54,6 +54,17 @@ Memento::Memento(not_null controller) controller->section().mediaType()) { } +Memento::Memento(PeerId peerId, PeerId migratedPeerId, Type type) +: ContentMemento(peerId, migratedPeerId) +, _type(type) { + _searchState.query.type = type; + _searchState.query.peerId = peerId; + _searchState.query.migratedPeerId = migratedPeerId; + if (migratedPeerId) { + _searchState.migratedList = Storage::SparseIdsList(); + } +} + Section Memento::section() const { return Section(_type); } @@ -119,7 +130,7 @@ std::unique_ptr Widget::createMemento() { } void Widget::saveState(not_null memento) { - memento->setScrollTop(scrollTopSave()); + controller()->saveSearchState(memento); _inner->saveState(memento); } diff --git a/Telegram/SourceFiles/info/media/info_media_widget.h b/Telegram/SourceFiles/info/media/info_media_widget.h index c6b3f350e..5bc928516 100644 --- a/Telegram/SourceFiles/info/media/info_media_widget.h +++ b/Telegram/SourceFiles/info/media/info_media_widget.h @@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include #include "info/info_content_widget.h" #include "storage/storage_shared_media.h" +#include "history/history_search_controller.h" namespace Ui { class SearchFieldController; @@ -41,11 +42,9 @@ class InnerWidget; class Memento final : public ContentMemento { public: Memento(not_null controller); + Memento(PeerId peerId, PeerId migratedPeerId, Type type); - Memento(PeerId peerId, PeerId migratedPeerId, Type type) - : ContentMemento(peerId, migratedPeerId) - , _type(type) { - } + using SearchState = Api::DelayedSearchController::SavedState; object_ptr createWidget( QWidget *parent, @@ -82,13 +81,20 @@ public: int scrollTopShift() const { return _scrollTopShift; } + void setSearchState(SearchState &&state) { + _searchState = std::move(state); + } + SearchState searchState() { + return std::move(_searchState); + } private: Type _type = Type::Photo; FullMsgId _aroundId; int _idsLimit = 0; FullMsgId _scrollTopItem; - int _scrollTopShift = 0;; + int _scrollTopShift = 0; + SearchState _searchState; }; diff --git a/Telegram/SourceFiles/ui/search_field_controller.cpp b/Telegram/SourceFiles/ui/search_field_controller.cpp index 8ae75a3ea..5a3714ed8 100644 --- a/Telegram/SourceFiles/ui/search_field_controller.cpp +++ b/Telegram/SourceFiles/ui/search_field_controller.cpp @@ -29,6 +29,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace Ui { +SearchFieldController::SearchFieldController(const QString &query) +: _query(query) { +} + base::unique_qptr SearchFieldController::createRowView( QWidget *parent, const style::SearchFieldRow &st) { diff --git a/Telegram/SourceFiles/ui/search_field_controller.h b/Telegram/SourceFiles/ui/search_field_controller.h index 20cff564a..5e296b44f 100644 --- a/Telegram/SourceFiles/ui/search_field_controller.h +++ b/Telegram/SourceFiles/ui/search_field_controller.h @@ -36,6 +36,8 @@ class InputField; class SearchFieldController { public: + SearchFieldController(const QString &query); + base::unique_qptr createField( QWidget *parent, const style::InputField &st); @@ -43,6 +45,9 @@ public: QWidget *parent, const style::SearchFieldRow &st); + QString query() const { + return _query.current(); + } rpl::producer queryValue() const { return _query.value(); }