Save media search state to memento.

This commit is contained in:
John Preston 2017-11-03 19:47:08 +04:00
parent 09d1e3629a
commit 39c5898fa4
11 changed files with 138 additions and 25 deletions

View File

@ -299,6 +299,41 @@ rpl::producer<SparseIdsSlice> 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<CacheEntry>(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 {

View File

@ -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<IdsList> 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<PeerData*> peer) : peer(peer) {
}
not_null<PeerData*> 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;

View File

@ -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);
}
}

View File

@ -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;
};

View File

@ -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 &section) {
_section = section;
updateSearchControllers();
void Controller::setSection(not_null<ContentMemento*> memento) {
_section = memento->section();
updateSearchControllers(memento);
}
void Controller::updateSearchControllers() {
void Controller::updateSearchControllers(
not_null<ContentMemento*> 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<Api::DelayedSearchController>();
_searchController->setQueryFast(produceSearchQuery());
auto mediaMemento = dynamic_cast<Media::Memento*>(memento.get());
Assert(mediaMemento != nullptr);
_searchController->restoreState(
mediaMemento->searchState());
} else {
_searchController = nullptr;
}
if (hasMediaSearch) {
_searchFieldController
= std::make_unique<Ui::SearchFieldController>();
= std::make_unique<Ui::SearchFieldController>(
searchQuery);
_searchFieldController->queryValue()
| rpl::start_with_next([=](QString &&query) {
_searchController->setQuery(
@ -105,12 +112,25 @@ void Controller::updateSearchControllers() {
}
}
void Controller::saveSearchState(not_null<ContentMemento*> memento) {
if (_searchFieldController) {
memento->setSearchFieldQuery(
_searchFieldController->query());
}
if (_searchController) {
auto mediaMemento = dynamic_cast<Media::Memento*>(
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;
}

View File

@ -97,7 +97,7 @@ public:
Wrap wrap() const;
rpl::producer<Wrap> wrapValue() const;
void setSection(const Section &section);
void setSection(not_null<ContentMemento*> memento);
bool hasStackHistory() const;
not_null<Window::Controller*> window() const {
@ -114,6 +114,8 @@ public:
return _searchController->sourceChanged();
}
void saveSearchState(not_null<ContentMemento*> 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<ContentMemento*> memento);
SearchQuery produceSearchQuery(const QString &query) const;
not_null<WrapWidget*> _widget;
not_null<PeerData*> _peer;

View File

@ -189,7 +189,7 @@ bool InnerWidget::showInternal(not_null<Memento*> 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();

View File

@ -54,6 +54,17 @@ Memento::Memento(not_null<Controller*> 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<ContentMemento> Widget::createMemento() {
}
void Widget::saveState(not_null<Memento*> memento) {
memento->setScrollTop(scrollTopSave());
controller()->saveSearchState(memento);
_inner->saveState(memento);
}

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include <rpl/producer.h>
#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*> 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<ContentWidget> 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;
};

View File

@ -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<Ui::RpWidget> SearchFieldController::createRowView(
QWidget *parent,
const style::SearchFieldRow &st) {

View File

@ -36,6 +36,8 @@ class InputField;
class SearchFieldController {
public:
SearchFieldController(const QString &query);
base::unique_qptr<Ui::InputField> 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<QString> queryValue() const {
return _query.value();
}