Fixed simple animation of message sending with custom chat themes.

This commit is contained in:
23rd 2022-02-11 09:38:44 +03:00 committed by John Preston
parent a0a857a6db
commit 6939da2fd2
7 changed files with 60 additions and 44 deletions

View file

@ -838,6 +838,19 @@ void HistoryInner::paintEmpty(
_emptyPainter->paint(p, st, width, height); _emptyPainter->paint(p, st, width, height);
} }
Ui::ChatPaintContext HistoryInner::preparePaintContext(
const QRect &clip) const {
const auto visibleAreaTopGlobal = mapToGlobal(
QPoint(0, _visibleAreaTop)).y();
return _controller->preparePaintContext({
.theme = _theme.get(),
.visibleAreaTop = _visibleAreaTop,
.visibleAreaTopGlobal = visibleAreaTopGlobal,
.visibleAreaWidth = width(),
.clip = clip,
});
}
void HistoryInner::paintEvent(QPaintEvent *e) { void HistoryInner::paintEvent(QPaintEvent *e) {
if (Ui::skipPaintEvent(this, e)) { if (Ui::skipPaintEvent(this, e)) {
return; return;
@ -852,15 +865,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
auto clip = e->rect(); auto clip = e->rect();
const auto visibleAreaTopGlobal = mapToGlobal( auto context = preparePaintContext(clip);
QPoint(0, _visibleAreaTop)).y();
auto context = _controller->preparePaintContext({
.theme = _theme.get(),
.visibleAreaTop = _visibleAreaTop,
.visibleAreaTopGlobal = visibleAreaTopGlobal,
.visibleAreaWidth = width(),
.clip = clip,
});
_pathGradient->startFrame( _pathGradient->startFrame(
0, 0,
width(), width(),

View file

@ -44,6 +44,7 @@ class ChatTheme;
class ChatStyle; class ChatStyle;
class PopupMenu; class PopupMenu;
enum class ReportReason; enum class ReportReason;
struct ChatPaintContext;
class PathShiftGradient; class PathShiftGradient;
} // namespace Ui } // namespace Ui
@ -89,6 +90,8 @@ public:
return _theme.get(); return _theme.get();
} }
Ui::ChatPaintContext preparePaintContext(const QRect &clip) const;
void messagesReceived(PeerData *peer, const QVector<MTPMessage> &messages); void messagesReceived(PeerData *peer, const QVector<MTPMessage> &messages);
void messagesReceivedDown(PeerData *peer, const QVector<MTPMessage> &messages); void messagesReceivedDown(PeerData *peer, const QVector<MTPMessage> &messages);

View file

@ -5413,7 +5413,7 @@ void HistoryWidget::startMessageSendingAnimation(
sendingAnimation.startAnimation({ sendingAnimation.startAnimation({
.globalEndGeometry = std::move(globalEndGeometry), .globalEndGeometry = std::move(globalEndGeometry),
.view = [=] { return item->mainView(); }, .view = [=] { return item->mainView(); },
.theme = _list->theme(), .paintContext = [=] { return _list->preparePaintContext({}); },
}); });
} }

View file

@ -1595,7 +1595,7 @@ void ListWidget::startMessageSendingAnimation(
sendingAnimation.startAnimation({ sendingAnimation.startAnimation({
.globalEndGeometry = std::move(globalEndGeometry), .globalEndGeometry = std::move(globalEndGeometry),
.view = [=] { return viewForItem(item); }, .view = [=] { return viewForItem(item); },
.theme = _delegate->listChatTheme(), .paintContext = [=] { return preparePaintContext({}); },
}); });
} }
@ -1733,6 +1733,17 @@ TextSelection ListWidget::itemRenderSelection(
return TextSelection(); return TextSelection();
} }
Ui::ChatPaintContext ListWidget::preparePaintContext(
const QRect &clip) const {
return controller()->preparePaintContext({
.theme = _delegate->listChatTheme(),
.visibleAreaTop = _visibleTop,
.visibleAreaTopGlobal = mapToGlobal(QPoint(0, _visibleTop)).y(),
.visibleAreaWidth = width(),
.clip = clip,
});
}
void ListWidget::paintEvent(QPaintEvent *e) { void ListWidget::paintEvent(QPaintEvent *e) {
if (Ui::skipPaintEvent(this, e)) { if (Ui::skipPaintEvent(this, e)) {
return; return;
@ -1762,13 +1773,7 @@ void ListWidget::paintEvent(QPaintEvent *e) {
_reactionsManager->startEffectsCollection(); _reactionsManager->startEffectsCollection();
auto top = itemTop(from->get()); auto top = itemTop(from->get());
auto context = controller()->preparePaintContext({ auto context = preparePaintContext(clip).translated(0, -top);
.theme = _delegate->listChatTheme(),
.visibleAreaTop = _visibleTop,
.visibleAreaTopGlobal = mapToGlobal(QPoint(0, _visibleTop)).y(),
.visibleAreaWidth = width(),
.clip = clip,
}).translated(0, -top);
p.translate(0, top); p.translate(0, top);
const auto &sendingAnimation = _controller->sendingAnimation(); const auto &sendingAnimation = _controller->sendingAnimation();
for (auto i = from; i != to; ++i) { for (auto i = from; i != to; ++i) {

View file

@ -22,6 +22,7 @@ class Session;
namespace Ui { namespace Ui {
class PopupMenu; class PopupMenu;
class ChatTheme; class ChatTheme;
struct ChatPaintContext;
} // namespace Ui } // namespace Ui
namespace Window { namespace Window {
@ -376,6 +377,8 @@ private:
void saveScrollState(); void saveScrollState();
void restoreScrollState(); void restoreScrollState();
Ui::ChatPaintContext preparePaintContext(const QRect &clip) const;
Element *viewForItem(FullMsgId itemId) const; Element *viewForItem(FullMsgId itemId) const;
Element *viewForItem(const HistoryItem *item) const; Element *viewForItem(const HistoryItem *item) const;
not_null<Element*> enforceViewForItem(not_null<HistoryItem*> item); not_null<Element*> enforceViewForItem(not_null<HistoryItem*> item);

View file

@ -48,10 +48,10 @@ private:
using Context = Ui::ChatPaintContext; using Context = Ui::ChatPaintContext;
void createSurrounding(); void createSurrounding();
not_null<HistoryView::Element*> view() const;
const not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;
Fn<not_null<HistoryView::Element*>()> _view; MessageSendingAnimationController::SendingInfoTo _toInfo;
not_null<ChatTheme*> _theme;
QRect _from; QRect _from;
QRect _to; QRect _to;
QRect _innerContentRect; QRect _innerContentRect;
@ -72,18 +72,18 @@ Content::Content(
MessageSendingAnimationController::SendingInfoTo &&to) MessageSendingAnimationController::SendingInfoTo &&to)
: RpWidget(parent) : RpWidget(parent)
, _controller(controller) , _controller(controller)
, _view(std::move(to.view)) , _toInfo(std::move(to))
, _theme(to.theme)
, _from(parent->mapFromGlobal(globalGeometryFrom)) , _from(parent->mapFromGlobal(globalGeometryFrom))
, _innerContentRect(_view()->media()->contentRectForReactions()) { , _innerContentRect(view()->media()->contentRectForReactions()) {
Expects(_view != nullptr); Expects(_toInfo.view != nullptr);
Expects(_toInfo.paintContext != nullptr);
show(); show();
setAttribute(Qt::WA_TransparentForMouseEvents); setAttribute(Qt::WA_TransparentForMouseEvents);
raise(); raise();
base::take( base::take(
to.globalEndGeometry _toInfo.globalEndGeometry
) | rpl::distinct_until_changed( ) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](const QRect &r) { ) | rpl::start_with_next([=](const QRect &r) {
_to = parent->mapFromGlobal(r); _to = parent->mapFromGlobal(r);
@ -117,10 +117,10 @@ Content::Content(
} }
if (value == 1.) { if (value == 1.) {
const auto view = _view(); const auto currentView = view();
const auto controller = _controller; const auto controller = _controller;
_destroyRequests.fire({}); _destroyRequests.fire({});
controller->session().data().requestViewRepaint(view); controller->session().data().requestViewRepaint(currentView);
} }
}; };
animationCallback(0.); animationCallback(0.);
@ -131,6 +131,10 @@ Content::Content(
HistoryView::ListWidget::kItemRevealDuration); HistoryView::ListWidget::kItemRevealDuration);
} }
not_null<HistoryView::Element*> Content::view() const {
return _toInfo.view();
}
void Content::paintEvent(QPaintEvent *e) { void Content::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
@ -145,14 +149,13 @@ void Content::paintEvent(QPaintEvent *e) {
(1 - progress) * OffsetMid(height(), _minScale)); (1 - progress) * OffsetMid(height(), _minScale));
p.scale(scale, scale); p.scale(scale, scale);
auto context = _controller->preparePaintContext({ const auto currentView = view();
.theme = _theme,
}); auto context = _toInfo.paintContext();
const auto view = _view();
context.skipDrawingParts = Context::SkipDrawingParts::Surrounding; context.skipDrawingParts = Context::SkipDrawingParts::Surrounding;
context.outbg = view->hasOutLayout(); context.outbg = currentView->hasOutLayout();
p.translate(-_innerContentRect.topLeft()); p.translate(-_innerContentRect.topLeft());
view->media()->draw(p, context); currentView->media()->draw(p, context);
} }
rpl::producer<> Content::destroyRequests() const { rpl::producer<> Content::destroyRequests() const {
@ -163,8 +166,8 @@ void Content::createSurrounding() {
_surrounding = base::make_unique_q<Ui::RpWidget>(parentWidget()); _surrounding = base::make_unique_q<Ui::RpWidget>(parentWidget());
_surrounding->setAttribute(Qt::WA_TransparentForMouseEvents); _surrounding->setAttribute(Qt::WA_TransparentForMouseEvents);
const auto view = _view(); const auto currentView = view();
const auto surroundingSize = view->innerGeometry().size(); const auto surroundingSize = currentView->innerGeometry().size();
const auto offset = _innerContentRect.topLeft(); const auto offset = _innerContentRect.topLeft();
_surrounding->resize(surroundingSize); _surrounding->resize(surroundingSize);
@ -194,16 +197,13 @@ void Content::createSurrounding() {
revProgress * OffsetMid(size.height() + offset.y(), _minScale)); revProgress * OffsetMid(size.height() + offset.y(), _minScale));
p.scale(scale, scale); p.scale(scale, scale);
auto context = _controller->preparePaintContext({ const auto currentView = view();
.theme = _theme,
});
const auto view = _view();
auto context = _toInfo.paintContext();
context.skipDrawingParts = Context::SkipDrawingParts::Content; context.skipDrawingParts = Context::SkipDrawingParts::Content;
context.outbg = view->hasOutLayout(); context.outbg = currentView->hasOutLayout();
view->media()->draw(p, context); currentView->media()->draw(p, context);
}, _surrounding->lifetime()); }, _surrounding->lifetime());
} }

View file

@ -21,7 +21,7 @@ class SessionController;
namespace Ui { namespace Ui {
class RpWidget; class RpWidget;
class ChatTheme; struct ChatPaintContext;
class MessageSendingAnimationController final { class MessageSendingAnimationController final {
public: public:
@ -31,7 +31,7 @@ public:
struct SendingInfoTo { struct SendingInfoTo {
rpl::producer<QRect> globalEndGeometry; rpl::producer<QRect> globalEndGeometry;
Fn<not_null<HistoryView::Element*>()> view; Fn<not_null<HistoryView::Element*>()> view;
not_null<Ui::ChatTheme*> theme; Fn<Ui::ChatPaintContext()> paintContext;
}; };
void appendSending(MessageSendingAnimationFrom from); void appendSending(MessageSendingAnimationFrom from);