mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Added ripple animation to right action in messages.
This commit is contained in:
parent
d55d383627
commit
0310d9902c
13 changed files with 150 additions and 17 deletions
|
@ -1227,6 +1227,9 @@ ClickHandlerPtr Element::rightActionLink() const {
|
|||
return ClickHandlerPtr();
|
||||
}
|
||||
|
||||
void Element::applyRightActionLastPoint(QPoint p) const {
|
||||
}
|
||||
|
||||
TimeId Element::displayedEditDate() const {
|
||||
return TimeId(0);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue