From 4efd649c2788634700383e4adbf6cacddd36c785 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 30 Apr 2020 14:11:05 +0400 Subject: [PATCH] Hide tooltip button in psa / quizes. --- .../admin_log/history_admin_log_inner.cpp | 4 +- .../admin_log/history_admin_log_inner.h | 4 +- .../history/history_inner_widget.cpp | 17 +++- .../history/history_inner_widget.h | 4 +- .../history/history_item_components.h | 1 - .../history/view/history_view_element.cpp | 3 +- .../history/view/history_view_element.h | 8 +- .../history/view/history_view_list_widget.cpp | 4 +- .../history/view/history_view_list_widget.h | 4 +- .../history/view/history_view_message.cpp | 99 +++++++++++++------ .../history/view/history_view_message.h | 13 ++- .../history/view/media/history_view_poll.cpp | 53 +++++++++- .../history/view/media/history_view_poll.h | 7 ++ 13 files changed, 174 insertions(+), 47 deletions(-) diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index 062f97818..a12e49c37 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -582,7 +582,9 @@ void InnerWidget::elementShowPollResults( FullMsgId context) { } -void InnerWidget::elementShowTooltip(const TextWithEntities &text) { +void InnerWidget::elementShowTooltip( + const TextWithEntities &text, + Fn hiddenCallback) { } void InnerWidget::saveState(not_null memento) { diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h index 3a19f46bf..b539ed42f 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h @@ -104,7 +104,9 @@ public: void elementShowPollResults( not_null poll, FullMsgId context) override; - void elementShowTooltip(const TextWithEntities &text) override; + void elementShowTooltip( + const TextWithEntities &text, + Fn hiddenCallback) override; ~InnerWidget(); diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index aaf0587b9..9d0440268 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -2488,7 +2488,9 @@ void HistoryInner::elementShowPollResults( FullMsgId context) { } -void HistoryInner::elementShowTooltip(const TextWithEntities &text) { +void HistoryInner::elementShowTooltip( + const TextWithEntities &text, + Fn hiddenCallback) { if (const auto strong = _topToast.get()) { strong->hideAnimated(); } @@ -2500,6 +2502,13 @@ void HistoryInner::elementShowTooltip(const TextWithEntities &text) { .dark = true, .slideSide = RectPart::Top, }); + if (const auto strong = _topToast.get()) { + if (hiddenCallback) { + connect(strong->widget(), &QObject::destroyed, hiddenCallback); + } + } else if (hiddenCallback) { + hiddenCallback(); + } } auto HistoryInner::getSelectionState() const @@ -3369,9 +3378,11 @@ not_null HistoryInner::ElementDelegate() { Instance->elementShowPollResults(poll, context); } } - void elementShowTooltip(const TextWithEntities &text) override { + void elementShowTooltip( + const TextWithEntities &text, + Fn hiddenCallback) override { if (Instance) { - Instance->elementShowTooltip(text); + Instance->elementShowTooltip(text, hiddenCallback); } } diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index 1f9f1df43..25ffcd55d 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -88,7 +88,9 @@ public: void elementShowPollResults( not_null poll, FullMsgId context); - void elementShowTooltip(const TextWithEntities &text); + void elementShowTooltip( + const TextWithEntities &text, + Fn hiddenCallback); void updateBotInfo(bool recount = true); diff --git a/Telegram/SourceFiles/history/history_item_components.h b/Telegram/SourceFiles/history/history_item_components.h index 729069e24..6582bca1f 100644 --- a/Telegram/SourceFiles/history/history_item_components.h +++ b/Telegram/SourceFiles/history/history_item_components.h @@ -78,7 +78,6 @@ struct HistoryMessageForwarded : public RuntimeComponent hiddenSenderInfo; QString originalAuthor; QString psaType; - mutable ClickHandlerPtr psaTooltipLink; MsgId originalId = 0; mutable Ui::Text::String text = { 1 }; diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 0e5a75209..3e4e9cea0 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -100,7 +100,8 @@ void SimpleElementDelegate::elementShowPollResults( } void SimpleElementDelegate::elementShowTooltip( - const TextWithEntities &text) { + const TextWithEntities &text, + Fn hiddenCallback) { } TextSelection UnshiftItemSelection( diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index 27a583188..8b6577479 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -54,7 +54,9 @@ public: virtual void elementShowPollResults( not_null poll, FullMsgId context) = 0; - virtual void elementShowTooltip(const TextWithEntities &text) = 0; + virtual void elementShowTooltip( + const TextWithEntities &text, + Fn hiddenCallback) = 0; }; @@ -78,7 +80,9 @@ public: void elementShowPollResults( not_null poll, FullMsgId context) override; - void elementShowTooltip(const TextWithEntities &text) override; + void elementShowTooltip( + const TextWithEntities &text, + Fn hiddenCallback) override; }; diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 7bdfff6e4..4b652fed7 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -1158,7 +1158,9 @@ void ListWidget::elementShowPollResults( FullMsgId context) { } -void ListWidget::elementShowTooltip(const TextWithEntities &text) { +void ListWidget::elementShowTooltip( + const TextWithEntities &text, + Fn hiddenCallback) { } void ListWidget::saveState(not_null memento) { diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index 1bb94045d..549ebbf4e 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -200,7 +200,9 @@ public: void elementShowPollResults( not_null poll, FullMsgId context) override; - void elementShowTooltip(const TextWithEntities &text) override; + void elementShowTooltip( + const TextWithEntities &text, + Fn hiddenCallback) override; ~ListWidget(); diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 2100d0867..9a09b5961 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -204,6 +204,7 @@ Message::Message( not_null data) : Element(delegate, data) { initLogEntryOriginal(); + initPsa(); } not_null Message::message() const { @@ -653,19 +654,32 @@ void Message::paintForwardedInfo(Painter &p, QRect &trect, bool selected) const p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette)); if (!forwarded->psaType.isEmpty()) { - const auto &icon = selected - ? (outbg - ? st::historyPsaIconOutSelected - : st::historyPsaIconInSelected) - : (outbg ? st::historyPsaIconOut : st::historyPsaIconIn); - const auto position = fits - ? st::historyPsaIconPosition1 - : st::historyPsaIconPosition2; - icon.paint( - p, - trect.x() + trect.width() - position.x() - icon.width(), - trect.y() + position.y(), - trect.width()); + const auto entry = Get(); + Assert(entry != nullptr); + const auto shown = entry->buttonVisibleAnimation.value( + entry->buttonVisible ? 1. : 0.); + if (shown > 0) { + const auto &icon = selected + ? (outbg + ? st::historyPsaIconOutSelected + : st::historyPsaIconInSelected) + : (outbg ? st::historyPsaIconOut : st::historyPsaIconIn); + const auto position = fits + ? st::historyPsaIconPosition1 + : st::historyPsaIconPosition2; + const auto x = trect.x() + trect.width() - position.x() - icon.width(); + const auto y = trect.y() + position.y(); + if (shown == 1) { + icon.paint(p, x, y, trect.width()); + } else { + p.save(); + p.translate(x + icon.width() / 2, y + icon.height() / 2); + p.scale(shown, shown); + p.setOpacity(shown); + icon.paint(p, -icon.width() / 2, -icon.height() / 2, width()); + p.restore(); + } + } } trect.setY(trect.y() + ((fits ? 1 : 2) * serviceFont->height)); @@ -1012,9 +1026,10 @@ bool Message::getStateForwardedInfo( icon.width(), icon.height()); if (iconRect.contains(point)) { - ensurePsaTooltipLink(forwarded); - outResult->link = forwarded->psaTooltipLink; - return true; + if (const auto link = psaTooltipLink()) { + outResult->link = link; + return true; + } } } const auto useWidth = trect.width() - (fits ? skip1 : skip2); @@ -1041,12 +1056,14 @@ bool Message::getStateForwardedInfo( return false; } -void Message::ensurePsaTooltipLink( - not_null forwarded) const { - if (forwarded->psaTooltipLink) { - return; +ClickHandlerPtr Message::psaTooltipLink() const { + const auto state = Get(); + if (!state || !state->buttonVisible) { + return nullptr; + } else if (state->link) { + return state->link; } - const auto type = forwarded->psaType; + const auto type = state->type; const auto handler = [=] { const auto custom = type.isEmpty() ? QString() @@ -1057,11 +1074,29 @@ void Message::ensurePsaTooltipLink( ? tr::lng_tooltip_psa_default(tr::now) : custom)); TextUtilities::ParseEntities(text, 0); - delegate()->elementShowTooltip(text); + psaTooltipToggled(true); + delegate()->elementShowTooltip(text, crl::guard(this, [=] { + psaTooltipToggled(false); + })); }; - forwarded->psaTooltipLink - = std::make_shared( - crl::guard(this, handler)); + state->link = std::make_shared( + crl::guard(this, handler)); + return state->link; +} + +void Message::psaTooltipToggled(bool tooltipShown) const { + const auto visible = !tooltipShown; + const auto state = Get(); + if (state->buttonVisible == visible) { + return; + } + state->buttonVisible = visible; + history()->owner().notifyViewLayoutChange(this); + state->buttonVisibleAnimation.start( + [=] { history()->owner().requestViewRepaint(this); }, + visible ? 0. : 1., + visible ? 1. : 0., + st::fadeWrapDuration); } bool Message::getStateReplyInfo( @@ -1437,6 +1472,15 @@ void Message::initLogEntryOriginal() { } } +void Message::initPsa() { + if (const auto forwarded = message()->Get()) { + if (!forwarded->psaType.isEmpty()) { + AddComponents(PsaTooltipState::Bit()); + Get()->type = forwarded->psaType; + } + } +} + WebPage *Message::logEntryOriginal() const { if (const auto entry = Get()) { return entry->page.get(); @@ -1465,10 +1509,7 @@ bool Message::displayFromName() const { if (!hasFromName() || isAttachedToPrevious()) { return false; } - if (const auto forwarded = message()->Get()) { - return forwarded->psaType.isEmpty(); - } - return true; + return !Has(); } bool Message::displayForwardedFrom() const { diff --git a/Telegram/SourceFiles/history/view/history_view_message.h b/Telegram/SourceFiles/history/view/history_view_message.h index abee35780..303cd8381 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.h +++ b/Telegram/SourceFiles/history/view/history_view_message.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "history/view/history_view_element.h" +#include "ui/effects/animations.h" #include "base/weak_ptr.h" class HistoryMessage; @@ -30,6 +31,13 @@ struct LogEntryOriginal }; +struct PsaTooltipState : public RuntimeComponent { + QString type; + mutable ClickHandlerPtr link; + mutable Ui::Animations::Simple buttonVisibleAnimation; + mutable bool buttonVisible = true; +}; + class Message : public Element, public base::has_weak_ptr { public: Message( @@ -97,6 +105,7 @@ private: not_null message() const; void initLogEntryOriginal(); + void initPsa(); void refreshEditedBadge(); void fromNameUpdated(int width) const; @@ -154,8 +163,8 @@ private: WebPage *logEntryOriginal() const; - void ensurePsaTooltipLink( - not_null forwarded) const; + [[nodiscard]] ClickHandlerPtr psaTooltipLink() const; + void psaTooltipToggled(bool shown) const; mutable ClickHandlerPtr _rightActionLink; mutable ClickHandlerPtr _fastReplyLink; diff --git a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp index 68c20c9d3..292c36670 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp @@ -373,6 +373,7 @@ void Poll::updateTexts() { if (_pollVersion == _poll->version) { return; } + const auto first = !_pollVersion; _pollVersion = _poll->version; const auto willStartAnimation = checkAnimationStart(); @@ -411,6 +412,9 @@ void Poll::updateTexts() { checkQuizAnswered(); } } + solutionToggled( + _solutionShown, + first ? anim::type::instant : anim::type::normal); } void Poll::checkQuizAnswered() { @@ -437,7 +441,37 @@ void Poll::checkQuizAnswered() { void Poll::showSolution() const { if (!_poll->solution.text.isEmpty()) { - _parent->delegate()->elementShowTooltip(_poll->solution); + solutionToggled(true); + _parent->delegate()->elementShowTooltip( + _poll->solution, + crl::guard(this, [=] { solutionToggled(false); })); + } +} + +void Poll::solutionToggled( + bool solutionShown, + anim::type animated) const { + _solutionShown = solutionShown; + const auto visible = canShowSolution() && !_solutionShown; + if (_solutionButtonVisible == visible) { + if (animated == anim::type::instant + && _solutionButtonAnimation.animating()) { + _solutionButtonAnimation.stop(); + history()->owner().requestViewRepaint(_parent); + } + return; + } + _solutionButtonVisible = visible; + history()->owner().notifyViewLayoutChange(_parent); + if (animated == anim::type::instant) { + _solutionButtonAnimation.stop(); + history()->owner().requestViewRepaint(_parent); + } else { + _solutionButtonAnimation.start( + [=] { history()->owner().requestViewRepaint(_parent); }, + visible ? 0. : 1., + visible ? 1. : 0., + st::fadeWrapDuration); } } @@ -913,7 +947,9 @@ void Poll::paintShowSolution( int right, int top, TextSelection selection) const { - if (!showVotes() || _poll->solution.text.isEmpty()) { + const auto shown = _solutionButtonAnimation.value( + _solutionButtonVisible ? 1. : 0.); + if (!shown) { return; } if (!_showSolutionLink) { @@ -928,7 +964,16 @@ void Poll::paintShowSolution( : (outbg ? st::historyQuizExplainOut : st::historyQuizExplainIn); const auto x = right - icon.width(); const auto y = top + (st::normalFont->height - icon.height()) / 2; - icon.paint(p, x, y, width()); + if (shown == 1.) { + icon.paint(p, x, y, width()); + } else { + p.save(); + p.translate(x + icon.width() / 2, y + icon.height() / 2); + p.scale(shown, shown); + p.setOpacity(shown); + icon.paint(p, -icon.width() / 2, -icon.height() / 2, width()); + p.restore(); + } } int Poll::paintAnswer( @@ -1388,7 +1433,7 @@ bool Poll::inShowSolution( QPoint point, int right, int top) const { - if (!canShowSolution()) { + if (!canShowSolution() || !_solutionButtonVisible) { return false; } const auto &icon = st::historyQuizExplainIn; diff --git a/Telegram/SourceFiles/history/view/media/history_view_poll.h b/Telegram/SourceFiles/history/view/media/history_view_poll.h index 28d19d80b..c3e9b2c37 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_poll.h +++ b/Telegram/SourceFiles/history/view/media/history_view_poll.h @@ -166,6 +166,9 @@ private: void showResults(); void checkQuizAnswered(); void showSolution() const; + void solutionToggled( + bool solutionShown, + anim::type animated = anim::type::normal) const; [[nodiscard]] bool canShowSolution() const; [[nodiscard]] bool inShowSolution( @@ -201,6 +204,10 @@ private: mutable std::unique_ptr _close; + mutable Ui::Animations::Simple _solutionButtonAnimation; + mutable bool _solutionShown = false; + mutable bool _solutionButtonVisible = false; + bool _hasSelected = false; bool _votedFromHere = false; mutable bool _wrongAnswerAnimated = false;