Hide tooltip button in psa / quizes.

This commit is contained in:
John Preston 2020-04-30 14:11:05 +04:00
parent ff25f1d5c9
commit 4efd649c27
13 changed files with 174 additions and 47 deletions

View File

@ -582,7 +582,9 @@ void InnerWidget::elementShowPollResults(
FullMsgId context) { FullMsgId context) {
} }
void InnerWidget::elementShowTooltip(const TextWithEntities &text) { void InnerWidget::elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) {
} }
void InnerWidget::saveState(not_null<SectionMemento*> memento) { void InnerWidget::saveState(not_null<SectionMemento*> memento) {

View File

@ -104,7 +104,9 @@ public:
void elementShowPollResults( void elementShowPollResults(
not_null<PollData*> poll, not_null<PollData*> poll,
FullMsgId context) override; FullMsgId context) override;
void elementShowTooltip(const TextWithEntities &text) override; void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) override;
~InnerWidget(); ~InnerWidget();

View File

@ -2488,7 +2488,9 @@ void HistoryInner::elementShowPollResults(
FullMsgId context) { FullMsgId context) {
} }
void HistoryInner::elementShowTooltip(const TextWithEntities &text) { void HistoryInner::elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) {
if (const auto strong = _topToast.get()) { if (const auto strong = _topToast.get()) {
strong->hideAnimated(); strong->hideAnimated();
} }
@ -2500,6 +2502,13 @@ void HistoryInner::elementShowTooltip(const TextWithEntities &text) {
.dark = true, .dark = true,
.slideSide = RectPart::Top, .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 auto HistoryInner::getSelectionState() const
@ -3369,9 +3378,11 @@ not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() {
Instance->elementShowPollResults(poll, context); Instance->elementShowPollResults(poll, context);
} }
} }
void elementShowTooltip(const TextWithEntities &text) override { void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) override {
if (Instance) { if (Instance) {
Instance->elementShowTooltip(text); Instance->elementShowTooltip(text, hiddenCallback);
} }
} }

View File

@ -88,7 +88,9 @@ public:
void elementShowPollResults( void elementShowPollResults(
not_null<PollData*> poll, not_null<PollData*> poll,
FullMsgId context); FullMsgId context);
void elementShowTooltip(const TextWithEntities &text); void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback);
void updateBotInfo(bool recount = true); void updateBotInfo(bool recount = true);

View File

@ -78,7 +78,6 @@ struct HistoryMessageForwarded : public RuntimeComponent<HistoryMessageForwarded
std::unique_ptr<HiddenSenderInfo> hiddenSenderInfo; std::unique_ptr<HiddenSenderInfo> hiddenSenderInfo;
QString originalAuthor; QString originalAuthor;
QString psaType; QString psaType;
mutable ClickHandlerPtr psaTooltipLink;
MsgId originalId = 0; MsgId originalId = 0;
mutable Ui::Text::String text = { 1 }; mutable Ui::Text::String text = { 1 };

View File

@ -100,7 +100,8 @@ void SimpleElementDelegate::elementShowPollResults(
} }
void SimpleElementDelegate::elementShowTooltip( void SimpleElementDelegate::elementShowTooltip(
const TextWithEntities &text) { const TextWithEntities &text,
Fn<void()> hiddenCallback) {
} }
TextSelection UnshiftItemSelection( TextSelection UnshiftItemSelection(

View File

@ -54,7 +54,9 @@ public:
virtual void elementShowPollResults( virtual void elementShowPollResults(
not_null<PollData*> poll, not_null<PollData*> poll,
FullMsgId context) = 0; FullMsgId context) = 0;
virtual void elementShowTooltip(const TextWithEntities &text) = 0; virtual void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) = 0;
}; };
@ -78,7 +80,9 @@ public:
void elementShowPollResults( void elementShowPollResults(
not_null<PollData*> poll, not_null<PollData*> poll,
FullMsgId context) override; FullMsgId context) override;
void elementShowTooltip(const TextWithEntities &text) override; void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) override;
}; };

View File

@ -1158,7 +1158,9 @@ void ListWidget::elementShowPollResults(
FullMsgId context) { FullMsgId context) {
} }
void ListWidget::elementShowTooltip(const TextWithEntities &text) { void ListWidget::elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) {
} }
void ListWidget::saveState(not_null<ListMemento*> memento) { void ListWidget::saveState(not_null<ListMemento*> memento) {

View File

@ -200,7 +200,9 @@ public:
void elementShowPollResults( void elementShowPollResults(
not_null<PollData*> poll, not_null<PollData*> poll,
FullMsgId context) override; FullMsgId context) override;
void elementShowTooltip(const TextWithEntities &text) override; void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) override;
~ListWidget(); ~ListWidget();

View File

@ -204,6 +204,7 @@ Message::Message(
not_null<HistoryMessage*> data) not_null<HistoryMessage*> data)
: Element(delegate, data) { : Element(delegate, data) {
initLogEntryOriginal(); initLogEntryOriginal();
initPsa();
} }
not_null<HistoryMessage*> Message::message() const { not_null<HistoryMessage*> 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)); p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette));
if (!forwarded->psaType.isEmpty()) { if (!forwarded->psaType.isEmpty()) {
const auto &icon = selected const auto entry = Get<PsaTooltipState>();
? (outbg Assert(entry != nullptr);
? st::historyPsaIconOutSelected const auto shown = entry->buttonVisibleAnimation.value(
: st::historyPsaIconInSelected) entry->buttonVisible ? 1. : 0.);
: (outbg ? st::historyPsaIconOut : st::historyPsaIconIn); if (shown > 0) {
const auto position = fits const auto &icon = selected
? st::historyPsaIconPosition1 ? (outbg
: st::historyPsaIconPosition2; ? st::historyPsaIconOutSelected
icon.paint( : st::historyPsaIconInSelected)
p, : (outbg ? st::historyPsaIconOut : st::historyPsaIconIn);
trect.x() + trect.width() - position.x() - icon.width(), const auto position = fits
trect.y() + position.y(), ? st::historyPsaIconPosition1
trect.width()); : 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)); trect.setY(trect.y() + ((fits ? 1 : 2) * serviceFont->height));
@ -1012,9 +1026,10 @@ bool Message::getStateForwardedInfo(
icon.width(), icon.width(),
icon.height()); icon.height());
if (iconRect.contains(point)) { if (iconRect.contains(point)) {
ensurePsaTooltipLink(forwarded); if (const auto link = psaTooltipLink()) {
outResult->link = forwarded->psaTooltipLink; outResult->link = link;
return true; return true;
}
} }
} }
const auto useWidth = trect.width() - (fits ? skip1 : skip2); const auto useWidth = trect.width() - (fits ? skip1 : skip2);
@ -1041,12 +1056,14 @@ bool Message::getStateForwardedInfo(
return false; return false;
} }
void Message::ensurePsaTooltipLink( ClickHandlerPtr Message::psaTooltipLink() const {
not_null<const HistoryMessageForwarded*> forwarded) const { const auto state = Get<PsaTooltipState>();
if (forwarded->psaTooltipLink) { if (!state || !state->buttonVisible) {
return; return nullptr;
} else if (state->link) {
return state->link;
} }
const auto type = forwarded->psaType; const auto type = state->type;
const auto handler = [=] { const auto handler = [=] {
const auto custom = type.isEmpty() const auto custom = type.isEmpty()
? QString() ? QString()
@ -1057,11 +1074,29 @@ void Message::ensurePsaTooltipLink(
? tr::lng_tooltip_psa_default(tr::now) ? tr::lng_tooltip_psa_default(tr::now)
: custom)); : custom));
TextUtilities::ParseEntities(text, 0); TextUtilities::ParseEntities(text, 0);
delegate()->elementShowTooltip(text); psaTooltipToggled(true);
delegate()->elementShowTooltip(text, crl::guard(this, [=] {
psaTooltipToggled(false);
}));
}; };
forwarded->psaTooltipLink state->link = std::make_shared<LambdaClickHandler>(
= std::make_shared<LambdaClickHandler>( crl::guard(this, handler));
crl::guard(this, handler)); return state->link;
}
void Message::psaTooltipToggled(bool tooltipShown) const {
const auto visible = !tooltipShown;
const auto state = Get<PsaTooltipState>();
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( bool Message::getStateReplyInfo(
@ -1437,6 +1472,15 @@ void Message::initLogEntryOriginal() {
} }
} }
void Message::initPsa() {
if (const auto forwarded = message()->Get<HistoryMessageForwarded>()) {
if (!forwarded->psaType.isEmpty()) {
AddComponents(PsaTooltipState::Bit());
Get<PsaTooltipState>()->type = forwarded->psaType;
}
}
}
WebPage *Message::logEntryOriginal() const { WebPage *Message::logEntryOriginal() const {
if (const auto entry = Get<LogEntryOriginal>()) { if (const auto entry = Get<LogEntryOriginal>()) {
return entry->page.get(); return entry->page.get();
@ -1465,10 +1509,7 @@ bool Message::displayFromName() const {
if (!hasFromName() || isAttachedToPrevious()) { if (!hasFromName() || isAttachedToPrevious()) {
return false; return false;
} }
if (const auto forwarded = message()->Get<HistoryMessageForwarded>()) { return !Has<PsaTooltipState>();
return forwarded->psaType.isEmpty();
}
return true;
} }
bool Message::displayForwardedFrom() const { bool Message::displayForwardedFrom() const {

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "history/view/history_view_element.h" #include "history/view/history_view_element.h"
#include "ui/effects/animations.h"
#include "base/weak_ptr.h" #include "base/weak_ptr.h"
class HistoryMessage; class HistoryMessage;
@ -30,6 +31,13 @@ struct LogEntryOriginal
}; };
struct PsaTooltipState : public RuntimeComponent<PsaTooltipState, Element> {
QString type;
mutable ClickHandlerPtr link;
mutable Ui::Animations::Simple buttonVisibleAnimation;
mutable bool buttonVisible = true;
};
class Message : public Element, public base::has_weak_ptr { class Message : public Element, public base::has_weak_ptr {
public: public:
Message( Message(
@ -97,6 +105,7 @@ private:
not_null<HistoryMessage*> message() const; not_null<HistoryMessage*> message() const;
void initLogEntryOriginal(); void initLogEntryOriginal();
void initPsa();
void refreshEditedBadge(); void refreshEditedBadge();
void fromNameUpdated(int width) const; void fromNameUpdated(int width) const;
@ -154,8 +163,8 @@ private:
WebPage *logEntryOriginal() const; WebPage *logEntryOriginal() const;
void ensurePsaTooltipLink( [[nodiscard]] ClickHandlerPtr psaTooltipLink() const;
not_null<const HistoryMessageForwarded*> forwarded) const; void psaTooltipToggled(bool shown) const;
mutable ClickHandlerPtr _rightActionLink; mutable ClickHandlerPtr _rightActionLink;
mutable ClickHandlerPtr _fastReplyLink; mutable ClickHandlerPtr _fastReplyLink;

View File

@ -373,6 +373,7 @@ void Poll::updateTexts() {
if (_pollVersion == _poll->version) { if (_pollVersion == _poll->version) {
return; return;
} }
const auto first = !_pollVersion;
_pollVersion = _poll->version; _pollVersion = _poll->version;
const auto willStartAnimation = checkAnimationStart(); const auto willStartAnimation = checkAnimationStart();
@ -411,6 +412,9 @@ void Poll::updateTexts() {
checkQuizAnswered(); checkQuizAnswered();
} }
} }
solutionToggled(
_solutionShown,
first ? anim::type::instant : anim::type::normal);
} }
void Poll::checkQuizAnswered() { void Poll::checkQuizAnswered() {
@ -437,7 +441,37 @@ void Poll::checkQuizAnswered() {
void Poll::showSolution() const { void Poll::showSolution() const {
if (!_poll->solution.text.isEmpty()) { 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 right,
int top, int top,
TextSelection selection) const { TextSelection selection) const {
if (!showVotes() || _poll->solution.text.isEmpty()) { const auto shown = _solutionButtonAnimation.value(
_solutionButtonVisible ? 1. : 0.);
if (!shown) {
return; return;
} }
if (!_showSolutionLink) { if (!_showSolutionLink) {
@ -928,7 +964,16 @@ void Poll::paintShowSolution(
: (outbg ? st::historyQuizExplainOut : st::historyQuizExplainIn); : (outbg ? st::historyQuizExplainOut : st::historyQuizExplainIn);
const auto x = right - icon.width(); const auto x = right - icon.width();
const auto y = top + (st::normalFont->height - icon.height()) / 2; 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( int Poll::paintAnswer(
@ -1388,7 +1433,7 @@ bool Poll::inShowSolution(
QPoint point, QPoint point,
int right, int right,
int top) const { int top) const {
if (!canShowSolution()) { if (!canShowSolution() || !_solutionButtonVisible) {
return false; return false;
} }
const auto &icon = st::historyQuizExplainIn; const auto &icon = st::historyQuizExplainIn;

View File

@ -166,6 +166,9 @@ private:
void showResults(); void showResults();
void checkQuizAnswered(); void checkQuizAnswered();
void showSolution() const; void showSolution() const;
void solutionToggled(
bool solutionShown,
anim::type animated = anim::type::normal) const;
[[nodiscard]] bool canShowSolution() const; [[nodiscard]] bool canShowSolution() const;
[[nodiscard]] bool inShowSolution( [[nodiscard]] bool inShowSolution(
@ -201,6 +204,10 @@ private:
mutable std::unique_ptr<CloseInformation> _close; mutable std::unique_ptr<CloseInformation> _close;
mutable Ui::Animations::Simple _solutionButtonAnimation;
mutable bool _solutionShown = false;
mutable bool _solutionButtonVisible = false;
bool _hasSelected = false; bool _hasSelected = false;
bool _votedFromHere = false; bool _votedFromHere = false;
mutable bool _wrongAnswerAnimated = false; mutable bool _wrongAnswerAnimated = false;