From dbfc555d9c9b6635ebfcb9a1b3778c486d5a8dff Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 24 Jan 2020 11:49:12 +0300 Subject: [PATCH] Support shaking bubble for wrong quiz answer. --- Telegram/SourceFiles/history/history.style | 4 +- .../history/view/history_view_message.cpp | 13 +++++ .../history/view/media/history_view_media.h | 12 +++++ .../history/view/media/history_view_poll.cpp | 50 +++++++++++++++++++ .../history/view/media/history_view_poll.h | 5 ++ 5 files changed, 82 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index ab24059f3..cf37a9d06 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -537,10 +537,10 @@ historyPollQuestionStyle: TextStyle(defaultTextStyle) { historyPollAnswerStyle: defaultTextStyle; historyPollQuestionTop: 7px; historyPollSubtitleSkip: 4px; -historyPollAnswerPadding: margins(31px, 10px, 0px, 10px); +historyPollAnswerPadding: margins(32px, 10px, 0px, 10px); historyPollAnswersSkip: 2px; historyPollPercentFont: semiboldFont; -historyPollPercentSkip: 6px; +historyPollPercentSkip: 5px; historyPollPercentTop: 0px; historyPollTotalVotesSkip: 5px; historyPollFillingMin: 4px; diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index af27346f9..1ad134e55 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -409,6 +409,15 @@ void Message::draw( paintHighlight(p, g.height()); + const auto roll = media ? media->getBubbleRoll() : Media::BubbleRoll(); + if (roll) { + p.save(); + p.translate(g.center()); + p.rotate(roll.rotate); + p.scale(roll.scale, roll.scale); + p.translate(-g.center()); + } + p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette)); @@ -504,6 +513,10 @@ void Message::draw( p.restoreTextPalette(); + if (roll) { + p.restore(); + } + const auto reply = item->Get(); if (reply && reply->isNameUpdated()) { const_cast(this)->setPendingResize(); diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.h b/Telegram/SourceFiles/history/view/media/history_view_media.h index 96335abae..3db33a4af 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media.h @@ -233,6 +233,18 @@ public: return true; } + struct BubbleRoll { + float64 rotate = 0.; + float64 scale = 1.; + + explicit operator bool() const { + return (rotate != 0.) || (scale != 1.); + } + }; + [[nodiscard]] virtual BubbleRoll getBubbleRoll() const { + return BubbleRoll(); + } + virtual void unloadHeavyPart() { } diff --git a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp index a5ee5ad7b..5c054f5d9 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp @@ -344,6 +344,7 @@ void Poll::updateTexts() { _pollVersion = _poll->version; const auto willStartAnimation = checkAnimationStart(); + const auto voted = _voted; if (_question.toString() != _poll->question) { auto options = Ui::WebpageTextTitleOptions(); @@ -374,9 +375,29 @@ void Poll::updateTexts() { if (willStartAnimation) { startAnswersAnimation(); + if (!voted) { + checkQuizAnsweredWrong(); + } } } +void Poll::checkQuizAnsweredWrong() { + if (!_voted || !_poll->quiz()) { + return; + } + const auto i = ranges::find(_answers, true, &Answer::chosen); + if (i == end(_answers) || i->correct) { + return; + } + constexpr auto kDuration = crl::time(400); + _wrongAnswerAnimation.start( + [=] { history()->owner().requestViewRepaint(_parent); }, + 0., + 1., + kDuration, + anim::linear); +} + void Poll::updateRecentVoters() { auto &&sliced = ranges::view::all( _poll->recentVoters @@ -1121,6 +1142,35 @@ TextState Poll::textState(QPoint point, StateRequest request) const { return result; } +auto Poll::getBubbleRoll() const -> BubbleRoll { + constexpr auto kRotateSegments = 8; + constexpr auto kRotateAmplitude = 2.5; + constexpr auto kScaleSegments = 2; + constexpr auto kScaleAmplitude = 0.025; + + const auto value = _wrongAnswerAnimation.value(1.); + if (value == 1.) { + return BubbleRoll(); + } + const auto rotateFull = value * kRotateSegments; + const auto progress = [](float64 full) { + const auto lower = std::floor(full); + const auto shift = (full - lower); + switch (int(lower) % 4) { + case 0: return -shift; + case 1: return (shift - 1.); + case 2: return shift; + case 3: return (1. - shift); + } + Unexpected("Value in Poll::getBubbleRollDegrees."); + }; + const auto scaleFull = value * kScaleSegments; + return { + .rotate = progress(value * kRotateSegments) * kRotateAmplitude, + .scale = 1. + progress(value * kScaleSegments) * kScaleAmplitude + }; +} + void Poll::clickHandlerPressedChanged( const ClickHandlerPtr &handler, bool pressed) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_poll.h b/Telegram/SourceFiles/history/view/media/history_view_poll.h index 4fc57b111..015ad75e6 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_poll.h +++ b/Telegram/SourceFiles/history/view/media/history_view_poll.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "history/view/media/history_view_media.h" +#include "ui/effects/animations.h" #include "data/data_poll.h" #include "base/weak_ptr.h" @@ -40,6 +41,8 @@ public: return false; } + BubbleRoll getBubbleRoll() const override; + void clickHandlerPressedChanged( const ClickHandlerPtr &handler, bool pressed) override; @@ -145,6 +148,7 @@ private: void toggleMultiOption(const QByteArray &option); void sendMultiOptions(); void showResults(); + void checkQuizAnsweredWrong(); [[nodiscard]] int bottomButtonHeight() const; @@ -168,6 +172,7 @@ private: mutable std::unique_ptr _answersAnimation; mutable std::unique_ptr _sendingAnimation; + mutable Ui::Animations::Simple _wrongAnswerAnimation; mutable QPoint _lastLinkPoint; };