Save media search state to memento.
This commit is contained in:
parent
09d1e3629a
commit
39c5898fa4
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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<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;
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ public:
|
|||
|
||||
Wrap wrap() const;
|
||||
rpl::producer<Wrap> wrapValue() const;
|
||||
void setSection(const Section §ion);
|
||||
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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue