From ebae0d71b8b7b0c0d8be46588729da99ba52982b Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 15 Jan 2020 21:16:49 +0300 Subject: [PATCH] Save poll results state when viewing profiles. --- .../polls/info_polls_results_inner_widget.cpp | 193 ++++++++++++------ .../polls/info_polls_results_inner_widget.h | 4 +- .../info/polls/info_polls_results_widget.cpp | 16 +- .../info/polls/info_polls_results_widget.h | 14 +- 4 files changed, 161 insertions(+), 66 deletions(-) diff --git a/Telegram/SourceFiles/info/polls/info_polls_results_inner_widget.cpp b/Telegram/SourceFiles/info/polls/info_polls_results_inner_widget.cpp index e2d540fd6..be6fc8ede 100644 --- a/Telegram/SourceFiles/info/polls/info_polls_results_inner_widget.cpp +++ b/Telegram/SourceFiles/info/polls/info_polls_results_inner_widget.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "info/polls/info_polls_results_inner_widget.h" +#include "info/polls/info_polls_results_widget.h" #include "info/info_controller.h" #include "lang/lang_keys.h" #include "data/data_poll.h" @@ -51,44 +52,6 @@ public: }; -class ListController final : public PeerListController { -public: - ListController( - not_null session, - not_null poll, - FullMsgId context, - QByteArray option); - - Main::Session &session() const override; - void prepare() override; - void rowClicked(not_null row) override; - void loadMoreRows() override; - - void allowLoadAll(); - - rpl::producer> showPeerInfoRequests() const; - -private: - bool appendRow(not_null user); - std::unique_ptr createRow(not_null user) const; - - const not_null _session; - const not_null _poll; - const FullMsgId _context; - const QByteArray _option; - - MTP::Sender _api; - - QString _offset; - mtpRequestId _loadRequestId = 0; - int _fullCount = 0; - bool _allLoaded = false; - bool _loadingAll = false; - - rpl::event_stream> _showPeerInfoRequests; - -}; - void ListDelegate::peerListSetTitle(rpl::producer title) { } @@ -123,6 +86,59 @@ void ListDelegate::peerListSetDescription( description.destroy(); } +} // namespace + +class ListController final : public PeerListController { +public: + ListController( + not_null session, + not_null poll, + FullMsgId context, + QByteArray option); + + Main::Session &session() const override; + void prepare() override; + void rowClicked(not_null row) override; + void loadMoreRows() override; + + void allowLoadAll(); + + rpl::producer> showPeerInfoRequests() const; + + std::unique_ptr saveState() const override; + void restoreState(std::unique_ptr state) override; + + std::unique_ptr createRestoredRow( + not_null peer) override; + +private: + struct SavedState : SavedStateBase { + QString offset; + bool allLoaded = false; + bool wasLoading = false; + bool loadingAll = false; + }; + + bool appendRow(not_null user); + std::unique_ptr createRow(not_null user) const; + + const not_null _session; + const not_null _poll; + const FullMsgId _context; + const QByteArray _option; + + MTP::Sender _api; + + QString _offset; + mtpRequestId _loadRequestId = 0; + int _fullCount = 0; + bool _allLoaded = false; + bool _loadingAll = false; + + rpl::event_stream> _showPeerInfoRequests; + +}; + ListController::ListController( not_null session, not_null poll, @@ -198,6 +214,46 @@ auto ListController::showPeerInfoRequests() const return _showPeerInfoRequests.events(); } +auto ListController::saveState() const -> std::unique_ptr { + auto result = PeerListController::saveState(); + + auto my = std::make_unique(); + my->offset = _offset; + my->allLoaded = _allLoaded; + my->wasLoading = (_loadRequestId != 0); + my->loadingAll = _loadingAll; + result->controllerState = std::move(my); + + return result; +} + +void ListController::restoreState(std::unique_ptr state) { + auto typeErasedState = state + ? state->controllerState.get() + : nullptr; + if (const auto my = dynamic_cast(typeErasedState)) { + if (const auto requestId = base::take(_loadRequestId)) { + _api.request(requestId).cancel(); + } + + _offset = my->offset; + _allLoaded = my->allLoaded; + _loadingAll = my->loadingAll; + if (my->wasLoading) { + loadMoreRows(); + } + PeerListController::restoreState(std::move(state)); + } +} + +std::unique_ptr ListController::createRestoredRow( + not_null peer) { + if (const auto user = peer->asUser()) { + return createRow(user); + } + return nullptr; +} + void ListController::rowClicked(not_null row) { _showPeerInfoRequests.fire(row->peer()); } @@ -303,8 +359,6 @@ ListController *CreateAnswerRows( return controller; } -} // namespace - InnerWidget::InnerWidget( QWidget *parent, not_null controller, @@ -314,7 +368,8 @@ InnerWidget::InnerWidget( , _controller(controller) , _poll(poll) , _contextId(contextId) -, _content(setupContent(this)) { +, _content(this) { + setupContent(); } void InnerWidget::visibleTopBottomUpdated( @@ -324,11 +379,23 @@ void InnerWidget::visibleTopBottomUpdated( } void InnerWidget::saveState(not_null memento) { - //memento->setListState(_listController->saveState()); + auto states = base::flat_map< + QByteArray, + std::unique_ptr>(); + for (const auto &[option, controller] : _sections) { + states[option] = controller->saveState(); + } + memento->setListStates(std::move(states)); } void InnerWidget::restoreState(not_null memento) { - //_listController->restoreState(memento->listState()); + auto states = memento->listStates(); + for (const auto &[option, controller] : _sections) { + const auto i = states.find(option); + if (i != end(states)) { + controller->restoreState(std::move(i->second)); + } + } } int InnerWidget::desiredHeight() const { @@ -339,14 +406,11 @@ int InnerWidget::desiredHeight() const { return qMax(height(), desired); } -object_ptr InnerWidget::setupContent( - RpWidget *parent) { - auto result = object_ptr(parent); - +void InnerWidget::setupContent() { const auto quiz = _poll->quiz(); - result->add( + _content->add( object_ptr( - result, + _content, _poll->question, st::pollResultsQuestion), style::margins{ @@ -357,27 +421,30 @@ object_ptr InnerWidget::setupContent( for (const auto &answer : _poll->answers) { const auto session = &_controller->parentController()->session(); const auto controller = CreateAnswerRows( - result, + _content, session, _poll, _contextId, answer); - if (controller) { - controller->showPeerInfoRequests( - ) | rpl::start_to_stream( - _showPeerInfoRequests, - lifetime()); + if (!controller) { + continue; } + controller->showPeerInfoRequests( + ) | rpl::start_to_stream( + _showPeerInfoRequests, + lifetime()); + _sections.emplace(answer.option, controller); } - parent->widthValue( - ) | rpl::start_with_next([content = result.data()](int newWidth) { - content->resizeToWidth(newWidth); - }, result->lifetime()); - result->heightValue( + + widthValue( + ) | rpl::start_with_next([=](int newWidth) { + _content->resizeToWidth(newWidth); + }, _content->lifetime()); + + _content->heightValue( ) | rpl::start_with_next([=](int height) { - parent->resize(parent->width(), height); - }, result->lifetime()); - return result; + resize(width(), height); + }, _content->lifetime()); } auto InnerWidget::showPeerInfoRequests() const diff --git a/Telegram/SourceFiles/info/polls/info_polls_results_inner_widget.h b/Telegram/SourceFiles/info/polls/info_polls_results_inner_widget.h index 1bd49441a..8b39e8cbe 100644 --- a/Telegram/SourceFiles/info/polls/info_polls_results_inner_widget.h +++ b/Telegram/SourceFiles/info/polls/info_polls_results_inner_widget.h @@ -21,6 +21,7 @@ class Controller; namespace Polls { class Memento; +class ListController; class InnerWidget final : public Ui::RpWidget { public: @@ -51,13 +52,14 @@ protected: int visibleBottom) override; private: - object_ptr setupContent(RpWidget *parent); + void setupContent(); not_null _controller; not_null _poll; FullMsgId _contextId; object_ptr _content; rpl::event_stream> _showPeerInfoRequests; + base::flat_map> _sections; }; diff --git a/Telegram/SourceFiles/info/polls/info_polls_results_widget.cpp b/Telegram/SourceFiles/info/polls/info_polls_results_widget.cpp index 82bd5ec66..cd071a397 100644 --- a/Telegram/SourceFiles/info/polls/info_polls_results_widget.cpp +++ b/Telegram/SourceFiles/info/polls/info_polls_results_widget.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/polls/info_polls_results_widget.h" #include "info/polls/info_polls_results_inner_widget.h" +#include "boxes/peer_list_box.h" namespace Info { namespace Polls { @@ -20,6 +21,17 @@ Section Memento::section() const { return Section(Section::Type::PollResults); } +void Memento::setListStates(base::flat_map< + QByteArray, + std::unique_ptr> states) { + _listStates = std::move(states); +} + +auto Memento::listStates() +-> base::flat_map> { + return std::move(_listStates); +} + object_ptr Memento::createWidget( QWidget *parent, not_null controller, @@ -82,10 +94,12 @@ std::unique_ptr Widget::doCreateMemento() { void Widget::saveState(not_null memento) { memento->setScrollTop(scrollTopSave()); + _inner->saveState(memento); } void Widget::restoreState(not_null memento) { - const auto scrollTop = memento->scrollTop(); + _inner->restoreState(memento); + auto scrollTop = memento->scrollTop(); scrollTopRestore(memento->scrollTop()); } diff --git a/Telegram/SourceFiles/info/polls/info_polls_results_widget.h b/Telegram/SourceFiles/info/polls/info_polls_results_widget.h index efce0460c..f8a140711 100644 --- a/Telegram/SourceFiles/info/polls/info_polls_results_widget.h +++ b/Telegram/SourceFiles/info/polls/info_polls_results_widget.h @@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/info_content_widget.h" #include "info/info_controller.h" +struct PeerListState; + namespace Info { namespace Polls { @@ -18,6 +20,7 @@ class InnerWidget; class Memento final : public ContentMemento { public: Memento(not_null poll, FullMsgId contextId); + ~Memento(); object_ptr createWidget( QWidget *parent, @@ -26,7 +29,16 @@ public: Section section() const override; - ~Memento(); + void setListStates(base::flat_map< + QByteArray, + std::unique_ptr> states); + auto listStates() + -> base::flat_map>; + +private: + base::flat_map< + QByteArray, + std::unique_ptr> _listStates; };