Move poll results to a Info-like layer.

This commit is contained in:
John Preston 2020-01-15 14:53:42 +03:00
parent d0597407d8
commit 8c11e1724a
18 changed files with 458 additions and 108 deletions

View File

@ -188,8 +188,6 @@ PRIVATE
boxes/passcode_box.h boxes/passcode_box.h
boxes/photo_crop_box.cpp boxes/photo_crop_box.cpp
boxes/photo_crop_box.h boxes/photo_crop_box.h
boxes/poll_results_box.cpp
boxes/poll_results_box.h
boxes/rate_call_box.cpp boxes/rate_call_box.cpp
boxes/rate_call_box.h boxes/rate_call_box.h
boxes/report_box.cpp boxes/report_box.cpp
@ -520,6 +518,10 @@ PRIVATE
info/media/info_media_widget.h info/media/info_media_widget.h
info/members/info_members_widget.cpp info/members/info_members_widget.cpp
info/members/info_members_widget.h info/members/info_members_widget.h
info/polls/info_polls_results_inner_widget.cpp
info/polls/info_polls_results_inner_widget.h
info/polls/info_polls_results_widget.cpp
info/polls/info_polls_results_widget.h
info/profile/info_profile_actions.cpp info/profile/info_profile_actions.cpp
info/profile/info_profile_actions.h info/profile/info_profile_actions.h
info/profile/info_profile_cover.cpp info/profile/info_profile_cover.cpp

View File

@ -1,23 +0,0 @@
/*
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
*/
#pragma once
#include "ui/layers/generic_box.h"
class PollData;
class HistoryItem;
namespace Window {
class SessionController;
} // namespace Window
void PollResultsBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> window,
not_null<PollData*> poll,
FullMsgId context);

View File

@ -34,7 +34,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "boxes/report_box.h" #include "boxes/report_box.h"
#include "boxes/sticker_set_box.h" #include "boxes/sticker_set_box.h"
#include "boxes/poll_results_box.h"
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "chat_helpers/stickers.h" #include "chat_helpers/stickers.h"
#include "history/history_widget.h" #include "history/history_widget.h"
@ -2423,8 +2422,7 @@ void HistoryInner::elementStartStickerLoop(
void HistoryInner::elementShowPollResults( void HistoryInner::elementShowPollResults(
not_null<PollData*> poll, not_null<PollData*> poll,
FullMsgId context) { FullMsgId context) {
_controller->window().show( _controller->showPollResults(poll, context);
Box(PollResultsBox, _controller, poll, context));
} }
auto HistoryInner::getSelectionState() const auto HistoryInner::getSelectionState() const

View File

@ -18,7 +18,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/effects/radial_animation.h" #include "ui/effects/radial_animation.h"
#include "ui/effects/ripple_animation.h" #include "ui/effects/ripple_animation.h"
#include "boxes/poll_results_box.h"
#include "data/data_media_types.h" #include "data/data_media_types.h"
#include "data/data_poll.h" #include "data/data_poll.h"
#include "data/data_user.h" #include "data/data_user.h"

View File

@ -266,6 +266,8 @@ Key ContentMemento::key() const {
return Key(Auth().data().peer(peerId)); return Key(Auth().data().peer(peerId));
//} else if (const auto feed = this->feed()) { // #feed //} else if (const auto feed = this->feed()) { // #feed
// return Key(feed); // return Key(feed);
} else if (const auto poll = this->poll()) {
return Key(poll, pollContextId());
} else { } else {
return Settings::Tag{ settingsSelf() }; return Settings::Tag{ settingsSelf() };
} }

View File

@ -123,6 +123,10 @@ public:
//explicit ContentMemento(not_null<Data::Feed*> feed) : _feed(feed) { // #feed //explicit ContentMemento(not_null<Data::Feed*> feed) : _feed(feed) { // #feed
//} //}
explicit ContentMemento(Settings::Tag settings); explicit ContentMemento(Settings::Tag settings);
ContentMemento(not_null<PollData*> poll, FullMsgId contextId)
: _poll(poll)
, _pollContextId(contextId) {
}
virtual object_ptr<ContentWidget> createWidget( virtual object_ptr<ContentWidget> createWidget(
QWidget *parent, QWidget *parent,
@ -141,6 +145,12 @@ public:
UserData *settingsSelf() const { UserData *settingsSelf() const {
return _settingsSelf; return _settingsSelf;
} }
PollData *poll() const {
return _poll;
}
FullMsgId pollContextId() const {
return _pollContextId;
}
Key key() const; Key key() const;
virtual Section section() const = 0; virtual Section section() const = 0;
@ -177,6 +187,9 @@ private:
const PeerId _migratedPeerId = 0; const PeerId _migratedPeerId = 0;
//Data::Feed * const _feed = nullptr; // #feed //Data::Feed * const _feed = nullptr; // #feed
UserData * const _settingsSelf = nullptr; UserData * const _settingsSelf = nullptr;
PollData * const _poll = nullptr;
const FullMsgId _pollContextId;
int _scrollTop = 0; int _scrollTop = 0;
QString _searchFieldQuery; QString _searchFieldQuery;
bool _searchEnabledByContent = false; bool _searchEnabledByContent = false;

View File

@ -19,6 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_media_types.h"
#include "history/history_item.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
@ -46,6 +48,10 @@ Key::Key(not_null<PeerData*> peer) : _value(peer) {
Key::Key(Settings::Tag settings) : _value(settings) { Key::Key(Settings::Tag settings) : _value(settings) {
} }
Key::Key(not_null<PollData*> poll, FullMsgId contextId)
: _value(PollKey{ poll, contextId }) {
}
PeerData *Key::peer() const { PeerData *Key::peer() const {
if (const auto peer = base::get_if<not_null<PeerData*>>(&_value)) { if (const auto peer = base::get_if<not_null<PeerData*>>(&_value)) {
return *peer; return *peer;
@ -67,6 +73,20 @@ UserData *Key::settingsSelf() const {
return nullptr; return nullptr;
} }
PollData *Key::poll() const {
if (const auto data = base::get_if<PollKey>(&_value)) {
return data->poll;
}
return nullptr;
}
FullMsgId Key::pollContextId() const {
if (const auto data = base::get_if<PollKey>(&_value)) {
return data->contextId;
}
return FullMsgId();
}
rpl::producer<SparseIdsMergedSlice> AbstractController::mediaSource( rpl::producer<SparseIdsMergedSlice> AbstractController::mediaSource(
SparseIdsMergedSlice::UniversalMsgId aroundId, SparseIdsMergedSlice::UniversalMsgId aroundId,
int limitBefore, int limitBefore,
@ -106,6 +126,15 @@ PeerId AbstractController::migratedPeerId() const {
return PeerId(0); return PeerId(0);
} }
PollData *AbstractController::poll() const {
if (const auto item = session().data().message(pollContextId())) {
if (const auto media = item->media()) {
return media->poll();
}
}
return nullptr;
}
void AbstractController::showSection( void AbstractController::showSection(
Window::SectionMemento &&memento, Window::SectionMemento &&memento,
const Window::SectionShow &params) { const Window::SectionShow &params) {

View File

@ -33,16 +33,24 @@ public:
Key(not_null<PeerData*> peer); Key(not_null<PeerData*> peer);
//Key(not_null<Data::Feed*> feed); // #feed //Key(not_null<Data::Feed*> feed); // #feed
Key(Settings::Tag settings); Key(Settings::Tag settings);
Key(not_null<PollData*> poll, FullMsgId contextId);
PeerData *peer() const; PeerData *peer() const;
//Data::Feed *feed() const; // #feed //Data::Feed *feed() const; // #feed
UserData *settingsSelf() const; UserData *settingsSelf() const;
PollData *poll() const;
FullMsgId pollContextId() const;
private: private:
struct PollKey {
not_null<PollData*> poll;
FullMsgId contextId;
};
base::variant< base::variant<
not_null<PeerData*>, not_null<PeerData*>,
//not_null<Data::Feed*>, // #feed //not_null<Data::Feed*>, // #feed
Settings::Tag> _value; Settings::Tag,
PollKey> _value;
}; };
@ -60,6 +68,7 @@ public:
Members, Members,
//Channels, // #feed //Channels, // #feed
Settings, Settings,
PollResults,
}; };
using SettingsType = ::Settings::Type; using SettingsType = ::Settings::Type;
using MediaType = Storage::SharedMediaType; using MediaType = Storage::SharedMediaType;
@ -113,6 +122,10 @@ public:
UserData *settingsSelf() const { UserData *settingsSelf() const {
return key().settingsSelf(); return key().settingsSelf();
} }
PollData *poll() const;
FullMsgId pollContextId() const {
return key().pollContextId();
}
virtual void setSearchEnabledByContent(bool enabled) { virtual void setSearchEnabledByContent(bool enabled) {
} }

View File

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/common_groups/info_common_groups_widget.h" #include "info/common_groups/info_common_groups_widget.h"
//#include "info/feed/info_feed_profile_widget.h" // #feed //#include "info/feed/info_feed_profile_widget.h" // #feed
#include "info/settings/info_settings_widget.h" #include "info/settings/info_settings_widget.h"
#include "info/polls/info_polls_results_widget.h"
#include "info/info_section_widget.h" #include "info/info_section_widget.h"
#include "info/info_layer_widget.h" #include "info/info_layer_widget.h"
#include "info/info_controller.h" #include "info/info_controller.h"
@ -42,6 +43,10 @@ Memento::Memento(Settings::Tag settings, Section section)
: Memento(DefaultStack(settings, section)) { : Memento(DefaultStack(settings, section)) {
} }
Memento::Memento(not_null<PollData*> poll, FullMsgId contextId)
: Memento(DefaultStack(poll, contextId)) {
}
Memento::Memento(std::vector<std::unique_ptr<ContentMemento>> stack) Memento::Memento(std::vector<std::unique_ptr<ContentMemento>> stack)
: _stack(std::move(stack)) { : _stack(std::move(stack)) {
} }
@ -72,6 +77,14 @@ std::vector<std::unique_ptr<ContentMemento>> Memento::DefaultStack(
return result; return result;
} }
std::vector<std::unique_ptr<ContentMemento>> Memento::DefaultStack(
not_null<PollData*> poll,
FullMsgId contextId) {
auto result = std::vector<std::unique_ptr<ContentMemento>>();
result.push_back(std::make_unique<Polls::Memento>(poll, contextId));
return result;
}
Section Memento::DefaultSection(not_null<PeerData*> peer) { Section Memento::DefaultSection(not_null<PeerData*> peer) {
if (peer->isSelf()) { if (peer->isSelf()) {
return Section(Section::MediaType::Photo); return Section(Section::MediaType::Photo);

View File

@ -36,6 +36,7 @@ public:
Memento(PeerId peerId, Section section); Memento(PeerId peerId, Section section);
//Memento(not_null<Data::Feed*> feed, Section section); // #feed //Memento(not_null<Data::Feed*> feed, Section section); // #feed
Memento(Settings::Tag settings, Section section); Memento(Settings::Tag settings, Section section);
Memento(not_null<PollData*> poll, FullMsgId contextId);
explicit Memento(std::vector<std::unique_ptr<ContentMemento>> stack); explicit Memento(std::vector<std::unique_ptr<ContentMemento>> stack);
object_ptr<Window::SectionWidget> createWidget( object_ptr<Window::SectionWidget> createWidget(
@ -76,10 +77,13 @@ private:
static std::vector<std::unique_ptr<ContentMemento>> DefaultStack( static std::vector<std::unique_ptr<ContentMemento>> DefaultStack(
Settings::Tag settings, Settings::Tag settings,
Section section); Section section);
static std::vector<std::unique_ptr<ContentMemento>> DefaultStack(
not_null<PollData*> poll,
FullMsgId contextId);
//static std::unique_ptr<ContentMemento> DefaultContent( // #feed //static std::unique_ptr<ContentMemento> DefaultContent( // #feed
// not_null<Data::Feed*> feed, // not_null<Data::Feed*> feed,
// Section section); // Section section);
static std::unique_ptr<ContentMemento> DefaultContent( static std::unique_ptr<ContentMemento> DefaultContent(
PeerId peerId, PeerId peerId,
Section section); Section section);

View File

@ -628,6 +628,11 @@ rpl::producer<QString> TitleValue(
return tr::lng_settings_section_call_settings(); return tr::lng_settings_section_call_settings();
} }
Unexpected("Bad settings type in Info::TitleValue()"); Unexpected("Bad settings type in Info::TitleValue()");
case Section::Type::PollResults:
return key.poll()->quiz()
? tr::lng_polls_quiz_results_title()
: tr::lng_polls_poll_results_title();
} }
Unexpected("Bad section type in Info::TitleValue()"); Unexpected("Bad section type in Info::TitleValue()");
} }

View File

@ -5,8 +5,9 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "boxes/poll_results_box.h" #include "info/polls/info_polls_results_inner_widget.h"
#include "info/info_controller.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "data/data_poll.h" #include "data/data_poll.h"
#include "data/data_peer.h" #include "data/data_peer.h"
@ -14,11 +15,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/padding_wrap.h" #include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "boxes/peer_list_box.h" #include "boxes/peer_list_box.h"
#include "window/window_session_controller.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
@ -27,12 +28,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_info.h" #include "styles/style_info.h"
namespace Info {
namespace Polls {
namespace { namespace {
constexpr auto kFirstPage = 10; constexpr auto kFirstPage = 10;
constexpr auto kPerPage = 100; constexpr auto kPerPage = 100;
class Delegate final : public PeerListContentDelegate { class ListDelegate final : public PeerListContentDelegate {
public: public:
void peerListSetTitle(rpl::producer<QString> title) override; void peerListSetTitle(rpl::producer<QString> title) override;
void peerListSetAdditionalTitle(rpl::producer<QString> title) override; void peerListSetAdditionalTitle(rpl::producer<QString> title) override;
@ -48,10 +51,10 @@ public:
}; };
class Controller final : public PeerListController { class ListController final : public PeerListController {
public: public:
Controller( ListController(
not_null<Window::SessionController*> window, not_null<Main::Session*> session,
not_null<PollData*> poll, not_null<PollData*> poll,
FullMsgId context, FullMsgId context,
QByteArray option); QByteArray option);
@ -63,11 +66,13 @@ public:
void allowLoadAll(); void allowLoadAll();
rpl::producer<not_null<PeerData*>> showPeerInfoRequests() const;
private: 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;
const not_null<Window::SessionController*> _window; const not_null<Main::Session*> _session;
const not_null<PollData*> _poll; const not_null<PollData*> _poll;
const FullMsgId _context; const FullMsgId _context;
const QByteArray _option; const QByteArray _option;
@ -80,62 +85,65 @@ private:
bool _allLoaded = false; bool _allLoaded = false;
bool _loadingAll = false; bool _loadingAll = false;
rpl::event_stream<not_null<PeerData*>> _showPeerInfoRequests;
}; };
void Delegate::peerListSetTitle(rpl::producer<QString> title) { void ListDelegate::peerListSetTitle(rpl::producer<QString> title) {
} }
void Delegate::peerListSetAdditionalTitle(rpl::producer<QString> title) { void ListDelegate::peerListSetAdditionalTitle(rpl::producer<QString> title) {
} }
bool Delegate::peerListIsRowSelected(not_null<PeerData*> peer) { bool ListDelegate::peerListIsRowSelected(not_null<PeerData*> peer) {
return false; return false;
} }
int Delegate::peerListSelectedRowsCount() { int ListDelegate::peerListSelectedRowsCount() {
return 0; return 0;
} }
std::vector<not_null<PeerData*>> Delegate::peerListCollectSelectedRows() { auto ListDelegate::peerListCollectSelectedRows()
-> std::vector<not_null<PeerData*>> {
return {}; return {};
} }
void Delegate::peerListScrollToTop() { void ListDelegate::peerListScrollToTop() {
} }
void Delegate::peerListAddSelectedRowInBunch(not_null<PeerData*> peer) { void ListDelegate::peerListAddSelectedRowInBunch(not_null<PeerData*> peer) {
Unexpected("Item selection in Info::Profile::Members."); Unexpected("Item selection in Info::Profile::Members.");
} }
void Delegate::peerListFinishSelectedRowsBunch() { void ListDelegate::peerListFinishSelectedRowsBunch() {
} }
void Delegate::peerListSetDescription( void ListDelegate::peerListSetDescription(
object_ptr<Ui::FlatLabel> description) { object_ptr<Ui::FlatLabel> description) {
description.destroy(); description.destroy();
} }
Controller::Controller( ListController::ListController(
not_null<Window::SessionController*> window, not_null<Main::Session*> session,
not_null<PollData*> poll, not_null<PollData*> poll,
FullMsgId context, FullMsgId context,
QByteArray option) QByteArray option)
: _window(window) : _session(session)
, _poll(poll) , _poll(poll)
, _context(context) , _context(context)
, _option(option) , _option(option)
, _api(_window->session().api().instance()) { , _api(_session->api().instance()) {
} }
Main::Session &Controller::session() const { Main::Session &ListController::session() const {
return _window->session(); return *_session;
} }
void Controller::prepare() { void ListController::prepare() {
delegate()->peerListRefreshRows(); delegate()->peerListRefreshRows();
} }
void Controller::loadMoreRows() { void ListController::loadMoreRows() {
if (_loadRequestId if (_loadRequestId
|| _allLoaded || _allLoaded
|| (!_loadingAll && !_offset.isEmpty())) { || (!_loadingAll && !_offset.isEmpty())) {
@ -180,16 +188,21 @@ void Controller::loadMoreRows() {
}).send(); }).send();
} }
void Controller::allowLoadAll() { void ListController::allowLoadAll() {
_loadingAll = true; _loadingAll = true;
loadMoreRows(); loadMoreRows();
} }
void Controller::rowClicked(not_null<PeerListRow*> row) { auto ListController::showPeerInfoRequests() const
_window->showPeerHistory(row->peer(), Window::SectionShow::Way::Forward); -> rpl::producer<not_null<PeerData*>> {
return _showPeerInfoRequests.events();
} }
bool Controller::appendRow(not_null<UserData*> user) { void ListController::rowClicked(not_null<PeerListRow*> row) {
_showPeerInfoRequests.fire(row->peer());
}
bool ListController::appendRow(not_null<UserData*> user) {
if (delegate()->peerListFindRow(user->id)) { if (delegate()->peerListFindRow(user->id)) {
return false; return false;
} }
@ -197,21 +210,21 @@ bool Controller::appendRow(not_null<UserData*> user) {
return true; return true;
} }
std::unique_ptr<PeerListRow> Controller::createRow( std::unique_ptr<PeerListRow> ListController::createRow(
not_null<UserData*> user) const { not_null<UserData*> user) const {
auto row = std::make_unique<PeerListRow>(user); auto row = std::make_unique<PeerListRow>(user);
row->setCustomStatus(QString()); row->setCustomStatus(QString());
return row; return row;
} }
void CreateAnswerRows( ListController *CreateAnswerRows(
not_null<Ui::GenericBox*> box, not_null<Ui::VerticalLayout*> container,
not_null<Window::SessionController*> window, not_null<Main::Session*> session,
not_null<PollData*> poll, not_null<PollData*> poll,
FullMsgId context, FullMsgId context,
const PollAnswer &answer) { const PollAnswer &answer) {
if (!answer.votes) { if (!answer.votes) {
return; return nullptr;
} }
const auto percent = answer.votes * 100 / poll->totalVoters; const auto percent = answer.votes * 100 / poll->totalVoters;
@ -224,12 +237,12 @@ void CreateAnswerRows(
const auto &font = st::boxDividerLabel.style.font; const auto &font = st::boxDividerLabel.style.font;
const auto rightWidth = font->width(rightText); const auto rightWidth = font->width(rightText);
const auto rightSkip = rightWidth + font->spacew * 4; const auto rightSkip = rightWidth + font->spacew * 4;
const auto header = box->addRow( const auto header = container->add(
object_ptr<Ui::DividerLabel>( object_ptr<Ui::DividerLabel>(
box, container,
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
box, container,
(answer.text.repeated(20) (answer.text
+ QString::fromUtf8(" \xe2\x80\x94 ") + QString::fromUtf8(" \xe2\x80\x94 ")
+ QString::number(percent) + QString::number(percent)
+ "%"), + "%"),
@ -238,8 +251,7 @@ void CreateAnswerRows(
st::pollResultsHeaderPadding.left(), st::pollResultsHeaderPadding.left(),
st::pollResultsHeaderPadding.top(), st::pollResultsHeaderPadding.top(),
st::pollResultsHeaderPadding.right() + rightSkip, st::pollResultsHeaderPadding.right() + rightSkip,
st::pollResultsHeaderPadding.bottom())), st::pollResultsHeaderPadding.bottom())));
style::margins());
const auto votes = Ui::CreateChild<Ui::FlatLabel>( const auto votes = Ui::CreateChild<Ui::FlatLabel>(
header, header,
rightText, rightText,
@ -251,72 +263,128 @@ void CreateAnswerRows(
st::pollResultsHeaderPadding.top(), st::pollResultsHeaderPadding.top(),
width); width);
}, votes->lifetime()); }, votes->lifetime());
box->addRow(object_ptr<Ui::FixedHeightWidget>(box, st::boxLittleSkip)); container->add(object_ptr<Ui::FixedHeightWidget>(
container,
st::boxLittleSkip));
const auto delegate = box->lifetime().make_state<Delegate>(); const auto delegate = container->lifetime().make_state<ListDelegate>();
const auto controller = box->lifetime().make_state<Controller>( const auto controller = container->lifetime().make_state<ListController>(
window, session,
poll, poll,
context, context,
answer.option); answer.option);
const auto content = box->addRow( const auto content = container->add(object_ptr<PeerListContent>(
object_ptr<PeerListContent>( container,
box, controller,
controller, st::infoCommonGroupsList));
st::infoCommonGroupsList),
style::margins());
delegate->setContent(content); delegate->setContent(content);
controller->setDelegate(delegate); controller->setDelegate(delegate);
const auto more = box->addRow( const auto more = container->add(
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>( object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
box, container,
object_ptr<Ui::SettingsButton>( object_ptr<Ui::SettingsButton>(
box, container,
tr::lng_polls_show_more( tr::lng_polls_show_more(
lt_count_decimal, lt_count_decimal,
rpl::single(answer.votes + 0.), rpl::single(answer.votes + 0.),
Ui::Text::Upper), Ui::Text::Upper),
st::pollResultsShowMore)), st::pollResultsShowMore)));
style::margins());
more->toggle(answer.votes > kFirstPage, anim::type::instant); more->toggle(answer.votes > kFirstPage, anim::type::instant);
more->entity()->setClickedCallback([=] { more->entity()->setClickedCallback([=] {
controller->allowLoadAll(); controller->allowLoadAll();
more->hide(anim::type::instant); more->hide(anim::type::instant);
}); });
box->addRow(object_ptr<Ui::FixedHeightWidget>(box, st::boxLittleSkip)); container->add(object_ptr<Ui::FixedHeightWidget>(
container,
st::boxLittleSkip));
return controller;
} }
} // namespace } // namespace
void PollResultsBox( InnerWidget::InnerWidget(
not_null<Ui::GenericBox*> box, QWidget *parent,
not_null<Window::SessionController*> window, not_null<Controller*> controller,
not_null<PollData*> poll, not_null<PollData*> poll,
FullMsgId context) { FullMsgId contextId)
const auto quiz = poll->quiz(); : RpWidget(parent)
box->setWidth(st::boxWideWidth); , _controller(controller)
box->setTitle(quiz , _poll(poll)
? tr::lng_polls_quiz_results_title() , _contextId(contextId)
: tr::lng_polls_poll_results_title()); , _content(setupContent(this)) {
box->setAdditionalTitle((quiz }
? tr::lng_polls_answers_count
: tr::lng_polls_votes_count)( void InnerWidget::visibleTopBottomUpdated(
lt_count_decimal, int visibleTop,
rpl::single(poll->totalVoters * 1.))); int visibleBottom) {
box->addRow( setChildVisibleTopBottom(_content, visibleTop, visibleBottom);
}
void InnerWidget::saveState(not_null<Memento*> memento) {
//memento->setListState(_listController->saveState());
}
void InnerWidget::restoreState(not_null<Memento*> memento) {
//_listController->restoreState(memento->listState());
}
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);
}
object_ptr<Ui::VerticalLayout> InnerWidget::setupContent(
RpWidget *parent) {
auto result = object_ptr<Ui::VerticalLayout>(parent);
const auto quiz = _poll->quiz();
result->add(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
box, result,
poll->question, _poll->question,
st::pollResultsQuestion), st::pollResultsQuestion),
style::margins{ style::margins{
st::boxRowPadding.left(), st::boxRowPadding.left(),
0, 0,
st::boxRowPadding.right(), st::boxRowPadding.right(),
st::boxMediumSkip }); st::boxMediumSkip });
for (const auto &answer : poll->answers) { for (const auto &answer : _poll->answers) {
CreateAnswerRows(box, window, poll, context, answer); const auto session = &_controller->parentController()->session();
const auto controller = CreateAnswerRows(
result,
session,
_poll,
_contextId,
answer);
if (controller) {
controller->showPeerInfoRequests(
) | rpl::start_to_stream(
_showPeerInfoRequests,
lifetime());
}
} }
box->addButton(tr::lng_close(), [=] { box->closeBox(); }); parent->widthValue(
) | rpl::start_with_next([content = result.data()](int newWidth) {
content->resizeToWidth(newWidth);
}, result->lifetime());
result->heightValue(
) | rpl::start_with_next([=](int height) {
parent->resize(parent->width(), height);
}, result->lifetime());
return result;
} }
auto InnerWidget::showPeerInfoRequests() const
-> rpl::producer<not_null<PeerData*>> {
return _showPeerInfoRequests.events();
}
} // namespace Polls
} // namespace Info

View File

@ -0,0 +1,65 @@
/*
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
*/
#pragma once
#include "ui/rp_widget.h"
#include "base/object_ptr.h"
namespace Ui {
class VerticalLayout;
} // namespace Ui
namespace Info {
class Controller;
namespace Polls {
class Memento;
class InnerWidget final : public Ui::RpWidget {
public:
InnerWidget(
QWidget *parent,
not_null<Controller*> controller,
not_null<PollData*> poll,
FullMsgId contextId);
[[nodiscard]] not_null<PollData*> poll() const {
return _poll;
}
[[nodiscard]] FullMsgId contextId() const {
return _contextId;
}
[[nodiscard]] auto showPeerInfoRequests() const
-> rpl::producer<not_null<PeerData*>>;
[[nodiscard]] int desiredHeight() const;
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
private:
object_ptr<Ui::VerticalLayout> setupContent(RpWidget *parent);
not_null<Controller*> _controller;
not_null<PollData*> _poll;
FullMsgId _contextId;
object_ptr<Ui::VerticalLayout> _content;
rpl::event_stream<not_null<PeerData*>> _showPeerInfoRequests;
};
} // namespace Polls
} // namespace Info

View File

@ -0,0 +1,93 @@
/*
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_widget.h"
#include "info/polls/info_polls_results_inner_widget.h"
namespace Info {
namespace Polls {
Memento::Memento(not_null<PollData*> poll, FullMsgId contextId)
: ContentMemento(poll, contextId) {
}
Section Memento::section() const {
return Section(Section::Type::PollResults);
}
object_ptr<ContentWidget> Memento::createWidget(
QWidget *parent,
not_null<Controller*> controller,
const QRect &geometry) {
auto result = object_ptr<Widget>(parent, controller);
result->setInternalState(geometry, this);
return result;
}
Memento::~Memento() = default;
Widget::Widget(QWidget *parent, not_null<Controller*> controller)
: ContentWidget(parent, controller)
, _inner(setInnerWidget(
object_ptr<InnerWidget>(
this,
controller,
controller->poll(),
controller->pollContextId()))) {
_inner->showPeerInfoRequests(
) | rpl::start_with_next([=](not_null<PeerData*> peer) {
controller->showPeerInfo(peer);
}, _inner->lifetime());
controller->setCanSaveChanges(rpl::single(false));
}
not_null<PollData*> Widget::poll() const {
return _inner->poll();
}
FullMsgId Widget::contextId() const {
return _inner->contextId();
}
bool Widget::showInternal(not_null<ContentMemento*> memento) {
//if (const auto myMemento = dynamic_cast<Memento*>(memento.get())) {
// Assert(myMemento->self() == self());
// if (_inner->showInternal(myMemento)) {
// return true;
// }
//}
return false;
}
void Widget::setInternalState(
const QRect &geometry,
not_null<Memento*> memento) {
setGeometry(geometry);
Ui::SendPendingMoveResizeEvents(this);
restoreState(memento);
}
std::unique_ptr<ContentMemento> Widget::doCreateMemento() {
auto result = std::make_unique<Memento>(poll(), contextId());
saveState(result.get());
return result;
}
void Widget::saveState(not_null<Memento*> memento) {
memento->setScrollTop(scrollTopSave());
}
void Widget::restoreState(not_null<Memento*> memento) {
const auto scrollTop = memento->scrollTop();
scrollTopRestore(memento->scrollTop());
}
} // namespace Polls
} // namespace Info

View File

@ -0,0 +1,58 @@
/*
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
*/
#pragma once
#include "info/info_content_widget.h"
#include "info/info_controller.h"
namespace Info {
namespace Polls {
class InnerWidget;
class Memento final : public ContentMemento {
public:
Memento(not_null<PollData*> poll, FullMsgId contextId);
object_ptr<ContentWidget> createWidget(
QWidget *parent,
not_null<Controller*> controller,
const QRect &geometry) override;
Section section() const override;
~Memento();
};
class Widget final : public ContentWidget {
public:
Widget(QWidget *parent, not_null<Controller*> controller);
[[nodiscard]] not_null<PollData*> poll() const;
[[nodiscard]] FullMsgId contextId() const;
bool showInternal(
not_null<ContentMemento*> memento) override;
void setInternalState(
const QRect &geometry,
not_null<Memento*> memento);
private:
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);
std::unique_ptr<ContentMemento> doCreateMemento() override;
not_null<InnerWidget*> _inner;
};
} // namespace Settings
} // namespace Info

View File

@ -20,7 +20,6 @@ namespace Settings {
using Type = Section::SettingsType; using Type = Section::SettingsType;
struct Tag; struct Tag;
class InnerWidget;
class Memento final : public ContentMemento { class Memento final : public ContentMemento {
public: public:

View File

@ -100,6 +100,13 @@ void SessionNavigation::showSettings(const SectionShow &params) {
showSettings(Settings::Type::Main, params); showSettings(Settings::Type::Main, params);
} }
void SessionNavigation::showPollResults(
not_null<PollData*> poll,
FullMsgId contextId,
const SectionShow &params) {
showSection(Info::Memento(poll, contextId), params);
}
SessionController::SessionController( SessionController::SessionController(
not_null<Main::Session*> session, not_null<Main::Session*> session,
not_null<Controller*> window) not_null<Controller*> window)

View File

@ -148,6 +148,11 @@ public:
const SectionShow &params = SectionShow()); const SectionShow &params = SectionShow());
void showSettings(const SectionShow &params = SectionShow()); void showSettings(const SectionShow &params = SectionShow());
void showPollResults(
not_null<PollData*> poll,
FullMsgId contextId,
const SectionShow &params = SectionShow());
virtual ~SessionNavigation() = default; virtual ~SessionNavigation() = default;
private: private: