mirror of https://github.com/procxx/kepka.git
Allow collapsing expanded poll results.
This commit is contained in:
parent
e6c005dcba
commit
ac650b08fd
|
@ -2204,6 +2204,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_polls_quiz_results_title" = "Quiz results";
|
"lng_polls_quiz_results_title" = "Quiz results";
|
||||||
"lng_polls_show_more#one" = "Show {count} more voter";
|
"lng_polls_show_more#one" = "Show {count} more voter";
|
||||||
"lng_polls_show_more#other" = "Show {count} more voters";
|
"lng_polls_show_more#other" = "Show {count} more voters";
|
||||||
|
"lng_polls_votes_collapse" = "Collapse";
|
||||||
|
|
||||||
"lng_outdated_title" = "PLEASE UPDATE YOUR OPERATING SYSTEM.";
|
"lng_outdated_title" = "PLEASE UPDATE YOUR OPERATING SYSTEM.";
|
||||||
"lng_outdated_soon" = "Otherwise, Telegram Desktop will stop updating on {date}.";
|
"lng_outdated_soon" = "Otherwise, Telegram Desktop will stop updating on {date}.";
|
||||||
|
|
|
@ -165,9 +165,11 @@ public:
|
||||||
void loadMoreRows() override;
|
void loadMoreRows() override;
|
||||||
|
|
||||||
void allowLoadMore();
|
void allowLoadMore();
|
||||||
|
void collapse();
|
||||||
|
|
||||||
[[nodiscard]] auto showPeerInfoRequests() const
|
[[nodiscard]] auto showPeerInfoRequests() const
|
||||||
-> rpl::producer<not_null<PeerData*>>;
|
-> rpl::producer<not_null<PeerData*>>;
|
||||||
|
[[nodiscard]] rpl::producer<int> scrollToRequests() const;
|
||||||
[[nodiscard]] rpl::producer<int> count() const;
|
[[nodiscard]] rpl::producer<int> count() const;
|
||||||
[[nodiscard]] rpl::producer<int> fullCount() const;
|
[[nodiscard]] rpl::producer<int> fullCount() const;
|
||||||
[[nodiscard]] rpl::producer<int> loadMoreCount() const;
|
[[nodiscard]] rpl::producer<int> loadMoreCount() const;
|
||||||
|
@ -178,6 +180,8 @@ public:
|
||||||
std::unique_ptr<PeerListRow> createRestoredRow(
|
std::unique_ptr<PeerListRow> createRestoredRow(
|
||||||
not_null<PeerData*> peer) override;
|
not_null<PeerData*> peer) override;
|
||||||
|
|
||||||
|
void scrollTo(int y);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SavedState : SavedStateBase {
|
struct SavedState : SavedStateBase {
|
||||||
QString offset;
|
QString offset;
|
||||||
|
@ -191,6 +195,8 @@ private:
|
||||||
bool appendRow(not_null<UserData*> user);
|
bool appendRow(not_null<UserData*> user);
|
||||||
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) const;
|
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) const;
|
||||||
void addPreloaded();
|
void addPreloaded();
|
||||||
|
bool addPreloadedPage();
|
||||||
|
void preloadedAdded();
|
||||||
|
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
const not_null<PollData*> _poll;
|
const not_null<PollData*> _poll;
|
||||||
|
@ -208,6 +214,7 @@ private:
|
||||||
rpl::variable<int> _leftToLoad;
|
rpl::variable<int> _leftToLoad;
|
||||||
|
|
||||||
rpl::event_stream<not_null<PeerData*>> _showPeerInfoRequests;
|
rpl::event_stream<not_null<PeerData*>> _showPeerInfoRequests;
|
||||||
|
rpl::event_stream<int> _scrollToRequests;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -280,15 +287,15 @@ void ListController::loadMoreRows() {
|
||||||
}
|
}
|
||||||
return data.vcount().v;
|
return data.vcount().v;
|
||||||
});
|
});
|
||||||
_count = delegate()->peerListFullRowsCount();
|
|
||||||
if (_offset.isEmpty()) {
|
if (_offset.isEmpty()) {
|
||||||
addPreloaded();
|
addPreloaded();
|
||||||
_fullCount = delegate()->peerListFullRowsCount();
|
_fullCount = delegate()->peerListFullRowsCount();
|
||||||
_leftToLoad = 0;
|
_leftToLoad = 0;
|
||||||
} else {
|
} else {
|
||||||
delegate()->peerListRefreshRows();
|
_count = delegate()->peerListFullRowsCount();
|
||||||
_fullCount = count;
|
_fullCount = count;
|
||||||
_leftToLoad = count - delegate()->peerListFullRowsCount();
|
_leftToLoad = count - delegate()->peerListFullRowsCount();
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
}
|
}
|
||||||
_loadRequestId = 0;
|
_loadRequestId = 0;
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
|
@ -297,16 +304,58 @@ void ListController::loadMoreRows() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListController::allowLoadMore() {
|
void ListController::allowLoadMore() {
|
||||||
_loadForOffset = _offset;
|
if (!addPreloadedPage()) {
|
||||||
addPreloaded();
|
_loadForOffset = _offset;
|
||||||
loadMoreRows();
|
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() {
|
void ListController::addPreloaded() {
|
||||||
for (const auto user : base::take(_preloaded)) {
|
for (const auto user : base::take(_preloaded)) {
|
||||||
appendRow(user);
|
appendRow(user);
|
||||||
}
|
}
|
||||||
_leftToLoad = _fullCount.current() - delegate()->peerListFullRowsCount();
|
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();
|
delegate()->peerListRefreshRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,6 +364,10 @@ auto ListController::showPeerInfoRequests() const
|
||||||
return _showPeerInfoRequests.events();
|
return _showPeerInfoRequests.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<int> ListController::scrollToRequests() const {
|
||||||
|
return _scrollToRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<int> ListController::count() const {
|
rpl::producer<int> ListController::count() const {
|
||||||
return _count.value();
|
return _count.value();
|
||||||
}
|
}
|
||||||
|
@ -399,6 +452,10 @@ std::unique_ptr<PeerListRow> ListController::createRow(
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListController::scrollTo(int y) {
|
||||||
|
_scrollToRequests.fire_copy(y);
|
||||||
|
}
|
||||||
|
|
||||||
ListController *CreateAnswerRows(
|
ListController *CreateAnswerRows(
|
||||||
not_null<Ui::VerticalLayout*> container,
|
not_null<Ui::VerticalLayout*> container,
|
||||||
rpl::producer<int> visibleTop,
|
rpl::producer<int> visibleTop,
|
||||||
|
@ -479,6 +536,23 @@ ListController *CreateAnswerRows(
|
||||||
lt_count_decimal,
|
lt_count_decimal,
|
||||||
controller->fullCount() | rpl::map(_1 + 0.)),
|
controller->fullCount() | rpl::map(_1 + 0.)),
|
||||||
st::pollResultsVotesCount);
|
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(
|
headerWrap->widthValue(
|
||||||
) | rpl::start_with_next([=](int width) {
|
) | rpl::start_with_next([=](int width) {
|
||||||
|
@ -487,6 +561,10 @@ ListController *CreateAnswerRows(
|
||||||
st::pollResultsHeaderPadding.right(),
|
st::pollResultsHeaderPadding.right(),
|
||||||
st::pollResultsHeaderPadding.top(),
|
st::pollResultsHeaderPadding.top(),
|
||||||
width);
|
width);
|
||||||
|
collapse->moveToRight(
|
||||||
|
st::pollResultsHeaderPadding.right(),
|
||||||
|
st::pollResultsHeaderPadding.top(),
|
||||||
|
width);
|
||||||
}, header->lifetime());
|
}, header->lifetime());
|
||||||
|
|
||||||
header->heightValue(
|
header->heightValue(
|
||||||
|
@ -520,7 +598,9 @@ ListController *CreateAnswerRows(
|
||||||
std::move(visibleTop),
|
std::move(visibleTop),
|
||||||
headerWrap->geometryValue(),
|
headerWrap->geometryValue(),
|
||||||
more->topValue()
|
more->topValue()
|
||||||
) | rpl::start_with_next([=](
|
) | rpl::filter([=](int, QRect headerRect, int moreTop) {
|
||||||
|
return moreTop >= headerRect.y() + headerRect.height();
|
||||||
|
}) | rpl::start_with_next([=](
|
||||||
int visibleTop,
|
int visibleTop,
|
||||||
QRect headerRect,
|
QRect headerRect,
|
||||||
int moreTop) {
|
int moreTop) {
|
||||||
|
@ -612,6 +692,10 @@ void InnerWidget::setupContent() {
|
||||||
) | rpl::start_to_stream(
|
) | rpl::start_to_stream(
|
||||||
_showPeerInfoRequests,
|
_showPeerInfoRequests,
|
||||||
lifetime());
|
lifetime());
|
||||||
|
controller->scrollToRequests(
|
||||||
|
) | rpl::start_with_next([=](int y) {
|
||||||
|
_scrollToRequests.fire({ y, -1 });
|
||||||
|
}, lifetime());
|
||||||
_sections.emplace(answer.option, controller);
|
_sections.emplace(answer.option, controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,6 +710,10 @@ void InnerWidget::setupContent() {
|
||||||
}, _content->lifetime());
|
}, _content->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
|
||||||
|
return _scrollToRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
auto InnerWidget::showPeerInfoRequests() const
|
auto InnerWidget::showPeerInfoRequests() const
|
||||||
-> rpl::producer<not_null<PeerData*>> {
|
-> rpl::producer<not_null<PeerData*>> {
|
||||||
return _showPeerInfoRequests.events();
|
return _showPeerInfoRequests.events();
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
#include "ui/widgets/scroll_area.h"
|
||||||
#include "base/object_ptr.h"
|
#include "base/object_ptr.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
@ -38,6 +39,9 @@ public:
|
||||||
return _contextId;
|
return _contextId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto scrollToRequests() const
|
||||||
|
-> rpl::producer<Ui::ScrollToRequest>;
|
||||||
|
|
||||||
[[nodiscard]] auto showPeerInfoRequests() const
|
[[nodiscard]] auto showPeerInfoRequests() const
|
||||||
-> rpl::producer<not_null<PeerData*>>;
|
-> rpl::producer<not_null<PeerData*>>;
|
||||||
|
|
||||||
|
@ -58,9 +62,11 @@ private:
|
||||||
not_null<PollData*> _poll;
|
not_null<PollData*> _poll;
|
||||||
FullMsgId _contextId;
|
FullMsgId _contextId;
|
||||||
object_ptr<Ui::VerticalLayout> _content;
|
object_ptr<Ui::VerticalLayout> _content;
|
||||||
|
base::flat_map<QByteArray, not_null<ListController*>> _sections;
|
||||||
|
|
||||||
|
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
|
||||||
rpl::event_stream<not_null<PeerData*>> _showPeerInfoRequests;
|
rpl::event_stream<not_null<PeerData*>> _showPeerInfoRequests;
|
||||||
rpl::variable<int> _visibleTop = 0;
|
rpl::variable<int> _visibleTop = 0;
|
||||||
base::flat_map<QByteArray, not_null<ListController*>> _sections;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,10 @@ Widget::Widget(QWidget *parent, not_null<Controller*> controller)
|
||||||
) | rpl::start_with_next([=](not_null<PeerData*> peer) {
|
) | rpl::start_with_next([=](not_null<PeerData*> peer) {
|
||||||
controller->showPeerInfo(peer);
|
controller->showPeerInfo(peer);
|
||||||
}, _inner->lifetime());
|
}, _inner->lifetime());
|
||||||
|
_inner->scrollToRequests(
|
||||||
|
) | rpl::start_with_next([=](const Ui::ScrollToRequest &request) {
|
||||||
|
scrollTo(request);
|
||||||
|
}, _inner->lifetime());
|
||||||
|
|
||||||
controller->setCanSaveChanges(rpl::single(false));
|
controller->setCanSaveChanges(rpl::single(false));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue