Added ripple animation to right action in messages.

This commit is contained in:
23rd 2022-12-05 22:54:24 +03:00
parent d55d383627
commit 0310d9902c
13 changed files with 150 additions and 17 deletions

View File

@ -1227,6 +1227,9 @@ ClickHandlerPtr Element::rightActionLink() const {
return ClickHandlerPtr();
}
void Element::applyRightActionLastPoint(QPoint p) const {
}
TimeId Element::displayedEditDate() const {
return TimeId(0);
}

View File

@ -404,6 +404,7 @@ public:
int top,
int outerWidth) const;
[[nodiscard]] virtual ClickHandlerPtr rightActionLink() const;
[[nodiscard]] virtual void applyRightActionLastPoint(QPoint p) const;
[[nodiscard]] virtual TimeId displayedEditDate() const;
[[nodiscard]] virtual bool hasVisibleText() const;
[[nodiscard]] virtual HistoryMessageReply *displayedReply() const;

View File

@ -292,6 +292,12 @@ struct Message::FromNameStatus {
int skip = 0;
};
struct Message::RightAction {
std::unique_ptr<Ui::RippleAnimation> ripple;
ClickHandlerPtr link;
QPoint lastPoint;
};
LogEntryOriginal::LogEntryOriginal() = default;
LogEntryOriginal::LogEntryOriginal(LogEntryOriginal &&other)
@ -1555,6 +1561,8 @@ void Message::clickHandlerPressedChanged(
Element::clickHandlerPressedChanged(handler, pressed);
if (!handler) {
return;
} else if (_rightAction && (handler == _rightAction->link)) {
toggleRightActionRipple(pressed);
} else if (_comments && (handler == _comments->link)) {
toggleCommentsButtonRipple(pressed);
} else if (_topicButton && (handler == _topicButton->link)) {
@ -1580,6 +1588,25 @@ void Message::toggleCommentsButtonRipple(bool pressed) {
}
}
void Message::toggleRightActionRipple(bool pressed) {
Expects(_rightAction != nullptr);
const auto size = rightActionSize();
Assert(size != std::nullopt);
if (pressed) {
if (!_rightAction->ripple) {
// Create a ripple.
_rightAction->ripple = std::make_unique<Ui::RippleAnimation>(
st::defaultRippleAnimation,
Ui::RippleAnimation::RoundRectMask(*size, size->width() / 2),
[=] { repaint(); });
}
_rightAction->ripple->add(_rightAction->lastPoint);
} else if (_rightAction->ripple) {
_rightAction->ripple->lastStop();
}
}
BottomRippleMask Message::bottomRippleMask(int buttonHeight) const {
using namespace Ui;
using namespace Images;
@ -1923,7 +1950,7 @@ TextState Message::textState(
}
}
checkBottomInfoState();
if (const auto size = rightActionSize()) {
if (const auto size = rightActionSize(); size && _rightAction) {
const auto fastShareSkip = std::clamp(
(g.height() - size->height()) / 2,
0,
@ -1938,6 +1965,8 @@ TextState Message::textState(
).contains(point)) {
result.link = rightActionLink();
}
applyRightActionLastPoint(point
- QPoint(fastShareLeft, fastShareTop));
}
} else if (media && media->isDisplayed()) {
result = media->textState(point - g.topLeft(), request);
@ -2685,8 +2714,8 @@ auto Message::verticalRepaintRange() const -> VerticalRepaintRange {
}
void Message::refreshDataIdHook() {
if (base::take(_rightActionLink)) {
_rightActionLink = rightActionLink();
if (_rightAction && base::take(_rightAction->link)) {
_rightAction->link = rightActionLink();
}
if (base::take(_fastReplyLink)) {
_fastReplyLink = fastReplyLink();
@ -2960,6 +2989,13 @@ std::optional<QSize> Message::rightActionSize() const {
: std::optional<QSize>();
}
void Message::applyRightActionLastPoint(QPoint p) const {
if (!_rightAction) {
_rightAction = std::make_unique<RightAction>();
}
_rightAction->lastPoint = std::move(p);
}
bool Message::displayFastShare() const {
const auto item = message();
const auto peer = item->history()->peer;
@ -3003,8 +3039,27 @@ void Message::drawRightAction(
int left,
int top,
int outerWidth) const {
if (!_rightAction) {
_rightAction = std::make_unique<RightAction>();
}
const auto size = rightActionSize();
const auto st = context.st;
if (_rightAction->ripple) {
const auto &stm = context.messageStyle();
const auto colorOverride = &stm->msgWaveformInactive->c;
_rightAction->ripple->paint(
p,
left,
top,
size->width(),
colorOverride);
if (_rightAction->ripple->empty()) {
_rightAction->ripple.reset();
}
}
p.setPen(Qt::NoPen);
p.setBrush(st->msgServiceBg());
{
@ -3050,15 +3105,18 @@ void Message::drawRightAction(
}
ClickHandlerPtr Message::rightActionLink() const {
if (_rightActionLink) {
return _rightActionLink;
if (!_rightAction) {
_rightAction = std::make_unique<RightAction>();
}
if (_rightAction->link) {
return _rightAction->link;
}
if (isPinnedContext()) {
_rightActionLink = goToMessageClickHandler(data());
return _rightActionLink;
_rightAction->link = goToMessageClickHandler(data());
return _rightAction->link;
} else if (displayRightActionComments()) {
_rightActionLink = createGoToCommentsLink();
return _rightActionLink;
_rightAction->link = createGoToCommentsLink();
return _rightAction->link;
}
const auto sessionId = data()->history()->session().uniqueId();
const auto owner = &data()->history()->owner();
@ -3106,7 +3164,7 @@ ClickHandlerPtr Message::rightActionLink() const {
}
};
};
_rightActionLink = std::make_shared<LambdaClickHandler>([=](
_rightAction->link = std::make_shared<LambdaClickHandler>([=](
ClickContext context) {
const auto controller = ExtractController(context).value_or(nullptr);
if (!controller) {
@ -3129,7 +3187,7 @@ ClickHandlerPtr Message::rightActionLink() const {
}
}
});
return _rightActionLink;
return _rightAction->link;
}
ClickHandlerPtr Message::fastReplyLink() const {

View File

@ -130,6 +130,7 @@ public:
bool displayFastReply() const override;
bool displayRightActionComments() const;
std::optional<QSize> rightActionSize() const override;
void applyRightActionLastPoint(QPoint p) const override;
void drawRightAction(
Painter &p,
const PaintContext &context,
@ -168,6 +169,7 @@ protected:
private:
struct CommentsButton;
struct FromNameStatus;
struct RightAction;
void initLogEntryOriginal();
void initPsa();
@ -186,6 +188,9 @@ private:
void toggleTopicButtonRipple(bool pressed);
void createTopicButtonRipple();
void toggleRightActionRipple(bool pressed);
void createRightActionRipple();
void paintCommentsButton(
Painter &p,
QRect &g,
@ -288,7 +293,7 @@ private:
void refreshReactions();
void validateFromNameText(PeerData *from) const;
mutable ClickHandlerPtr _rightActionLink;
mutable std::unique_ptr<RightAction> _rightAction;
mutable ClickHandlerPtr _fastReplyLink;
mutable std::unique_ptr<ViewButton> _viewButton;
std::unique_ptr<Reactions::InlineList> _reactions;

View File

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/chat/chat_style.h"
#include "ui/click_handler.h"
#include "ui/effects/radial_animation.h"
#include "ui/effects/ripple_animation.h"
#include "ui/painter.h"
#include "api/api_transcribes.h"
#include "apiwrap.h"
@ -68,12 +69,25 @@ void TranscribeButton::paint(
const auto stm = context.messageStyle();
if (_roundview) {
_lastPaintedPoint = { x, y };
const auto r = QRect(QPoint(x, y), size());
if (_ripple) {
const auto colorOverride = &stm->msgWaveformInactive->c;
_ripple->paint(
p,
x,
y,
r.width(),
colorOverride);
if (_ripple->empty()) {
_ripple.reset();
}
}
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
p.setBrush(context.st->msgServiceBg());
const auto r = QRect(QPoint(x, y), size());
p.drawEllipse(r);
context.st->historyFastTranscribeIcon().paintInCenter(p, r);
@ -195,8 +209,25 @@ ClickHandlerPtr TranscribeButton::link() {
return _link;
}
QRect TranscribeButton::lastPaintedRect() const {
return { _lastPaintedPoint, size() };
bool TranscribeButton::contains(const QPoint &p) {
_lastStatePoint = p - _lastPaintedPoint;
return QRect(_lastPaintedPoint, size()).contains(p);
}
void TranscribeButton::addRipple(Fn<void()> callback) {
if (!_ripple) {
_ripple = std::make_unique<Ui::RippleAnimation>(
st::defaultRippleAnimation,
Ui::RippleAnimation::EllipseMask(size()),
std::move(callback));
}
_ripple->add(_lastStatePoint);
}
void TranscribeButton::stopRipple() const {
if (_ripple) {
_ripple->lastStop();
}
}
} // namespace HistoryView

View File

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui {
struct ChatPaintContext;
class InfiniteRadialAnimation;
class RippleAnimation;
} // namespace Ui
namespace HistoryView {
@ -28,9 +29,11 @@ public:
void setOpened(bool opened, Fn<void()> update);
void setLoading(bool loading, Fn<void()> update);
void paint(QPainter &p, int x, int y, const PaintContext &context);
void addRipple(Fn<void()> callback);
void stopRipple() const;
[[nodiscard]] ClickHandlerPtr link();
[[nodiscard]] QRect lastPaintedRect() const;
[[nodiscard]] bool contains(const QPoint &p);
private:
const not_null<HistoryItem*> _item;
@ -38,12 +41,14 @@ private:
const QSize _size;
mutable std::unique_ptr<Ui::InfiniteRadialAnimation> _animation;
std::unique_ptr<Ui::RippleAnimation> _ripple;
ClickHandlerPtr _link;
QString _text;
Ui::Animations::Simple _openedAnimation;
bool _loading = false;
bool _opened = false;
QPoint _lastPaintedPoint;
QPoint _lastStatePoint;
};

View File

@ -394,6 +394,8 @@ TextState ExtendedPreview::textState(QPoint point, StateRequest request) const {
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point
- QPoint(fastShareLeft, fastShareTop));
}
}
}

View File

@ -1033,15 +1033,32 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
}
if (QRect(QPoint(fastShareLeft, fastShareTop), *size).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point
- QPoint(fastShareLeft, fastShareTop));
}
}
if (_transcribe && _transcribe->lastPaintedRect().contains(point)) {
if (_transcribe && _transcribe->contains(point)) {
result.link = _transcribe->link();
}
}
return result;
}
void Gif::clickHandlerPressedChanged(
const ClickHandlerPtr &handler,
bool pressed) {
File::clickHandlerPressedChanged(handler, pressed);
if (!handler) {
return;
} else if (_transcribe && (handler == _transcribe->link())) {
if (pressed) {
_transcribe->addRipple([=] { repaint(); });
} else {
_transcribe->stopRipple();
}
}
}
TextForMimeData Gif::selectedText(TextSelection selection) const {
return _caption.toTextForMimeData(selection);
}

View File

@ -50,6 +50,10 @@ public:
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
void clickHandlerPressedChanged(
const ClickHandlerPtr &p,
bool pressed) override;
[[nodiscard]] TextSelection adjustSelection(
TextSelection selection,
TextSelectType type) const override {

View File

@ -335,6 +335,8 @@ TextState Location::textState(QPoint point, StateRequest request) const {
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point
- QPoint(fastShareLeft, fastShareTop));
}
}
}

View File

@ -462,6 +462,8 @@ TextState GroupedMedia::textState(QPoint point, StateRequest request) const {
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point
- QPoint(fastShareLeft, fastShareTop));
}
}
}

View File

@ -486,6 +486,7 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
*rightActionSize);
if (QRect(position.x(), position.y(), rightActionSize->width(), rightActionSize->height()).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point - position);
return result;
}
}

View File

@ -566,6 +566,8 @@ TextState Photo::textState(QPoint point, StateRequest request) const {
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point
- QPoint(fastShareLeft, fastShareTop));
}
}
}