From afff7634f9004d9727a14844eac7a4d620e64435 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 9 Jan 2020 20:24:54 +0300 Subject: [PATCH] Display last voters userpics. --- .../SourceFiles/boxes/create_poll_box.cpp | 2 +- Telegram/SourceFiles/data/data_peer.h | 2 +- Telegram/SourceFiles/data/data_poll.cpp | 28 ++++++++++- Telegram/SourceFiles/data/data_poll.h | 8 +++- Telegram/SourceFiles/data/data_session.cpp | 2 +- Telegram/SourceFiles/history/history.style | 7 ++- .../history/view/media/history_view_poll.cpp | 46 ++++++++++++++++++- .../history/view/media/history_view_poll.h | 9 ++++ 8 files changed, 95 insertions(+), 9 deletions(-) diff --git a/Telegram/SourceFiles/boxes/create_poll_box.cpp b/Telegram/SourceFiles/boxes/create_poll_box.cpp index 11d44d311..66b1e32cc 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.cpp +++ b/Telegram/SourceFiles/boxes/create_poll_box.cpp @@ -706,7 +706,7 @@ object_ptr CreatePollBox::setupContent() { }; const auto collectResult = [=] { - auto result = PollData(id); + auto result = PollData(&_session->data(), id); result.question = question->getLastText().trimmed(); result.answers = options->toPollAnswers(); return result; diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index fcb82c2c4..4df31d110 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -366,7 +366,7 @@ private: static constexpr auto kUnknownPhotoId = PhotoId(0xFFFFFFFFFFFFFFFFULL); - not_null _owner; + const not_null _owner; ImagePtr _userpic; PhotoId _userpicPhotoId = kUnknownPhotoId; diff --git a/Telegram/SourceFiles/data/data_poll.cpp b/Telegram/SourceFiles/data/data_poll.cpp index 52e591c06..586c097d3 100644 --- a/Telegram/SourceFiles/data/data_poll.cpp +++ b/Telegram/SourceFiles/data/data_poll.cpp @@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_poll.h" #include "apiwrap.h" +#include "data/data_user.h" +#include "data/data_session.h" #include "main/main_session.h" namespace { @@ -34,7 +36,9 @@ PollAnswer *AnswerByOption( } // namespace -PollData::PollData(PollId id) : id(id) { +PollData::PollData(not_null owner, PollId id) +: id(id) +, _owner(owner) { } bool PollData::applyChanges(const MTPDpoll &poll) { @@ -96,6 +100,26 @@ bool PollData::applyResults(const MTPPollResults &results) { } } } + if (const auto recent = results.vrecent_voters()) { + const auto recentChanged = !ranges::equal( + recentVoters, + recent->v, + ranges::equal_to(), + &UserData::id, + &MTPint::v); + if (recentChanged) { + changed = true; + recentVoters = ranges::view::all( + recent->v + ) | ranges::view::transform([&](MTPint userId) { + return _owner->userLoaded(userId.v); + }) | ranges::view::filter([](UserData *user) { + return user != nullptr; + }) | ranges::view::transform([](UserData *user) { + return not_null(user); + }) | ranges::to_vector; + } + } if (!changed) { return false; } @@ -112,7 +136,7 @@ void PollData::checkResultsReload(not_null item, crl::time now) { return; } lastResultsUpdate = now; - Auth().api().reloadPollResults(item); + _owner->session().api().reloadPollResults(item); } PollAnswer *PollData::answerByOption(const QByteArray &option) { diff --git a/Telegram/SourceFiles/data/data_poll.h b/Telegram/SourceFiles/data/data_poll.h index 4fa266a80..13ff92bd1 100644 --- a/Telegram/SourceFiles/data/data_poll.h +++ b/Telegram/SourceFiles/data/data_poll.h @@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +namespace Data { +class Session; +} // namespace Data + struct PollAnswer { QString text; QByteArray option; @@ -25,7 +29,7 @@ inline bool operator!=(const PollAnswer &a, const PollAnswer &b) { } struct PollData { - explicit PollData(PollId id); + PollData(not_null owner, PollId id); enum class Flag { Closed = 0x01, @@ -54,6 +58,7 @@ struct PollData { PollId id = 0; QString question; std::vector answers; + std::vector> recentVoters; int totalVoters = 0; QByteArray sendingVote; crl::time lastResultsUpdate = 0; @@ -67,6 +72,7 @@ private: const MTPPollAnswerVoters &result, bool isMinResults); + not_null _owner; Flags _flags = Flags(); }; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 5f548721c..f2322f43c 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -2895,7 +2895,7 @@ void Session::gameApplyFields( not_null Session::poll(PollId id) { auto i = _polls.find(id); if (i == _polls.cend()) { - i = _polls.emplace(id, std::make_unique(id)).first; + i = _polls.emplace(id, std::make_unique(this, id)).first; } return i->second.get(); } diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index 2a84cd528..ca64ff18d 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -534,9 +534,9 @@ historyPollQuestionStyle: TextStyle(defaultTextStyle) { } historyPollAnswerStyle: defaultTextStyle; historyPollQuestionTop: 7px; -historyPollSubtitleSkip: 2px; +historyPollSubtitleSkip: 4px; historyPollAnswerPadding: margins(31px, 10px, 0px, 10px); -historyPollAnswersSkip: 3px; +historyPollAnswersSkip: 2px; historyPollPercentFont: semiboldFont; historyPollPercentSkip: 6px; historyPollPercentTop: 0px; @@ -570,6 +570,9 @@ historyPollRippleOut: RippleAnimation(defaultRippleAnimation) { color: msgWaveformOutInactive; } historyPollRippleOpacity: 0.3; +historyPollRecentVotersSkip: 4px; +historyPollRecentVoterSize: 18px; +historyPollRecentVoterSkip: 13px; boxAttachEmoji: IconButton(historyAttachEmoji) { width: 30px; diff --git a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp index c8079712e..a61bacdd5 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/ripple_animation.h" #include "data/data_media_types.h" #include "data/data_poll.h" +#include "data/data_user.h" #include "data/data_session.h" #include "layout.h" #include "main/main_session.h" @@ -29,6 +30,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace HistoryView { namespace { +constexpr auto kShowRecentVotersCount = 3; + struct PercentCounterItem { int index = 0; int percent = 0; @@ -331,7 +334,7 @@ void Poll::updateTexts() { ? tr::lng_polls_public(tr::now) : tr::lng_polls_anonymous(tr::now)))); } - + updateRecentVoters(); updateAnswers(); updateVotes(); @@ -340,6 +343,16 @@ void Poll::updateTexts() { } } +void Poll::updateRecentVoters() { + auto &&sliced = ranges::view::all( + _poll->recentVoters + ) | ranges::view::take(kShowRecentVotersCount); + const auto changed = !ranges::equal(_recentVoters, sliced); + if (changed) { + _recentVoters = sliced | ranges::to_vector; + } +} + void Poll::updateAnswers() { const auto changed = !ranges::equal( _answers, @@ -501,6 +514,7 @@ void Poll::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m p.setPen(regular); _subtitle.drawLeftElided(p, padding.left(), tshift, paintw, width()); + paintRecentVoters(p, padding.left() + _subtitle.maxWidth(), tshift, selection); tshift += st::msgDateFont->height + st::historyPollAnswersSkip; const auto progress = _answersAnimation @@ -560,6 +574,36 @@ void Poll::radialAnimationCallback() const { } } +void Poll::paintRecentVoters( + Painter &p, + int left, + int top, + TextSelection selection) const { + const auto count = int(_recentVoters.size()); + if (!count) { + return; + } + auto x = left + + st::historyPollRecentVotersSkip + + (count - 1) * st::historyPollRecentVoterSkip; + auto y = top; + const auto size = st::historyPollRecentVoterSize; + const auto outbg = _parent->hasOutLayout(); + const auto selected = (selection == FullSelection); + auto pen = (selected + ? (outbg ? st::msgOutBgSelected : st::msgInBgSelected) + : (outbg ? st::msgOutBg : st::msgInBg))->p; + pen.setWidth(st::lineWidth); + for (const auto &recent : _recentVoters) { + recent->paintUserpic(p, x, y, size); + p.setPen(pen); + p.setBrush(Qt::NoBrush); + PainterHighQualityEnabler hq(p); + p.drawEllipse(x, y, size, size); + x -= st::historyPollRecentVoterSkip; + } +} + int Poll::paintAnswer( Painter &p, const Answer &answer, diff --git a/Telegram/SourceFiles/history/view/media/history_view_poll.h b/Telegram/SourceFiles/history/view/media/history_view_poll.h index d99b388f8..0d4232623 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_poll.h +++ b/Telegram/SourceFiles/history/view/media/history_view_poll.h @@ -62,6 +62,7 @@ private: [[nodiscard]] ClickHandlerPtr createAnswerClickHandler( const Answer &answer) const; void updateTexts(); + void updateRecentVoters(); void updateAnswers(); void updateVotes(); void updateTotalVotes(); @@ -73,6 +74,11 @@ private: int maxVotes); void checkSendingAnimation() const; + void paintRecentVoters( + Painter &p, + int left, + int top, + TextSelection selection) const; int paintAnswer( Painter &p, const Answer &answer, @@ -124,6 +130,9 @@ private: Ui::Text::String _question; Ui::Text::String _subtitle; + std::vector> _recentVoters; + QImage _recentVotersImage; + std::vector _answers; Ui::Text::String _totalVotesLabel;