mirror of https://github.com/procxx/kepka.git
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(
|
void SearchController::requestMore(
|
||||||
const SparseIdsSliceBuilder::AroundData &key,
|
const SparseIdsSliceBuilder::AroundData &key,
|
||||||
const Query &query,
|
const Query &query,
|
||||||
|
@ -341,6 +376,10 @@ void DelayedSearchController::setQuery(const Query &query) {
|
||||||
void DelayedSearchController::setQuery(
|
void DelayedSearchController::setQuery(
|
||||||
const Query &query,
|
const Query &query,
|
||||||
TimeMs delay) {
|
TimeMs delay) {
|
||||||
|
if (currentQuery() == query) {
|
||||||
|
_timer.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_controller.hasInCache(query)) {
|
if (_controller.hasInCache(query)) {
|
||||||
setQueryFast(query);
|
setQueryFast(query);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -50,6 +50,7 @@ SearchResult ParseSearchResult(
|
||||||
|
|
||||||
class SearchController : private MTP::Sender {
|
class SearchController : private MTP::Sender {
|
||||||
public:
|
public:
|
||||||
|
using IdsList = Storage::SparseIdsList;
|
||||||
struct Query {
|
struct Query {
|
||||||
using MediaType = Storage::SharedMediaType;
|
using MediaType = Storage::SharedMediaType;
|
||||||
|
|
||||||
|
@ -68,6 +69,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
struct SavedState {
|
||||||
|
Query query;
|
||||||
|
IdsList peerList;
|
||||||
|
base::optional<IdsList> migratedList;
|
||||||
|
};
|
||||||
|
|
||||||
void setQuery(const Query &query);
|
void setQuery(const Query &query);
|
||||||
bool hasInCache(const Query &query) const;
|
bool hasInCache(const Query &query) const;
|
||||||
|
@ -82,13 +88,16 @@ public:
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
int limitAfter);
|
int limitAfter);
|
||||||
|
|
||||||
|
SavedState saveState();
|
||||||
|
void restoreState(SavedState &&state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Data {
|
struct Data {
|
||||||
explicit Data(not_null<PeerData*> peer) : peer(peer) {
|
explicit Data(not_null<PeerData*> peer) : peer(peer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<PeerData*> peer;
|
not_null<PeerData*> peer;
|
||||||
Storage::SparseIdsList list;
|
IdsList list;
|
||||||
base::flat_map<
|
base::flat_map<
|
||||||
SparseIdsSliceBuilder::AroundData,
|
SparseIdsSliceBuilder::AroundData,
|
||||||
rpl::lifetime> requests;
|
rpl::lifetime> requests;
|
||||||
|
@ -133,6 +142,8 @@ public:
|
||||||
DelayedSearchController();
|
DelayedSearchController();
|
||||||
|
|
||||||
using Query = SearchController::Query;
|
using Query = SearchController::Query;
|
||||||
|
using SavedState = SearchController::SavedState;
|
||||||
|
|
||||||
void setQuery(const Query &query);
|
void setQuery(const Query &query);
|
||||||
void setQuery(const Query &query, TimeMs delay);
|
void setQuery(const Query &query, TimeMs delay);
|
||||||
void setQueryFast(const Query &query);
|
void setQueryFast(const Query &query);
|
||||||
|
@ -155,6 +166,14 @@ public:
|
||||||
return _sourceChanges.events();
|
return _sourceChanges.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SavedState saveState() {
|
||||||
|
return _controller.saveState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void restoreState(SavedState &&state) {
|
||||||
|
_controller.restoreState(std::move(state));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SearchController _controller;
|
SearchController _controller;
|
||||||
Query _nextQuery;
|
Query _nextQuery;
|
||||||
|
|
|
@ -88,17 +88,18 @@ infoLayerMediaSearch: SearchFieldRow(infoMediaSearch) {
|
||||||
fieldCancelSkip: 46px;
|
fieldCancelSkip: 46px;
|
||||||
}
|
}
|
||||||
infoTopBarSearchRow: SearchFieldRow(infoLayerMediaSearch) {
|
infoTopBarSearchRow: SearchFieldRow(infoLayerMediaSearch) {
|
||||||
|
height: 52px;
|
||||||
padding: margins(0px, 12px, 8px, 10px);
|
padding: margins(0px, 12px, 8px, 10px);
|
||||||
fieldCancel: CrossButton(contactsSearchCancel) {
|
fieldCancel: CrossButton(contactsSearchCancel) {
|
||||||
width: 50px;
|
width: 51px;
|
||||||
height: 52px;
|
height: 52px;
|
||||||
cross: CrossAnimation {
|
cross: CrossAnimation {
|
||||||
size: 38px;
|
size: 42px;
|
||||||
skip: 12px;
|
skip: 14px;
|
||||||
stroke: 2px;
|
stroke: 2px;
|
||||||
minScale: 0.3;
|
minScale: 0.3;
|
||||||
}
|
}
|
||||||
crossPosition: point(3px, 8px);
|
crossPosition: point(1px, 6px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,11 +143,18 @@ public:
|
||||||
int scrollTop() const {
|
int scrollTop() const {
|
||||||
return _scrollTop;
|
return _scrollTop;
|
||||||
}
|
}
|
||||||
|
void setSearchFieldQuery(const QString &query) {
|
||||||
|
_searchFieldQuery = query;
|
||||||
|
}
|
||||||
|
QString searchFieldQuery() const {
|
||||||
|
return _searchFieldQuery;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const PeerId _peerId = 0;
|
const PeerId _peerId = 0;
|
||||||
const PeerId _migratedPeerId = 0;
|
const PeerId _migratedPeerId = 0;
|
||||||
int _scrollTop = 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 "history/history_shared_media.h"
|
||||||
#include "info/info_content_widget.h"
|
#include "info/info_content_widget.h"
|
||||||
#include "info/info_memento.h"
|
#include "info/info_memento.h"
|
||||||
|
#include "info/media/info_media_widget.h"
|
||||||
|
|
||||||
namespace Info {
|
namespace Info {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -50,7 +51,7 @@ Controller::Controller(
|
||||||
: nullptr)
|
: nullptr)
|
||||||
, _window(window)
|
, _window(window)
|
||||||
, _section(memento->section()) {
|
, _section(memento->section()) {
|
||||||
updateSearchControllers();
|
updateSearchControllers(memento);
|
||||||
}
|
}
|
||||||
|
|
||||||
Wrap Controller::wrap() const {
|
Wrap Controller::wrap() const {
|
||||||
|
@ -71,12 +72,13 @@ bool Controller::validateMementoPeer(
|
||||||
&& memento->migratedPeerId() == migratedPeerId();
|
&& memento->migratedPeerId() == migratedPeerId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::setSection(const Section §ion) {
|
void Controller::setSection(not_null<ContentMemento*> memento) {
|
||||||
_section = section;
|
_section = memento->section();
|
||||||
updateSearchControllers();
|
updateSearchControllers(memento);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::updateSearchControllers() {
|
void Controller::updateSearchControllers(
|
||||||
|
not_null<ContentMemento*> memento) {
|
||||||
auto isMedia = (_section.type() == Section::Type::Media);
|
auto isMedia = (_section.type() == Section::Type::Media);
|
||||||
auto mediaType = isMedia
|
auto mediaType = isMedia
|
||||||
? _section.mediaType()
|
? _section.mediaType()
|
||||||
|
@ -85,16 +87,21 @@ void Controller::updateSearchControllers() {
|
||||||
&& SharedMediaAllowSearch(mediaType);
|
&& SharedMediaAllowSearch(mediaType);
|
||||||
// auto hasCommonGroupsSearch
|
// auto hasCommonGroupsSearch
|
||||||
// = (_section.type() == Section::Type::CommonGroups);
|
// = (_section.type() == Section::Type::CommonGroups);
|
||||||
|
auto searchQuery = memento->searchFieldQuery();
|
||||||
if (isMedia) {
|
if (isMedia) {
|
||||||
_searchController
|
_searchController
|
||||||
= std::make_unique<Api::DelayedSearchController>();
|
= std::make_unique<Api::DelayedSearchController>();
|
||||||
_searchController->setQueryFast(produceSearchQuery());
|
auto mediaMemento = dynamic_cast<Media::Memento*>(memento.get());
|
||||||
|
Assert(mediaMemento != nullptr);
|
||||||
|
_searchController->restoreState(
|
||||||
|
mediaMemento->searchState());
|
||||||
} else {
|
} else {
|
||||||
_searchController = nullptr;
|
_searchController = nullptr;
|
||||||
}
|
}
|
||||||
if (hasMediaSearch) {
|
if (hasMediaSearch) {
|
||||||
_searchFieldController
|
_searchFieldController
|
||||||
= std::make_unique<Ui::SearchFieldController>();
|
= std::make_unique<Ui::SearchFieldController>(
|
||||||
|
searchQuery);
|
||||||
_searchFieldController->queryValue()
|
_searchFieldController->queryValue()
|
||||||
| rpl::start_with_next([=](QString &&query) {
|
| rpl::start_with_next([=](QString &&query) {
|
||||||
_searchController->setQuery(
|
_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(
|
auto Controller::produceSearchQuery(
|
||||||
QString &&query) const -> SearchQuery {
|
const QString &query) const -> SearchQuery {
|
||||||
auto result = SearchQuery();
|
auto result = SearchQuery();
|
||||||
result.type = _section.mediaType();
|
result.type = _section.mediaType();
|
||||||
result.peerId = _peer->id;
|
result.peerId = _peer->id;
|
||||||
result.query = std::move(query);
|
result.query = query;
|
||||||
result.migratedPeerId = _migrated ? _migrated->id : PeerId(0);
|
result.migratedPeerId = _migrated ? _migrated->id : PeerId(0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ public:
|
||||||
|
|
||||||
Wrap wrap() const;
|
Wrap wrap() const;
|
||||||
rpl::producer<Wrap> wrapValue() const;
|
rpl::producer<Wrap> wrapValue() const;
|
||||||
void setSection(const Section §ion);
|
void setSection(not_null<ContentMemento*> memento);
|
||||||
bool hasStackHistory() const;
|
bool hasStackHistory() const;
|
||||||
|
|
||||||
not_null<Window::Controller*> window() const {
|
not_null<Window::Controller*> window() const {
|
||||||
|
@ -114,6 +114,8 @@ public:
|
||||||
return _searchController->sourceChanged();
|
return _searchController->sourceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveSearchState(not_null<ContentMemento*> memento);
|
||||||
|
|
||||||
rpl::lifetime &lifetime() {
|
rpl::lifetime &lifetime() {
|
||||||
return _lifetime;
|
return _lifetime;
|
||||||
}
|
}
|
||||||
|
@ -123,9 +125,8 @@ public:
|
||||||
private:
|
private:
|
||||||
using SearchQuery = Api::DelayedSearchController::Query;
|
using SearchQuery = Api::DelayedSearchController::Query;
|
||||||
|
|
||||||
void updateSearchControllers();
|
void updateSearchControllers(not_null<ContentMemento*> memento);
|
||||||
SearchQuery produceSearchQuery(
|
SearchQuery produceSearchQuery(const QString &query) const;
|
||||||
QString &&query = QString()) const;
|
|
||||||
|
|
||||||
not_null<WrapWidget*> _widget;
|
not_null<WrapWidget*> _widget;
|
||||||
not_null<PeerData*> _peer;
|
not_null<PeerData*> _peer;
|
||||||
|
|
|
@ -189,7 +189,7 @@ bool InnerWidget::showInternal(not_null<Memento*> memento) {
|
||||||
|
|
||||||
void InnerWidget::switchToTab(Memento &&memento) {
|
void InnerWidget::switchToTab(Memento &&memento) {
|
||||||
// Save state of the tab before setSection() call.
|
// Save state of the tab before setSection() call.
|
||||||
_controller->setSection(memento.section());
|
_controller->setSection(&memento);
|
||||||
_list = setupList();
|
_list = setupList();
|
||||||
restoreState(&memento);
|
restoreState(&memento);
|
||||||
_list->show();
|
_list->show();
|
||||||
|
|
|
@ -54,6 +54,17 @@ Memento::Memento(not_null<Controller*> controller)
|
||||||
controller->section().mediaType()) {
|
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 {
|
Section Memento::section() const {
|
||||||
return Section(_type);
|
return Section(_type);
|
||||||
}
|
}
|
||||||
|
@ -119,7 +130,7 @@ std::unique_ptr<ContentMemento> Widget::createMemento() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::saveState(not_null<Memento*> memento) {
|
void Widget::saveState(not_null<Memento*> memento) {
|
||||||
memento->setScrollTop(scrollTopSave());
|
controller()->saveSearchState(memento);
|
||||||
_inner->saveState(memento);
|
_inner->saveState(memento);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include <rpl/producer.h>
|
#include <rpl/producer.h>
|
||||||
#include "info/info_content_widget.h"
|
#include "info/info_content_widget.h"
|
||||||
#include "storage/storage_shared_media.h"
|
#include "storage/storage_shared_media.h"
|
||||||
|
#include "history/history_search_controller.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class SearchFieldController;
|
class SearchFieldController;
|
||||||
|
@ -41,11 +42,9 @@ class InnerWidget;
|
||||||
class Memento final : public ContentMemento {
|
class Memento final : public ContentMemento {
|
||||||
public:
|
public:
|
||||||
Memento(not_null<Controller*> controller);
|
Memento(not_null<Controller*> controller);
|
||||||
|
Memento(PeerId peerId, PeerId migratedPeerId, Type type);
|
||||||
|
|
||||||
Memento(PeerId peerId, PeerId migratedPeerId, Type type)
|
using SearchState = Api::DelayedSearchController::SavedState;
|
||||||
: ContentMemento(peerId, migratedPeerId)
|
|
||||||
, _type(type) {
|
|
||||||
}
|
|
||||||
|
|
||||||
object_ptr<ContentWidget> createWidget(
|
object_ptr<ContentWidget> createWidget(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
|
@ -82,13 +81,20 @@ public:
|
||||||
int scrollTopShift() const {
|
int scrollTopShift() const {
|
||||||
return _scrollTopShift;
|
return _scrollTopShift;
|
||||||
}
|
}
|
||||||
|
void setSearchState(SearchState &&state) {
|
||||||
|
_searchState = std::move(state);
|
||||||
|
}
|
||||||
|
SearchState searchState() {
|
||||||
|
return std::move(_searchState);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type _type = Type::Photo;
|
Type _type = Type::Photo;
|
||||||
FullMsgId _aroundId;
|
FullMsgId _aroundId;
|
||||||
int _idsLimit = 0;
|
int _idsLimit = 0;
|
||||||
FullMsgId _scrollTopItem;
|
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 {
|
namespace Ui {
|
||||||
|
|
||||||
|
SearchFieldController::SearchFieldController(const QString &query)
|
||||||
|
: _query(query) {
|
||||||
|
}
|
||||||
|
|
||||||
base::unique_qptr<Ui::RpWidget> SearchFieldController::createRowView(
|
base::unique_qptr<Ui::RpWidget> SearchFieldController::createRowView(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
const style::SearchFieldRow &st) {
|
const style::SearchFieldRow &st) {
|
||||||
|
|
|
@ -36,6 +36,8 @@ class InputField;
|
||||||
|
|
||||||
class SearchFieldController {
|
class SearchFieldController {
|
||||||
public:
|
public:
|
||||||
|
SearchFieldController(const QString &query);
|
||||||
|
|
||||||
base::unique_qptr<Ui::InputField> createField(
|
base::unique_qptr<Ui::InputField> createField(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
const style::InputField &st);
|
const style::InputField &st);
|
||||||
|
@ -43,6 +45,9 @@ public:
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
const style::SearchFieldRow &st);
|
const style::SearchFieldRow &st);
|
||||||
|
|
||||||
|
QString query() const {
|
||||||
|
return _query.current();
|
||||||
|
}
|
||||||
rpl::producer<QString> queryValue() const {
|
rpl::producer<QString> queryValue() const {
|
||||||
return _query.value();
|
return _query.value();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue