mirror of https://github.com/procxx/kepka.git
726 lines
19 KiB
C++
726 lines
19 KiB
C++
/*
|
|
This file is part of Telegram Desktop,
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
For license and copyright information please follow this link:
|
|
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"
|
|
#include "data/data_peer.h"
|
|
#include "data/data_user.h"
|
|
#include "data/data_session.h"
|
|
#include "ui/widgets/labels.h"
|
|
#include "ui/widgets/buttons.h"
|
|
#include "ui/wrap/vertical_layout.h"
|
|
#include "ui/wrap/padding_wrap.h"
|
|
#include "ui/wrap/slide_wrap.h"
|
|
#include "ui/text/text_utilities.h"
|
|
#include "boxes/peer_list_box.h"
|
|
#include "main/main_session.h"
|
|
#include "history/history.h"
|
|
#include "history/history_item.h"
|
|
#include "apiwrap.h"
|
|
#include "styles/style_layers.h"
|
|
#include "styles/style_boxes.h"
|
|
#include "styles/style_info.h"
|
|
|
|
namespace Info {
|
|
namespace Polls {
|
|
namespace {
|
|
|
|
constexpr auto kFirstPage = 15;
|
|
constexpr auto kPerPage = 50;
|
|
constexpr auto kLeavePreloaded = 5;
|
|
|
|
class PeerListDummy final : public Ui::RpWidget {
|
|
public:
|
|
PeerListDummy(QWidget *parent, int count, const style::PeerList &st);
|
|
|
|
protected:
|
|
void paintEvent(QPaintEvent *e) override;
|
|
|
|
private:
|
|
const style::PeerList &_st;
|
|
int _count = 0;
|
|
|
|
std::vector<Ui::Animations::Simple> _animations;
|
|
|
|
};
|
|
|
|
class ListDelegate final : public PeerListContentDelegate {
|
|
public:
|
|
void peerListSetTitle(rpl::producer<QString> title) override;
|
|
void peerListSetAdditionalTitle(rpl::producer<QString> title) override;
|
|
bool peerListIsRowSelected(not_null<PeerData*> peer) override;
|
|
int peerListSelectedRowsCount() override;
|
|
std::vector<not_null<PeerData*>> peerListCollectSelectedRows() override;
|
|
void peerListScrollToTop() override;
|
|
void peerListAddSelectedRowInBunch(
|
|
not_null<PeerData*> peer) override;
|
|
void peerListFinishSelectedRowsBunch() override;
|
|
void peerListSetDescription(
|
|
object_ptr<Ui::FlatLabel> description) override;
|
|
|
|
};
|
|
|
|
PeerListDummy::PeerListDummy(
|
|
QWidget *parent,
|
|
int count,
|
|
const style::PeerList &st)
|
|
: _st(st)
|
|
, _count(count) {
|
|
resize(width(), _count * _st.item.height);
|
|
}
|
|
|
|
void PeerListDummy::paintEvent(QPaintEvent *e) {
|
|
QPainter p(this);
|
|
|
|
PainterHighQualityEnabler hq(p);
|
|
|
|
const auto fill = e->rect();
|
|
const auto bottom = fill.top() + fill.height();
|
|
const auto from = floorclamp(fill.top(), _st.item.height, 0, _count);
|
|
const auto till = ceilclamp(bottom, _st.item.height, 0, _count);
|
|
p.translate(0, _st.item.height * from);
|
|
p.setPen(Qt::NoPen);
|
|
for (auto i = from; i != till; ++i) {
|
|
p.setBrush(st::windowBgOver);
|
|
p.drawEllipse(
|
|
_st.item.photoPosition.x(),
|
|
_st.item.photoPosition.y(),
|
|
_st.item.photoSize,
|
|
_st.item.photoSize);
|
|
|
|
const auto small = int(1.5 * _st.item.photoSize);
|
|
const auto large = 2 * small;
|
|
const auto second = (i % 2) ? large : small;
|
|
const auto height = _st.item.nameStyle.font->height / 2;
|
|
const auto radius = height / 2;
|
|
const auto left = _st.item.namePosition.x();
|
|
const auto top = _st.item.namePosition.y()
|
|
+ (_st.item.nameStyle.font->height - height) / 2;
|
|
const auto skip = _st.item.namePosition.x()
|
|
- _st.item.photoPosition.x()
|
|
- _st.item.photoSize;
|
|
const auto next = left + small + skip;
|
|
p.drawRoundedRect(left, top, small, height, radius, radius);
|
|
p.drawRoundedRect(next, top, second, height, radius, radius);
|
|
|
|
p.translate(0, _st.item.height);
|
|
}
|
|
}
|
|
|
|
void ListDelegate::peerListSetTitle(rpl::producer<QString> title) {
|
|
}
|
|
|
|
void ListDelegate::peerListSetAdditionalTitle(rpl::producer<QString> title) {
|
|
}
|
|
|
|
bool ListDelegate::peerListIsRowSelected(not_null<PeerData*> peer) {
|
|
return false;
|
|
}
|
|
|
|
int ListDelegate::peerListSelectedRowsCount() {
|
|
return 0;
|
|
}
|
|
|
|
auto ListDelegate::peerListCollectSelectedRows()
|
|
-> std::vector<not_null<PeerData*>> {
|
|
return {};
|
|
}
|
|
|
|
void ListDelegate::peerListScrollToTop() {
|
|
}
|
|
|
|
void ListDelegate::peerListAddSelectedRowInBunch(not_null<PeerData*> peer) {
|
|
Unexpected("Item selection in Info::Profile::Members.");
|
|
}
|
|
|
|
void ListDelegate::peerListFinishSelectedRowsBunch() {
|
|
}
|
|
|
|
void ListDelegate::peerListSetDescription(
|
|
object_ptr<Ui::FlatLabel> description) {
|
|
description.destroy();
|
|
}
|
|
|
|
} // namespace
|
|
|
|
class ListController final : public PeerListController {
|
|
public:
|
|
ListController(
|
|
not_null<Main::Session*> session,
|
|
not_null<PollData*> poll,
|
|
FullMsgId context,
|
|
QByteArray option);
|
|
|
|
Main::Session &session() const override;
|
|
void prepare() override;
|
|
void rowClicked(not_null<PeerListRow*> row) override;
|
|
void loadMoreRows() override;
|
|
|
|
void allowLoadMore();
|
|
void collapse();
|
|
|
|
[[nodiscard]] auto showPeerInfoRequests() const
|
|
-> rpl::producer<not_null<PeerData*>>;
|
|
[[nodiscard]] rpl::producer<int> scrollToRequests() const;
|
|
[[nodiscard]] rpl::producer<int> count() const;
|
|
[[nodiscard]] rpl::producer<int> fullCount() const;
|
|
[[nodiscard]] rpl::producer<int> loadMoreCount() const;
|
|
|
|
std::unique_ptr<PeerListState> saveState() const override;
|
|
void restoreState(std::unique_ptr<PeerListState> state) override;
|
|
|
|
std::unique_ptr<PeerListRow> createRestoredRow(
|
|
not_null<PeerData*> peer) override;
|
|
|
|
void scrollTo(int y);
|
|
|
|
private:
|
|
struct SavedState : SavedStateBase {
|
|
QString offset;
|
|
QString loadForOffset;
|
|
int leftToLoad = 0;
|
|
int fullCount = 0;
|
|
std::vector<not_null<UserData*>> preloaded;
|
|
bool wasLoading = false;
|
|
};
|
|
|
|
bool appendRow(not_null<UserData*> user);
|
|
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) const;
|
|
void addPreloaded();
|
|
bool addPreloadedPage();
|
|
void preloadedAdded();
|
|
|
|
const not_null<Main::Session*> _session;
|
|
const not_null<PollData*> _poll;
|
|
const FullMsgId _context;
|
|
const QByteArray _option;
|
|
|
|
MTP::Sender _api;
|
|
|
|
QString _offset;
|
|
mtpRequestId _loadRequestId = 0;
|
|
QString _loadForOffset;
|
|
std::vector<not_null<UserData*>> _preloaded;
|
|
rpl::variable<int> _count = 0;
|
|
rpl::variable<int> _fullCount;
|
|
rpl::variable<int> _leftToLoad;
|
|
|
|
rpl::event_stream<not_null<PeerData*>> _showPeerInfoRequests;
|
|
rpl::event_stream<int> _scrollToRequests;
|
|
|
|
};
|
|
|
|
ListController::ListController(
|
|
not_null<Main::Session*> session,
|
|
not_null<PollData*> poll,
|
|
FullMsgId context,
|
|
QByteArray option)
|
|
: _session(session)
|
|
, _poll(poll)
|
|
, _context(context)
|
|
, _option(option)
|
|
, _api(_session->api().instance()) {
|
|
const auto i = ranges::find(poll->answers, option, &PollAnswer::option);
|
|
Assert(i != poll->answers.end());
|
|
_fullCount = i->votes;
|
|
_leftToLoad = i->votes;
|
|
}
|
|
|
|
Main::Session &ListController::session() const {
|
|
return *_session;
|
|
}
|
|
|
|
void ListController::prepare() {
|
|
delegate()->peerListRefreshRows();
|
|
}
|
|
|
|
void ListController::loadMoreRows() {
|
|
if (_loadRequestId
|
|
|| !_leftToLoad.current()
|
|
|| (!_offset.isEmpty() && _loadForOffset != _offset)
|
|
|| !_preloaded.empty()) {
|
|
return;
|
|
}
|
|
const auto item = session().data().message(_context);
|
|
if (!item || !IsServerMsgId(item->id)) {
|
|
_leftToLoad = 0;
|
|
return;
|
|
}
|
|
|
|
using Flag = MTPmessages_GetPollVotes::Flag;
|
|
const auto flags = Flag::f_option
|
|
| (_offset.isEmpty() ? Flag(0) : Flag::f_offset);
|
|
const auto limit = _offset.isEmpty() ? kFirstPage : kPerPage;
|
|
_loadRequestId = _api.request(MTPmessages_GetPollVotes(
|
|
MTP_flags(flags),
|
|
item->history()->peer->input,
|
|
MTP_int(item->id),
|
|
MTP_bytes(_option),
|
|
MTP_string(_offset),
|
|
MTP_int(limit)
|
|
)).done([=](const MTPmessages_VotesList &result) {
|
|
const auto count = result.match([&](
|
|
const MTPDmessages_votesList &data) {
|
|
_offset = data.vnext_offset().value_or_empty();
|
|
auto &owner = session().data();
|
|
owner.processUsers(data.vusers());
|
|
auto add = limit - kLeavePreloaded;
|
|
for (const auto &vote : data.vvotes().v) {
|
|
vote.match([&](const auto &data) {
|
|
const auto user = owner.user(data.vuser_id().v);
|
|
if (user->loadedStatus != PeerData::NotLoaded) {
|
|
if (add) {
|
|
appendRow(user);
|
|
--add;
|
|
} else {
|
|
_preloaded.push_back(user);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
return data.vcount().v;
|
|
});
|
|
if (_offset.isEmpty()) {
|
|
addPreloaded();
|
|
_fullCount = delegate()->peerListFullRowsCount();
|
|
_leftToLoad = 0;
|
|
} else {
|
|
_count = delegate()->peerListFullRowsCount();
|
|
_fullCount = count;
|
|
_leftToLoad = count - delegate()->peerListFullRowsCount();
|
|
delegate()->peerListRefreshRows();
|
|
}
|
|
_loadRequestId = 0;
|
|
}).fail([=](const RPCError &error) {
|
|
_loadRequestId = 0;
|
|
}).send();
|
|
}
|
|
|
|
void ListController::allowLoadMore() {
|
|
if (!addPreloadedPage()) {
|
|
_loadForOffset = _offset;
|
|
addPreloaded();
|
|
loadMoreRows();
|
|
}
|
|
}
|
|
|
|
void ListController::collapse() {
|
|
const auto count = delegate()->peerListFullRowsCount();
|
|
if (count <= kFirstPage) {
|
|
return;
|
|
}
|
|
const auto remove = count - (kFirstPage - kLeavePreloaded);
|
|
ranges::action::reverse(_preloaded);
|
|
_preloaded.reserve(_preloaded.size() + remove);
|
|
for (auto i = 0; i != remove; ++i) {
|
|
const auto row = delegate()->peerListRowAt(count - i - 1);
|
|
_preloaded.push_back(row->peer()->asUser());
|
|
delegate()->peerListRemoveRow(row);
|
|
}
|
|
ranges::action::reverse(_preloaded);
|
|
|
|
delegate()->peerListRefreshRows();
|
|
const auto now = count - remove;
|
|
_count = now;
|
|
_leftToLoad = _fullCount.current() - now;
|
|
}
|
|
|
|
void ListController::addPreloaded() {
|
|
for (const auto user : base::take(_preloaded)) {
|
|
appendRow(user);
|
|
}
|
|
preloadedAdded();
|
|
}
|
|
|
|
bool ListController::addPreloadedPage() {
|
|
if (_preloaded.size() < kPerPage + kLeavePreloaded) {
|
|
return false;
|
|
}
|
|
const auto from = begin(_preloaded);
|
|
const auto till = from + kPerPage;
|
|
for (auto i = from; i != till; ++i) {
|
|
appendRow(*i);
|
|
}
|
|
_preloaded.erase(from, till);
|
|
preloadedAdded();
|
|
return true;
|
|
}
|
|
|
|
void ListController::preloadedAdded() {
|
|
_count = delegate()->peerListFullRowsCount();
|
|
_leftToLoad = _fullCount.current() - _count.current();
|
|
delegate()->peerListRefreshRows();
|
|
}
|
|
|
|
auto ListController::showPeerInfoRequests() const
|
|
-> rpl::producer<not_null<PeerData*>> {
|
|
return _showPeerInfoRequests.events();
|
|
}
|
|
|
|
rpl::producer<int> ListController::scrollToRequests() const {
|
|
return _scrollToRequests.events();
|
|
}
|
|
|
|
rpl::producer<int> ListController::count() const {
|
|
return _count.value();
|
|
}
|
|
|
|
rpl::producer<int> ListController::fullCount() const {
|
|
return _fullCount.value();
|
|
}
|
|
|
|
rpl::producer<int> ListController::loadMoreCount() const {
|
|
const auto initial = (_fullCount.current() <= kFirstPage)
|
|
? _fullCount.current()
|
|
: (kFirstPage - kLeavePreloaded);
|
|
return rpl::combine(
|
|
_count.value(),
|
|
_leftToLoad.value()
|
|
) | rpl::map([=](int count, int leftToLoad) {
|
|
return (count > 0) ? leftToLoad : (leftToLoad - initial);
|
|
});
|
|
}
|
|
|
|
auto ListController::saveState() const -> std::unique_ptr<PeerListState> {
|
|
auto result = PeerListController::saveState();
|
|
|
|
auto my = std::make_unique<SavedState>();
|
|
my->offset = _offset;
|
|
my->fullCount = _fullCount.current();
|
|
my->leftToLoad = _leftToLoad.current();
|
|
my->preloaded = _preloaded;
|
|
my->wasLoading = (_loadRequestId != 0);
|
|
my->loadForOffset = _loadForOffset;
|
|
result->controllerState = std::move(my);
|
|
|
|
return result;
|
|
}
|
|
|
|
void ListController::restoreState(std::unique_ptr<PeerListState> state) {
|
|
auto typeErasedState = state
|
|
? state->controllerState.get()
|
|
: nullptr;
|
|
if (const auto my = dynamic_cast<SavedState*>(typeErasedState)) {
|
|
if (const auto requestId = base::take(_loadRequestId)) {
|
|
_api.request(requestId).cancel();
|
|
}
|
|
|
|
_offset = my->offset;
|
|
_loadForOffset = my->loadForOffset;
|
|
_preloaded = std::move(my->preloaded);
|
|
_count = int(state->list.size());
|
|
_fullCount = my->fullCount;
|
|
_leftToLoad = my->leftToLoad;
|
|
if (my->wasLoading) {
|
|
loadMoreRows();
|
|
}
|
|
PeerListController::restoreState(std::move(state));
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<PeerListRow> ListController::createRestoredRow(
|
|
not_null<PeerData*> peer) {
|
|
if (const auto user = peer->asUser()) {
|
|
return createRow(user);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void ListController::rowClicked(not_null<PeerListRow*> row) {
|
|
_showPeerInfoRequests.fire(row->peer());
|
|
}
|
|
|
|
bool ListController::appendRow(not_null<UserData*> user) {
|
|
if (delegate()->peerListFindRow(user->id)) {
|
|
return false;
|
|
}
|
|
delegate()->peerListAppendRow(createRow(user));
|
|
return true;
|
|
}
|
|
|
|
std::unique_ptr<PeerListRow> ListController::createRow(
|
|
not_null<UserData*> user) const {
|
|
auto row = std::make_unique<PeerListRow>(user);
|
|
row->setCustomStatus(QString());
|
|
return row;
|
|
}
|
|
|
|
void ListController::scrollTo(int y) {
|
|
_scrollToRequests.fire_copy(y);
|
|
}
|
|
|
|
ListController *CreateAnswerRows(
|
|
not_null<Ui::VerticalLayout*> container,
|
|
rpl::producer<int> visibleTop,
|
|
not_null<Main::Session*> session,
|
|
not_null<PollData*> poll,
|
|
FullMsgId context,
|
|
const PollAnswer &answer) {
|
|
using namespace rpl::mappers;
|
|
|
|
if (!answer.votes) {
|
|
return nullptr;
|
|
}
|
|
|
|
const auto delegate = container->lifetime().make_state<ListDelegate>();
|
|
const auto controller = container->lifetime().make_state<ListController>(
|
|
session,
|
|
poll,
|
|
context,
|
|
answer.option);
|
|
|
|
const auto percent = answer.votes * 100 / poll->totalVoters;
|
|
const auto phrase = poll->quiz()
|
|
? tr::lng_polls_answers_count
|
|
: tr::lng_polls_votes_count;
|
|
const auto sampleText = phrase(
|
|
tr::now,
|
|
lt_count_decimal,
|
|
answer.votes);
|
|
const auto &font = st::boxDividerLabel.style.font;
|
|
const auto sampleWidth = font->width(sampleText);
|
|
const auto rightSkip = sampleWidth + font->spacew * 4;
|
|
const auto headerWrap = container->add(
|
|
object_ptr<Ui::RpWidget>(
|
|
container));
|
|
|
|
container->add(object_ptr<Ui::FixedHeightWidget>(
|
|
container,
|
|
st::boxLittleSkip));
|
|
|
|
const auto content = container->add(object_ptr<PeerListContent>(
|
|
container,
|
|
controller,
|
|
st::infoCommonGroupsList));
|
|
delegate->setContent(content);
|
|
controller->setDelegate(delegate);
|
|
|
|
const auto count = (answer.votes <= kFirstPage)
|
|
? answer.votes
|
|
: (kFirstPage - kLeavePreloaded);
|
|
const auto placeholder = container->add(object_ptr<PeerListDummy>(
|
|
container,
|
|
count,
|
|
st::infoCommonGroupsList));
|
|
|
|
controller->count(
|
|
) | rpl::filter(_1 > 0) | rpl::start_with_next([=] {
|
|
delete placeholder;
|
|
}, placeholder->lifetime());
|
|
|
|
const auto header = Ui::CreateChild<Ui::DividerLabel>(
|
|
container.get(),
|
|
object_ptr<Ui::FlatLabel>(
|
|
container,
|
|
(answer.text
|
|
+ QString::fromUtf8(" \xe2\x80\x94 ")
|
|
+ QString::number(percent)
|
|
+ "%"),
|
|
st::boxDividerLabel),
|
|
style::margins(
|
|
st::pollResultsHeaderPadding.left(),
|
|
st::pollResultsHeaderPadding.top(),
|
|
st::pollResultsHeaderPadding.right() + rightSkip,
|
|
st::pollResultsHeaderPadding.bottom()));
|
|
|
|
const auto votes = Ui::CreateChild<Ui::FlatLabel>(
|
|
header,
|
|
phrase(
|
|
lt_count_decimal,
|
|
controller->fullCount() | rpl::map(_1 + 0.)),
|
|
st::pollResultsVotesCount);
|
|
const auto collapse = Ui::CreateChild<Ui::LinkButton>(
|
|
header,
|
|
tr::lng_polls_votes_collapse(tr::now),
|
|
st::defaultLinkButton);
|
|
collapse->setClickedCallback([=] {
|
|
controller->scrollTo(headerWrap->y());
|
|
controller->collapse();
|
|
});
|
|
rpl::combine(
|
|
controller->fullCount(),
|
|
controller->count()
|
|
) | rpl::start_with_next([=](int fullCount, int count) {
|
|
const auto many = (fullCount > kFirstPage)
|
|
&& (count > kFirstPage - kLeavePreloaded);
|
|
collapse->setVisible(many);
|
|
votes->setVisible(!many);
|
|
}, collapse->lifetime());
|
|
|
|
headerWrap->widthValue(
|
|
) | rpl::start_with_next([=](int width) {
|
|
header->resizeToWidth(width);
|
|
votes->moveToRight(
|
|
st::pollResultsHeaderPadding.right(),
|
|
st::pollResultsHeaderPadding.top(),
|
|
width);
|
|
collapse->moveToRight(
|
|
st::pollResultsHeaderPadding.right(),
|
|
st::pollResultsHeaderPadding.top(),
|
|
width);
|
|
}, header->lifetime());
|
|
|
|
header->heightValue(
|
|
) | rpl::start_with_next([=](int height) {
|
|
headerWrap->resize(headerWrap->width(), height);
|
|
}, header->lifetime());
|
|
|
|
const auto more = container->add(
|
|
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
|
|
container,
|
|
object_ptr<Ui::SettingsButton>(
|
|
container,
|
|
tr::lng_polls_show_more(
|
|
lt_count_decimal,
|
|
controller->loadMoreCount() | rpl::map(_1 + 0.),
|
|
Ui::Text::Upper),
|
|
st::pollResultsShowMore)));
|
|
more->entity()->setClickedCallback([=] {
|
|
controller->allowLoadMore();
|
|
});
|
|
controller->loadMoreCount(
|
|
) | rpl::map(_1 > 0) | rpl::start_with_next([=](bool visible) {
|
|
more->toggle(visible, anim::type::instant);
|
|
}, more->lifetime());
|
|
|
|
container->add(object_ptr<Ui::FixedHeightWidget>(
|
|
container,
|
|
st::boxLittleSkip));
|
|
|
|
rpl::combine(
|
|
std::move(visibleTop),
|
|
headerWrap->geometryValue(),
|
|
more->topValue()
|
|
) | rpl::filter([=](int, QRect headerRect, int moreTop) {
|
|
return moreTop >= headerRect.y() + headerRect.height();
|
|
}) | rpl::start_with_next([=](
|
|
int visibleTop,
|
|
QRect headerRect,
|
|
int moreTop) {
|
|
const auto skip = st::pollResultsHeaderPadding.top()
|
|
- st::pollResultsHeaderPadding.bottom();
|
|
const auto top = std::clamp(
|
|
visibleTop - skip,
|
|
headerRect.y(),
|
|
moreTop - headerRect.height());
|
|
header->move(0, top);
|
|
}, header->lifetime());
|
|
|
|
return controller;
|
|
}
|
|
|
|
InnerWidget::InnerWidget(
|
|
QWidget *parent,
|
|
not_null<Controller*> controller,
|
|
not_null<PollData*> poll,
|
|
FullMsgId contextId)
|
|
: RpWidget(parent)
|
|
, _controller(controller)
|
|
, _poll(poll)
|
|
, _contextId(contextId)
|
|
, _content(this) {
|
|
setupContent();
|
|
}
|
|
|
|
void InnerWidget::visibleTopBottomUpdated(
|
|
int visibleTop,
|
|
int visibleBottom) {
|
|
setChildVisibleTopBottom(_content, visibleTop, visibleBottom);
|
|
_visibleTop = visibleTop;
|
|
}
|
|
|
|
void InnerWidget::saveState(not_null<Memento*> memento) {
|
|
auto states = base::flat_map<
|
|
QByteArray,
|
|
std::unique_ptr<PeerListState>>();
|
|
for (const auto &[option, controller] : _sections) {
|
|
states[option] = controller->saveState();
|
|
}
|
|
memento->setListStates(std::move(states));
|
|
}
|
|
|
|
void InnerWidget::restoreState(not_null<Memento*> memento) {
|
|
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 {
|
|
auto desired = 0;
|
|
//auto count = qMax(_user->commonChatsCount(), 1);
|
|
//desired += qMax(count, _list->fullRowsCount())
|
|
// * st::infoCommonGroupsList.item.height;
|
|
return qMax(height(), desired);
|
|
}
|
|
|
|
void InnerWidget::setupContent() {
|
|
const auto quiz = _poll->quiz();
|
|
_content->add(
|
|
object_ptr<Ui::FlatLabel>(
|
|
_content,
|
|
_poll->question,
|
|
st::pollResultsQuestion),
|
|
style::margins{
|
|
st::boxRowPadding.left(),
|
|
0,
|
|
st::boxRowPadding.right(),
|
|
st::boxMediumSkip });
|
|
for (const auto &answer : _poll->answers) {
|
|
const auto session = &_controller->parentController()->session();
|
|
const auto controller = CreateAnswerRows(
|
|
_content,
|
|
_visibleTop.value(),
|
|
session,
|
|
_poll,
|
|
_contextId,
|
|
answer);
|
|
if (!controller) {
|
|
continue;
|
|
}
|
|
controller->showPeerInfoRequests(
|
|
) | rpl::start_to_stream(
|
|
_showPeerInfoRequests,
|
|
lifetime());
|
|
controller->scrollToRequests(
|
|
) | rpl::start_with_next([=](int y) {
|
|
_scrollToRequests.fire({ y, -1 });
|
|
}, lifetime());
|
|
_sections.emplace(answer.option, controller);
|
|
}
|
|
|
|
widthValue(
|
|
) | rpl::start_with_next([=](int newWidth) {
|
|
_content->resizeToWidth(newWidth);
|
|
}, _content->lifetime());
|
|
|
|
_content->heightValue(
|
|
) | rpl::start_with_next([=](int height) {
|
|
resize(width(), height);
|
|
}, _content->lifetime());
|
|
}
|
|
|
|
rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
|
|
return _scrollToRequests.events();
|
|
}
|
|
|
|
auto InnerWidget::showPeerInfoRequests() const
|
|
-> rpl::producer<not_null<PeerData*>> {
|
|
return _showPeerInfoRequests.events();
|
|
}
|
|
|
|
} // namespace Polls
|
|
} // namespace Info
|
|
|