Correctly round spoiler animation in ExtendedMedia.

This commit is contained in:
John Preston 2022-09-09 20:09:51 +04:00
parent a919978a37
commit 2e8a03dfd1
37 changed files with 141 additions and 255 deletions

View file

@ -357,7 +357,8 @@ void BackgroundPreviewBox::paintTexts(Painter &p, crl::time ms) {
auto context = _controller->defaultChatTheme()->preparePaintContext( auto context = _controller->defaultChatTheme()->preparePaintContext(
_chatStyle.get(), _chatStyle.get(),
rect(), rect(),
rect()); rect(),
_controller->isGifPausedAtLeastFor(Window::GifPauseReason::Layer));
p.translate(0, textsTop()); p.translate(0, textsTop());
paintDate(p); paintDate(p);

View file

@ -194,7 +194,9 @@ void AddMessage(
auto context = theme->preparePaintContext( auto context = theme->preparePaintContext(
state->style.get(), state->style.get(),
widget->rect(), widget->rect(),
widget->rect()); widget->rect(),
controller->isGifPausedAtLeastFor(
Window::GifPauseReason::Layer));
context.outbg = view->hasOutLayout(); context.outbg = view->hasOutLayout();
{ {

View file

@ -639,7 +639,7 @@ void InnerWidget::elementShowTooltip(
Fn<void()> hiddenCallback) { Fn<void()> hiddenCallback) {
} }
bool InnerWidget::elementIsGifPaused() { bool InnerWidget::elementAnimationsPaused() {
return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any); return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
} }

View file

@ -124,7 +124,7 @@ public:
void elementShowTooltip( void elementShowTooltip(
const TextWithEntities &text, const TextWithEntities &text,
Fn<void()> hiddenCallback) override; Fn<void()> hiddenCallback) override;
bool elementIsGifPaused() override; bool elementAnimationsPaused() override;
bool elementHideReply( bool elementHideReply(
not_null<const HistoryView::Element*> view) override; not_null<const HistoryView::Element*> view) override;
bool elementShownUnread( bool elementShownUnread(

View file

@ -219,8 +219,8 @@ public:
_widget->elementShowTooltip(text, hiddenCallback); _widget->elementShowTooltip(text, hiddenCallback);
} }
} }
bool elementIsGifPaused() override { bool elementAnimationsPaused() override {
return _widget ? _widget->elementIsGifPaused() : false; return _widget ? _widget->elementAnimationsPaused() : false;
} }
bool elementHideReply(not_null<const Element*> view) override { bool elementHideReply(not_null<const Element*> view) override {
return false; return false;
@ -370,7 +370,7 @@ HistoryInner::HistoryInner(
setMouseTracking(true); setMouseTracking(true);
_controller->gifPauseLevelChanged( _controller->gifPauseLevelChanged(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
if (!elementIsGifPaused()) { if (!elementAnimationsPaused()) {
update(); update();
} }
}, lifetime()); }, lifetime());
@ -1098,7 +1098,6 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
p.translate(0, -top); p.translate(0, -top);
} }
const auto paused = elementIsGifPaused();
enumerateUserpics([&](not_null<Element*> view, int userpicTop) { enumerateUserpics([&](not_null<Element*> view, int userpicTop) {
// stop the enumeration if the userpic is below the painted rect // stop the enumeration if the userpic is below the painted rect
if (userpicTop >= clip.top() + clip.height()) { if (userpicTop >= clip.top() + clip.height()) {
@ -1117,7 +1116,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
userpicTop, userpicTop,
width(), width(),
st::msgPhotoSize, st::msgPhotoSize,
paused); context.paused);
} else if (const auto info = view->data()->hiddenSenderInfo()) { } else if (const auto info = view->data()->hiddenSenderInfo()) {
if (info->customUserpic.empty()) { if (info->customUserpic.empty()) {
info->emptyUserpic.paint( info->emptyUserpic.paint(
@ -3250,7 +3249,7 @@ void HistoryInner::elementShowTooltip(
_widget->showInfoTooltip(text, std::move(hiddenCallback)); _widget->showInfoTooltip(text, std::move(hiddenCallback));
} }
bool HistoryInner::elementIsGifPaused() { bool HistoryInner::elementAnimationsPaused() {
return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any); return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
} }

View file

@ -145,7 +145,7 @@ public:
void elementShowTooltip( void elementShowTooltip(
const TextWithEntities &text, const TextWithEntities &text,
Fn<void()> hiddenCallback); Fn<void()> hiddenCallback);
bool elementIsGifPaused(); bool elementAnimationsPaused();
void elementSendBotCommand( void elementSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context); const FullMsgId &context);

View file

@ -460,7 +460,7 @@ void HistoryMessageReply::paint(
p.setTextPalette(inBubble p.setTextPalette(inBubble
? stm->replyTextPalette ? stm->replyTextPalette
: st->imgReplyTextPalette()); : st->imgReplyTextPalette());
holder->prepareCustomEmojiPaint(p, replyToText); holder->prepareCustomEmojiPaint(p, context, replyToText);
replyToText.drawLeftElided(p, x + st::msgReplyBarSkip + previewSkip, y + st::msgReplyPadding.top() + st::msgServiceNameFont->height, w - st::msgReplyBarSkip - previewSkip, w + 2 * x); replyToText.drawLeftElided(p, x + st::msgReplyBarSkip + previewSkip, y + st::msgReplyPadding.top() + st::msgServiceNameFont->height, w - st::msgReplyBarSkip - previewSkip, w + 2 * x);
p.setTextPalette(stm->textPalette); p.setTextPalette(stm->textPalette);
} }

View file

@ -170,7 +170,7 @@ void SimpleElementDelegate::elementShowTooltip(
Fn<void()> hiddenCallback) { Fn<void()> hiddenCallback) {
} }
bool SimpleElementDelegate::elementIsGifPaused() { bool SimpleElementDelegate::elementAnimationsPaused() {
return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any); return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
} }
@ -419,12 +419,13 @@ void Element::clearCustomEmojiRepaint() const {
void Element::prepareCustomEmojiPaint( void Element::prepareCustomEmojiPaint(
Painter &p, Painter &p,
const PaintContext &context,
const Ui::Text::String &text) const { const Ui::Text::String &text) const {
if (!text.hasCustomEmoji()) { if (!text.hasCustomEmoji()) {
return; return;
} }
clearCustomEmojiRepaint(); clearCustomEmojiRepaint();
p.setInactive(delegate()->elementIsGifPaused()); p.setInactive(context.paused);
if (!_heavyCustomEmoji) { if (!_heavyCustomEmoji) {
_heavyCustomEmoji = true; _heavyCustomEmoji = true;
history()->owner().registerHeavyViewPart(const_cast<Element*>(this)); history()->owner().registerHeavyViewPart(const_cast<Element*>(this));
@ -433,31 +434,19 @@ void Element::prepareCustomEmojiPaint(
void Element::prepareCustomEmojiPaint( void Element::prepareCustomEmojiPaint(
Painter &p, Painter &p,
const PaintContext &context,
const Reactions::InlineList &reactions) const { const Reactions::InlineList &reactions) const {
if (!reactions.hasCustomEmoji()) { if (!reactions.hasCustomEmoji()) {
return; return;
} }
clearCustomEmojiRepaint(); clearCustomEmojiRepaint();
p.setInactive(delegate()->elementIsGifPaused()); p.setInactive(context.paused);
if (!_heavyCustomEmoji) { if (!_heavyCustomEmoji) {
_heavyCustomEmoji = true; _heavyCustomEmoji = true;
history()->owner().registerHeavyViewPart(const_cast<Element*>(this)); history()->owner().registerHeavyViewPart(const_cast<Element*>(this));
} }
} }
//void Element::externalLottieProgressing(bool external) const {
// if (const auto media = _media.get()) {
// media->externalLottieProgressing(external);
// }
//}
//
//bool Element::externalLottieTill(ExternalLottieInfo info) const {
// if (const auto media = _media.get()) {
// return media->externalLottieTill(info);
// }
// return true;
//}
void Element::repaint() const { void Element::repaint() const {
history()->owner().requestViewRepaint(this); history()->owner().requestViewRepaint(this);
} }

View file

@ -49,7 +49,6 @@ enum class InfoDisplayType : char;
struct StateRequest; struct StateRequest;
struct TextState; struct TextState;
class Media; class Media;
//struct ExternalLottieInfo;
enum class Context : char { enum class Context : char {
History, History,
@ -92,7 +91,7 @@ public:
virtual void elementShowTooltip( virtual void elementShowTooltip(
const TextWithEntities &text, const TextWithEntities &text,
Fn<void()> hiddenCallback) = 0; Fn<void()> hiddenCallback) = 0;
virtual bool elementIsGifPaused() = 0; virtual bool elementAnimationsPaused() = 0;
virtual bool elementHideReply(not_null<const Element*> view) = 0; virtual bool elementHideReply(not_null<const Element*> view) = 0;
virtual bool elementShownUnread(not_null<const Element*> view) = 0; virtual bool elementShownUnread(not_null<const Element*> view) = 0;
virtual void elementSendBotCommand( virtual void elementSendBotCommand(
@ -154,7 +153,7 @@ public:
void elementShowTooltip( void elementShowTooltip(
const TextWithEntities &text, const TextWithEntities &text,
Fn<void()> hiddenCallback) override; Fn<void()> hiddenCallback) override;
bool elementIsGifPaused() override; bool elementAnimationsPaused() override;
bool elementHideReply(not_null<const Element*> view) override; bool elementHideReply(not_null<const Element*> view) override;
bool elementShownUnread(not_null<const Element*> view) override; bool elementShownUnread(not_null<const Element*> view) override;
void elementSendBotCommand( void elementSendBotCommand(
@ -262,9 +261,6 @@ public:
Context context() const; Context context() const;
void refreshDataId(); void refreshDataId();
//void externalLottieProgressing(bool external) const;
//bool externalLottieTill(ExternalLottieInfo info) const;
QDateTime dateTime() const; QDateTime dateTime() const;
int y() const; int y() const;
@ -420,9 +416,11 @@ public:
void customEmojiRepaint(); void customEmojiRepaint();
void prepareCustomEmojiPaint( void prepareCustomEmojiPaint(
Painter &p, Painter &p,
const PaintContext &context,
const Ui::Text::String &text) const; const Ui::Text::String &text) const;
void prepareCustomEmojiPaint( void prepareCustomEmojiPaint(
Painter &p, Painter &p,
const PaintContext &context,
const Reactions::InlineList &reactions) const; const Reactions::InlineList &reactions) const;
void clearCustomEmojiRepaint() const; void clearCustomEmojiRepaint() const;

View file

@ -45,8 +45,8 @@ constexpr auto kDropDelayedAfterDelay = crl::time(2000);
EmojiInteractions::EmojiInteractions( EmojiInteractions::EmojiInteractions(
not_null<Main::Session*> session, not_null<Main::Session*> session,
Fn<int(not_null<const Element*>)> itemTop) Fn<int(not_null<const Element*>)> itemTop)
: _session(session) : _session(session)
, _itemTop(std::move(itemTop)) { , _itemTop(std::move(itemTop)) {
_session->data().viewRemoved( _session->data().viewRemoved(
) | rpl::filter([=] { ) | rpl::filter([=] {
return !_plays.empty() || !_delayed.empty(); return !_plays.empty() || !_delayed.empty();
@ -58,13 +58,7 @@ EmojiInteractions::EmojiInteractions(
}, _lifetime); }, _lifetime);
} }
EmojiInteractions::~EmojiInteractions() { EmojiInteractions::~EmojiInteractions() = default;
//for (const auto &play : _plays) {
// if (play.premium) {
// play.view->externalLottieProgressing(false);
// }
//}
}
void EmojiInteractions::play( void EmojiInteractions::play(
ChatHelpers::EmojiInteractionPlayRequest request, ChatHelpers::EmojiInteractionPlayRequest request,
@ -98,17 +92,11 @@ bool EmojiInteractions::playPremiumEffect(
if (replacing) { if (replacing) {
const auto i = ranges::find(_plays, replacing, &Play::view); const auto i = ranges::find(_plays, replacing, &Play::view);
if (i != end(_plays)) { if (i != end(_plays)) {
//if (i->premium) {
// replacing->externalLottieProgressing(false);
//}
if (already) { if (already) {
_plays.erase(i); _plays.erase(i);
} else { } else {
i->view = view; i->view = view;
} }
//if (i->premium) {
// view->externalLottieProgressing(true);
//}
return true; return true;
} }
} else if (already) { } else if (already) {
@ -135,8 +123,6 @@ void EmojiInteractions::cancelPremiumEffect(not_null<const Element*> view) {
_plays.erase(ranges::remove_if(_plays, [&](const Play &play) { _plays.erase(ranges::remove_if(_plays, [&](const Play &play) {
if (play.view != view) { if (play.view != view) {
return false; return false;
//} else if (play.premium) {
// play.view->externalLottieProgressing(false);
} }
return true; return true;
}), end(_plays)); }), end(_plays));
@ -199,9 +185,6 @@ void EmojiInteractions::play(
} }
}); });
}, lottie->lifetime()); }, lottie->lifetime());
//if (premium) {
// view->externalLottieProgressing(true);
//}
_plays.push_back({ _plays.push_back({
.view = view, .view = view,
.lottie = std::move(lottie), .lottie = std::move(lottie),
@ -281,19 +264,11 @@ void EmojiInteractions::paint(QPainter &p) {
p.drawImage( p.drawImage(
QRect(rect.topLeft(), frame.image.size() / factor), QRect(rect.topLeft(), frame.image.size() / factor),
frame.image); frame.image);
//const auto info = HistoryView::ExternalLottieInfo{ play.lottie->markFrameShown();
// .frame = frame.index,
// .count = play.framesCount,
//};
//if (!play.premium || play.view->externalLottieTill(info)) {
play.lottie->markFrameShown();
//}
} }
_plays.erase(ranges::remove_if(_plays, [](const Play &play) { _plays.erase(ranges::remove_if(_plays, [](const Play &play) {
if (!play.finished) { if (!play.finished) {
return false; return false;
//} else if (play.premium) {
// play.view->externalLottieProgressing(false);
} }
return true; return true;
}), end(_plays)); }), end(_plays));

View file

@ -1471,7 +1471,7 @@ void ListWidget::elementShowTooltip(
_topToast.show(parentWidget(), text, hiddenCallback); _topToast.show(parentWidget(), text, hiddenCallback);
} }
bool ListWidget::elementIsGifPaused() { bool ListWidget::elementAnimationsPaused() {
return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any); return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
} }

View file

@ -287,7 +287,7 @@ public:
void elementShowTooltip( void elementShowTooltip(
const TextWithEntities &text, const TextWithEntities &text,
Fn<void()> hiddenCallback) override; Fn<void()> hiddenCallback) override;
bool elementIsGifPaused() override; bool elementAnimationsPaused() override;
bool elementHideReply(not_null<const Element*> view) override; bool elementHideReply(not_null<const Element*> view) override;
bool elementShownUnread(not_null<const Element*> view) override; bool elementShownUnread(not_null<const Element*> view) override;
void elementSendBotCommand( void elementSendBotCommand(

View file

@ -746,7 +746,7 @@ void Message::draw(Painter &p, const PaintContext &context) const {
g.setHeight(g.height() - reactionsHeight); g.setHeight(g.height() - reactionsHeight);
const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip); const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
p.translate(reactionsPosition); p.translate(reactionsPosition);
prepareCustomEmojiPaint(p, *_reactions); prepareCustomEmojiPaint(p, context, *_reactions);
_reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition)); _reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition));
if (context.reactionInfo) { if (context.reactionInfo) {
context.reactionInfo->position = reactionsPosition; context.reactionInfo->position = reactionsPosition;
@ -802,7 +802,7 @@ void Message::draw(Painter &p, const PaintContext &context) const {
trect.setHeight(trect.height() - reactionsHeight); trect.setHeight(trect.height() - reactionsHeight);
const auto reactionsPosition = QPoint(trect.left(), trect.top() + trect.height() + reactionsTop); const auto reactionsPosition = QPoint(trect.left(), trect.top() + trect.height() + reactionsTop);
p.translate(reactionsPosition); p.translate(reactionsPosition);
prepareCustomEmojiPaint(p, *_reactions); prepareCustomEmojiPaint(p, context, *_reactions);
_reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition)); _reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition));
if (context.reactionInfo) { if (context.reactionInfo) {
context.reactionInfo->position = reactionsPosition; context.reactionInfo->position = reactionsPosition;
@ -1152,7 +1152,7 @@ void Message::paintFromName(
.position = QPoint( .position = QPoint(
x - 2 * _fromNameStatus->skip, x - 2 * _fromNameStatus->skip,
y + _fromNameStatus->skip), y + _fromNameStatus->skip),
.paused = delegate()->elementIsGifPaused(), .paused = context.paused,
}); });
} else { } else {
st::dialogsPremiumIcon.paint(p, x, y, width(), color); st::dialogsPremiumIcon.paint(p, x, y, width(), color);
@ -1298,7 +1298,7 @@ void Message::paintText(
const auto stm = context.messageStyle(); const auto stm = context.messageStyle();
p.setPen(stm->historyTextFg); p.setPen(stm->historyTextFg);
p.setFont(st::msgFont); p.setFont(st::msgFont);
prepareCustomEmojiPaint(p, item->_text); prepareCustomEmojiPaint(p, context, item->_text);
item->_text.draw( item->_text.draw(
p, p,
trect.x(), trect.x(),

View file

@ -538,7 +538,7 @@ void Service::draw(Painter &p, const PaintContext &context) const {
p.setBrush(Qt::NoBrush); p.setBrush(Qt::NoBrush);
p.setPen(st->msgServiceFg()); p.setPen(st->msgServiceFg());
p.setFont(st::msgServiceFont); p.setFont(st::msgServiceFont);
prepareCustomEmojiPaint(p, item->_text); prepareCustomEmojiPaint(p, context, item->_text);
item->_text.draw( item->_text.draw(
p, p,
trect.x(), trect.x(),

View file

@ -211,7 +211,6 @@ void CustomEmoji::draw(
auto x = r.x(); auto x = r.x();
auto y = r.y(); auto y = r.y();
const auto perRow = std::max(r.width() / _singleSize, 1); const auto perRow = std::max(r.width() / _singleSize, 1);
const auto paused = _parent->delegate()->elementIsGifPaused();
for (auto &line : _lines) { for (auto &line : _lines) {
const auto count = int(line.size()); const auto count = int(line.size());
const auto rows = std::max((count + perRow - 1) / perRow, 1); const auto rows = std::max((count + perRow - 1) / perRow, 1);
@ -221,7 +220,7 @@ void CustomEmoji::draw(
if (index >= count) { if (index >= count) {
break; break;
} }
paintElement(p, x, y, line[index], context, paused); paintElement(p, x, y, line[index], context);
x += _singleSize; x += _singleSize;
} }
x = r.x(); x = r.x();
@ -235,12 +234,11 @@ void CustomEmoji::paintElement(
int x, int x,
int y, int y,
LargeCustomEmoji &element, LargeCustomEmoji &element,
const PaintContext &context, const PaintContext &context) {
bool paused) {
if (const auto sticker = std::get_if<StickerPtr>(&element)) { if (const auto sticker = std::get_if<StickerPtr>(&element)) {
paintSticker(p, x, y, sticker->get(), context, paused); paintSticker(p, x, y, sticker->get(), context);
} else if (const auto custom = std::get_if<CustomPtr>(&element)) { } else if (const auto custom = std::get_if<CustomPtr>(&element)) {
paintCustom(p, x, y, custom->get(), context, paused); paintCustom(p, x, y, custom->get(), context);
} }
} }
@ -249,8 +247,7 @@ void CustomEmoji::paintSticker(
int x, int x,
int y, int y,
not_null<Sticker*> sticker, not_null<Sticker*> sticker,
const PaintContext &context, const PaintContext &context) {
bool paused) {
sticker->draw(p, context, { QPoint(x, y), sticker->countOptimalSize() }); sticker->draw(p, context, { QPoint(x, y), sticker->countOptimalSize() });
} }
@ -259,8 +256,7 @@ void CustomEmoji::paintCustom(
int x, int x,
int y, int y,
not_null<Ui::Text::CustomEmoji*> emoji, not_null<Ui::Text::CustomEmoji*> emoji,
const PaintContext &context, const PaintContext &context) {
bool paused) {
if (!_hasHeavyPart) { if (!_hasHeavyPart) {
_hasHeavyPart = true; _hasHeavyPart = true;
_parent->history()->owner().registerHeavyViewPart(_parent); _parent->history()->owner().registerHeavyViewPart(_parent);
@ -280,7 +276,7 @@ void CustomEmoji::paintCustom(
emoji->paint(q, { emoji->paint(q, {
.preview = preview, .preview = preview,
.now = context.now, .now = context.now,
.paused = paused, .paused = context.paused,
}); });
q.end(); q.end();
@ -293,7 +289,7 @@ void CustomEmoji::paintCustom(
.preview = preview, .preview = preview,
.now = context.now, .now = context.now,
.position = { x, y }, .position = { x, y },
.paused = paused, .paused = context.paused,
}); });
} }
} }

View file

@ -64,22 +64,19 @@ private:
int x, int x,
int y, int y,
LargeCustomEmoji &element, LargeCustomEmoji &element,
const PaintContext &context, const PaintContext &context);
bool paused);
void paintSticker( void paintSticker(
Painter &p, Painter &p,
int x, int x,
int y, int y,
not_null<Sticker*> sticker, not_null<Sticker*> sticker,
const PaintContext &context, const PaintContext &context);
bool paused);
void paintCustom( void paintCustom(
Painter &p, Painter &p,
int x, int x,
int y, int y,
not_null<Ui::Text::CustomEmoji*> emoji, not_null<Ui::Text::CustomEmoji*> emoji,
const PaintContext &context, const PaintContext &context);
bool paused);
[[nodiscard]] not_null<Data::CustomEmojiManager::Listener*> listener() { [[nodiscard]] not_null<Data::CustomEmojiManager::Listener*> listener() {
return this; return this;

View file

@ -694,7 +694,7 @@ void Document::draw(
} }
if (const auto captioned = Get<HistoryDocumentCaptioned>()) { if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
p.setPen(stm->historyTextFg); p.setPen(stm->historyTextFg);
_parent->prepareCustomEmojiPaint(p, captioned->_caption); _parent->prepareCustomEmojiPaint(p, context, captioned->_caption);
captioned->_caption.draw(p, st::msgPadding.left(), captiontop, captionw, style::al_left, 0, -1, selection); captioned->_caption.draw(p, st::msgPadding.left(), captiontop, captionw, style::al_left, 0, -1, selection);
} }
} }

View file

@ -7,27 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "history/view/media/history_view_extended_preview.h" #include "history/view/media/history_view_extended_preview.h"
//#include "history/history_item_components.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "history/history.h" #include "history/history.h"
#include "history/view/history_view_element.h" #include "history/view/history_view_element.h"
#include "history/view/history_view_cursor_state.h" #include "history/view/history_view_cursor_state.h"
#include "history/view/media/history_view_media_common.h" #include "history/view/media/history_view_media_common.h"
//#include "main/main_session.h"
//#include "main/main_session_settings.h"
#include "media/streaming/media_streaming_utility.h" #include "media/streaming/media_streaming_utility.h"
#include "ui/effects/spoiler_mess.h" #include "ui/effects/spoiler_mess.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "ui/image/image_prepare.h"
#include "ui/chat/chat_style.h" #include "ui/chat/chat_style.h"
//#include "ui/cached_round_corners.h"
#include "data/data_session.h" #include "data/data_session.h"
//#include "data/data_streaming.h"
//#include "data/data_photo.h"
//#include "data/data_photo_media.h"
//#include "data/data_file_click_handler.h"
//#include "data/data_file_origin.h"
//#include "data/data_auto_download.h"
//#include "core/application.h"
#include "payments/payments_checkout_process.h" #include "payments/payments_checkout_process.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -88,7 +78,10 @@ bool ExtendedPreview::hasHeavyPart() const {
} }
void ExtendedPreview::unloadHeavyPart() { void ExtendedPreview::unloadHeavyPart() {
_inlineThumbnail = _imageCache = QImage(); _inlineThumbnail
= _imageCache
= _cornerCache
= _buttonBackground = QImage();
_animation = nullptr; _animation = nullptr;
_caption.unloadCustomEmoji(); _caption.unloadCustomEmoji();
} }
@ -193,29 +186,16 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const {
| ((isRoundedInBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None)); | ((isRoundedInBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None));
validateImageCache(rthumb.size(), roundRadius, roundCorners); validateImageCache(rthumb.size(), roundRadius, roundCorners);
p.drawImage(rthumb.topLeft(), _imageCache); p.drawImage(rthumb.topLeft(), _imageCache);
fillSpoilerMess(p, context.now, rthumb, roundRadius, roundCorners); fillSpoilerMess(p, rthumb, roundRadius, roundCorners, context);
paintButtonBackground(p, rthumb, context);
if (context.selected()) { if (context.selected()) {
Ui::FillComplexOverlayRect(p, st, rthumb, roundRadius, roundCorners); Ui::FillComplexOverlayRect(p, st, rthumb, roundRadius, roundCorners);
} }
const auto innerSize = st::msgFileLayout.thumbSize;
QRect inner(rthumb.x() + (rthumb.width() - innerSize) / 2, rthumb.y() + (rthumb.height() - innerSize) / 2, innerSize, innerSize);
p.setPen(Qt::NoPen);
if (context.selected()) {
p.setBrush(st->msgDateImgBgSelected());
} else {
const auto over = ClickHandler::showAsActive(_link);
p.setBrush(over ? st->msgDateImgBgOver() : st->msgDateImgBg());
}
{
PainterHighQualityEnabler hq(p);
p.drawEllipse(inner);
}
// date // date
if (!_caption.isEmpty()) { if (!_caption.isEmpty()) {
p.setPen(stm->historyTextFg); p.setPen(stm->historyTextFg);
_parent->prepareCustomEmojiPaint(p, _caption); _parent->prepareCustomEmojiPaint(p, context, _caption);
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection); _caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection);
} else if (!inWebPage) { } else if (!inWebPage) {
auto fullRight = paintx + paintw; auto fullRight = paintx + paintw;
@ -268,10 +248,10 @@ QImage ExtendedPreview::prepareImageCache(QSize outer) const {
void ExtendedPreview::fillSpoilerMess( void ExtendedPreview::fillSpoilerMess(
QPainter &p, QPainter &p,
crl::time now,
QRect rect, QRect rect,
ImageRoundRadius radius, ImageRoundRadius radius,
RectParts corners) const { RectParts corners,
const PaintContext &context) const {
if (!_animation) { if (!_animation) {
_animation = std::make_unique<Ui::SpoilerAnimation>([=] { _animation = std::make_unique<Ui::SpoilerAnimation>([=] {
_parent->customEmojiRepaint(); _parent->customEmojiRepaint();
@ -280,23 +260,47 @@ void ExtendedPreview::fillSpoilerMess(
} }
_parent->clearCustomEmojiRepaint(); _parent->clearCustomEmojiRepaint();
const auto &spoiler = Ui::DefaultImageSpoiler(); const auto &spoiler = Ui::DefaultImageSpoiler();
const auto size = spoiler.canvasSize() / style::DevicePixelRatio(); const auto index = _animation->index(context.now, context.paused);
const auto frame = spoiler.frame( Ui::FillSpoilerRect(
_animation->index(now, _parent->delegate()->elementIsGifPaused())); p,
const auto columns = (rect.width() + size - 1) / size; rect,
const auto rows = (rect.height() + size - 1) / size; radius,
p.setClipRect(rect); corners,
p.translate(rect.topLeft()); spoiler.frame(index),
for (auto y = 0; y != rows; ++y) { _cornerCache);
for (auto x = 0; x != columns; ++x) { }
p.drawImage(
QRect(x * size, y * size, size, size), void ExtendedPreview::paintButtonBackground(
*frame.image, QPainter &p,
frame.source); QRect outer,
const PaintContext &context) const {
const auto st = context.st;
const auto height = st::msgFileLayout.thumbSize;
const auto width = height * 4;
const auto overlay = st->msgDateImgBg()->c;
if (_buttonBackground.isNull() || _buttonBackgroundOverlay != overlay) {
const auto ratio = style::DevicePixelRatio();
if (_imageCache.width() < width * ratio
|| _imageCache.height() < height * ratio) {
return;
} }
_buttonBackground = _imageCache.copy(QRect(
(_imageCache.width() - width * ratio) / 2,
(_imageCache.height() - height * ratio) / 2,
width * ratio,
height * ratio));
_buttonBackground.setDevicePixelRatio(ratio);
auto p = QPainter(&_buttonBackground);
p.fillRect(0, 0, width, height, overlay);
p.end();
_buttonBackground = Images::Round(
std::move(_buttonBackground),
Images::CornersMask(height / 2));
} }
p.translate(-rect.topLeft()); p.drawImage(
p.setClipping(false); outer.x() + (outer.width() - width) / 2,
outer.y() + (outer.height() - height) / 2,
_buttonBackground);
} }
TextState ExtendedPreview::textState(QPoint point, StateRequest request) const { TextState ExtendedPreview::textState(QPoint point, StateRequest request) const {

View file

@ -85,13 +85,17 @@ private:
ImageRoundRadius radius, ImageRoundRadius radius,
RectParts corners) const; RectParts corners) const;
[[nodiscard]] QImage prepareImageCache(QSize outer) const; [[nodiscard]] QImage prepareImageCache(QSize outer) const;
void paintButtonBackground(
QPainter &p,
QRect outer,
const PaintContext &context) const;
void fillSpoilerMess( void fillSpoilerMess(
QPainter &p, QPainter &p,
crl::time now,
QRect rect, QRect rect,
ImageRoundRadius radius, ImageRoundRadius radius,
RectParts corners) const; RectParts corners,
const PaintContext &context) const;
const not_null<Data::Invoice*> _invoice; const not_null<Data::Invoice*> _invoice;
ClickHandlerPtr _link; ClickHandlerPtr _link;
@ -99,6 +103,9 @@ private:
mutable std::unique_ptr<Ui::SpoilerAnimation> _animation; mutable std::unique_ptr<Ui::SpoilerAnimation> _animation;
mutable QImage _inlineThumbnail; mutable QImage _inlineThumbnail;
mutable QImage _imageCache; mutable QImage _imageCache;
mutable QImage _cornerCache;
mutable QImage _buttonBackground;
mutable QColor _buttonBackgroundOverlay;
mutable int _imageCacheRoundRadius : 4 = 0; mutable int _imageCacheRoundRadius : 4 = 0;
mutable int _imageCacheRoundCorners : 12 = 0; mutable int _imageCacheRoundCorners : 12 = 0;
mutable int _imageCacheInvalid : 1 = 0; mutable int _imageCacheInvalid : 1 = 0;

View file

@ -245,7 +245,7 @@ void Game::draw(Painter &p, const PaintContext &context) const {
if (_description.hasSkipBlock()) { if (_description.hasSkipBlock()) {
endskip = _parent->skipBlockWidth(); endskip = _parent->skipBlockWidth();
} }
_parent->prepareCustomEmojiPaint(p, _description); _parent->prepareCustomEmojiPaint(p, context, _description);
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(context.selection)); _description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(context.selection));
tshift += _descriptionLines * lineHeight; tshift += _descriptionLines * lineHeight;
} }

View file

@ -279,7 +279,6 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
const auto st = context.st; const auto st = context.st;
const auto sti = context.imageStyle(); const auto sti = context.imageStyle();
const auto stm = context.messageStyle(); const auto stm = context.messageStyle();
const auto autoPaused = _parent->delegate()->elementIsGifPaused();
const auto cornerDownload = downloadInCorner(); const auto cornerDownload = downloadInCorner();
const auto canBePlayed = _dataMedia->canBePlayed(_realParent); const auto canBePlayed = _dataMedia->canBePlayed(_realParent);
const auto autoplay = autoplayEnabled() const auto autoplay = autoplayEnabled()
@ -383,7 +382,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
const auto skipDrawingContent = context.skipDrawingParts const auto skipDrawingContent = context.skipDrawingParts
== PaintContext::SkipDrawingParts::Content; == PaintContext::SkipDrawingParts::Content;
if (streamed && !skipDrawingContent) { if (streamed && !skipDrawingContent) {
auto paused = autoPaused; auto paused = context.paused;
if (isRound) { if (isRound) {
if (activeRoundStreamed()) { if (activeRoundStreamed()) {
paused = false; paused = false;
@ -604,7 +603,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
} }
if (!unwrapped && !_caption.isEmpty()) { if (!unwrapped && !_caption.isEmpty()) {
p.setPen(stm->historyTextFg); p.setPen(stm->historyTextFg);
_parent->prepareCustomEmojiPaint(p, _caption); _parent->prepareCustomEmojiPaint(p, context, _caption);
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection); _caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection);
} else if (!inWebPage && !skipDrawingSurrounding) { } else if (!inWebPage && !skipDrawingSurrounding) {
auto fullRight = paintx + usex + usew; auto fullRight = paintx + usex + usew;
@ -992,7 +991,6 @@ void Gif::drawGrouped(
|| _data->displayLoading(); || _data->displayLoading();
const auto st = context.st; const auto st = context.st;
const auto sti = context.imageStyle(); const auto sti = context.imageStyle();
const auto autoPaused = _parent->delegate()->elementIsGifPaused();
const auto fullFeatured = fullFeaturedGrouped(sides); const auto fullFeatured = fullFeaturedGrouped(sides);
const auto cornerDownload = fullFeatured && downloadInCorner(); const auto cornerDownload = fullFeatured && downloadInCorner();
const auto canBePlayed = _dataMedia->canBePlayed(_realParent); const auto canBePlayed = _dataMedia->canBePlayed(_realParent);
@ -1033,7 +1031,6 @@ void Gif::drawGrouped(
const auto roundRadius = ImageRoundRadius::Large; const auto roundRadius = ImageRoundRadius::Large;
if (streamed) { if (streamed) {
const auto paused = autoPaused;
const auto original = sizeForAspectRatio(); const auto original = sizeForAspectRatio();
const auto originalWidth = style::ConvertScale(original.width()); const auto originalWidth = style::ConvertScale(original.width());
const auto originalHeight = style::ConvertScale(original.height()); const auto originalHeight = style::ConvertScale(original.height());
@ -1062,7 +1059,7 @@ void Gif::drawGrouped(
activeOwnPlaying->frozenStatusText = QString(); activeOwnPlaying->frozenStatusText = QString();
} }
p.drawImage(geometry, streamed->frame(request)); p.drawImage(geometry, streamed->frame(request));
if (!paused) { if (!context.paused) {
streamed->markFrameShown(); streamed->markFrameShown();
} }
} }
@ -1607,7 +1604,7 @@ void Gif::repaintStreamedContent() {
const auto own = activeOwnStreamed(); const auto own = activeOwnStreamed();
if (own && !own->frozenFrame.isNull()) { if (own && !own->frozenFrame.isNull()) {
return; return;
} else if (_parent->delegate()->elementIsGifPaused() } else if (_parent->delegate()->elementAnimationsPaused()
&& !activeRoundStreamed()) { && !activeRoundStreamed()) {
return; return;
} }

View file

@ -95,7 +95,6 @@ void LargeEmoji::draw(
const auto y = r.y() + (r.height() - _size.height()) / 2 + padding.top(); const auto y = r.y() + (r.height() - _size.height()) / 2 + padding.top();
const auto skip = st::largeEmojiSkip - 2 * st::largeEmojiOutline; const auto skip = st::largeEmojiSkip - 2 * st::largeEmojiOutline;
const auto size = LargeEmojiImage::Size() / cIntRetinaFactor(); const auto size = LargeEmojiImage::Size() / cIntRetinaFactor();
const auto paused = _parent->delegate()->elementIsGifPaused();
const auto selected = context.selected(); const auto selected = context.selected();
if (!selected) { if (!selected) {
_selectedFrame = QImage(); _selectedFrame = QImage();
@ -114,7 +113,7 @@ void LargeEmoji::draw(
(*image)->load(); (*image)->load();
} }
} else if (const auto custom = std::get_if<CustomPtr>(&media)) { } else if (const auto custom = std::get_if<CustomPtr>(&media)) {
paintCustom(p, x, y, custom->get(), context, paused); paintCustom(p, x, y, custom->get(), context);
} else { } else {
continue; continue;
} }
@ -127,8 +126,7 @@ void LargeEmoji::paintCustom(
int x, int x,
int y, int y,
not_null<Ui::Text::CustomEmoji*> emoji, not_null<Ui::Text::CustomEmoji*> emoji,
const PaintContext &context, const PaintContext &context) {
bool paused) {
if (!_hasHeavyPart) { if (!_hasHeavyPart) {
_hasHeavyPart = true; _hasHeavyPart = true;
_parent->history()->owner().registerHeavyViewPart(_parent); _parent->history()->owner().registerHeavyViewPart(_parent);
@ -151,7 +149,7 @@ void LargeEmoji::paintCustom(
emoji->paint(q, { emoji->paint(q, {
.preview = preview, .preview = preview,
.now = context.now, .now = context.now,
.paused = paused, .paused = context.paused,
}); });
q.end(); q.end();
@ -164,7 +162,7 @@ void LargeEmoji::paintCustom(
.preview = preview, .preview = preview,
.now = context.now, .now = context.now,
.position = { x + skip, y + skip }, .position = { x + skip, y + skip },
.paused = paused, .paused = context.paused,
}); });
} }
} }

View file

@ -50,8 +50,7 @@ private:
int x, int x,
int y, int y,
not_null<Ui::Text::CustomEmoji*> emoji, not_null<Ui::Text::CustomEmoji*> emoji,
const PaintContext &context, const PaintContext &context);
bool paused);
const not_null<Element*> _parent; const not_null<Element*> _parent;
const std::array<LargeEmojiMedia, Ui::Text::kIsolatedEmojiLimit> _images; const std::array<LargeEmojiMedia, Ui::Text::kIsolatedEmojiLimit> _images;

View file

@ -69,11 +69,6 @@ enum class MediaInBubbleState {
TimeId duration, TimeId duration,
const QString &base); const QString &base);
//struct ExternalLottieInfo {
// int frame = -1;
// int count = -1;
//};
class Media : public Object { class Media : public Object {
public: public:
explicit Media(not_null<Element*> parent) : _parent(parent) { explicit Media(not_null<Element*> parent) : _parent(parent) {
@ -178,15 +173,6 @@ public:
virtual void checkAnimation() { virtual void checkAnimation() {
} }
//virtual void externalLottieProgressing(bool external) {
//}
//virtual bool externalLottieTill(ExternalLottieInfo info) {
// return true;
//}
//virtual ExternalLottieInfo externalLottieInfo() const {
// return {};
//}
[[nodiscard]] virtual QSize sizeForGroupingOptimal(int maxWidth) const { [[nodiscard]] virtual QSize sizeForGroupingOptimal(int maxWidth) const {
Unexpected("Grouping method call."); Unexpected("Grouping method call.");
} }

View file

@ -344,7 +344,7 @@ void GroupedMedia::draw(Painter &p, const PaintContext &context) const {
- _caption.countHeight(captionw); - _caption.countHeight(captionw);
const auto stm = context.messageStyle(); const auto stm = context.messageStyle();
p.setPen(stm->historyTextFg); p.setPen(stm->historyTextFg);
_parent->prepareCustomEmojiPaint(p, _caption); _parent->prepareCustomEmojiPaint(p, context, _caption);
_caption.draw(p, st::msgPadding.left(), captiony, captionw, style::al_left, 0, -1, selection); _caption.draw(p, st::msgPadding.left(), captiony, captionw, style::al_left, 0, -1, selection);
} else if (_parent->media() == this) { } else if (_parent->media() == this) {
auto fullRight = width(); auto fullRight = width();

View file

@ -466,18 +466,6 @@ std::unique_ptr<StickerPlayer> UnwrappedMedia::stickerTakePlayer(
return _content->stickerTakePlayer(data, replacements); return _content->stickerTakePlayer(data, replacements);
} }
//void UnwrappedMedia::externalLottieProgressing(bool external) {
// _content->externalLottieProgressing(external);
//}
//
//bool UnwrappedMedia::externalLottieTill(ExternalLottieInfo info) {
// return _content->externalLottieTill(info);
//}
//
//ExternalLottieInfo UnwrappedMedia::externalLottieInfo() const {
// return _content->externalLottieInfo();
//}
int UnwrappedMedia::calculateFullRight(const QRect &inner) const { int UnwrappedMedia::calculateFullRight(const QRect &inner) const {
const auto rightAligned = _parent->hasOutLayout() const auto rightAligned = _parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide(); && !_parent->delegate()->elementIsChatWide();

View file

@ -42,15 +42,6 @@ public:
not_null<DocumentData*> data, not_null<DocumentData*> data,
const Lottie::ColorReplacements *replacements); const Lottie::ColorReplacements *replacements);
//virtual void externalLottieProgressing(bool external) {
//}
//virtual bool externalLottieTill(ExternalLottieInfo info) {
// return true;
//}
//virtual ExternalLottieInfo externalLottieInfo() const {
// return {};
//}
virtual bool hasHeavyPart() const { virtual bool hasHeavyPart() const {
return false; return false;
} }
@ -108,10 +99,6 @@ public:
not_null<DocumentData*> data, not_null<DocumentData*> data,
const Lottie::ColorReplacements *replacements) override; const Lottie::ColorReplacements *replacements) override;
//void externalLottieProgressing(bool external) override;
//bool externalLottieTill(ExternalLottieInfo info) override;
//ExternalLottieInfo externalLottieInfo() const override;
bool hasHeavyPart() const override { bool hasHeavyPart() const override {
return _content->hasHeavyPart(); return _content->hasHeavyPart();
} }

View file

@ -295,7 +295,7 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
// date // date
if (!_caption.isEmpty()) { if (!_caption.isEmpty()) {
p.setPen(stm->historyTextFg); p.setPen(stm->historyTextFg);
_parent->prepareCustomEmojiPaint(p, _caption); _parent->prepareCustomEmojiPaint(p, context, _caption);
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection); _caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection);
} else if (!inWebPage) { } else if (!inWebPage) {
auto fullRight = paintx + paintw; auto fullRight = paintx + paintw;
@ -384,7 +384,6 @@ void Photo::paintUserpicFrame(
if (_streamed if (_streamed
&& _streamed->instance.player().ready() && _streamed->instance.player().ready()
&& !_streamed->instance.player().videoSize().isEmpty()) { && !_streamed->instance.player().videoSize().isEmpty()) {
const auto paused = _parent->delegate()->elementIsGifPaused();
auto request = ::Media::Streaming::FrameRequest(); auto request = ::Media::Streaming::FrameRequest();
request.outer = size * cIntRetinaFactor(); request.outer = size * cIntRetinaFactor();
request.resize = size * cIntRetinaFactor(); request.resize = size * cIntRetinaFactor();
@ -397,7 +396,7 @@ void Photo::paintUserpicFrame(
} else { } else {
_streamed->frozenFrame = QImage(); _streamed->frozenFrame = QImage();
p.drawImage(rect, _streamed->instance.frame(request)); p.drawImage(rect, _streamed->instance.frame(request));
if (!paused) { if (!context.paused) {
_streamed->instance.markFrameShown(); _streamed->instance.markFrameShown();
} }
} }
@ -768,7 +767,7 @@ void Photo::handleStreamingError(::Media::Streaming::Error &&error) {
void Photo::repaintStreamedContent() { void Photo::repaintStreamedContent() {
if (_streamed && !_streamed->frozenFrame.isNull()) { if (_streamed && !_streamed->frozenFrame.isNull()) {
return; return;
} else if (_parent->delegate()->elementIsGifPaused()) { } else if (_parent->delegate()->elementAnimationsPaused()) {
return; return;
} }
repaint(); repaint();

View file

@ -22,7 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h" #include "core/application.h"
#include "core/core_settings.h" #include "core/core_settings.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "window/window_session_controller.h" // isGifPausedAtLeastFor. #include "window/window_session_controller.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_document_media.h" #include "data/data_document_media.h"
@ -81,7 +81,6 @@ Sticker::Sticker(
if (const auto media = replacing ? replacing->media() : nullptr) { if (const auto media = replacing ? replacing->media() : nullptr) {
_player = media->stickerTakePlayer(_data, _replacements); _player = media->stickerTakePlayer(_data, _replacements);
if (_player) { if (_player) {
//_externalInfo = media->externalLottieInfo();
if (hasPremiumEffect() && !_premiumEffectPlayed) { if (hasPremiumEffect() && !_premiumEffectPlayed) {
_premiumEffectPlayed = true; _premiumEffectPlayed = true;
_parent->delegate()->elementStartPremium(_parent, replacing); _parent->delegate()->elementStartPremium(_parent, replacing);
@ -227,16 +226,13 @@ void Sticker::paintAnimationFrame(
const auto colored = (context.selected() && !_nextLastDiceFrame) const auto colored = (context.selected() && !_nextLastDiceFrame)
? context.st->msgStickerOverlay()->c ? context.st->msgStickerOverlay()->c
: QColor(0, 0, 0, 0); : QColor(0, 0, 0, 0);
const auto paused = /*(_externalInfo.frame >= 0)
? (_frameIndex % _externalInfo.count >= _externalInfo.frame)
: */_parent->delegate()->elementIsGifPaused();
const auto frame = _player const auto frame = _player
? _player->frame( ? _player->frame(
_size, _size,
colored, colored,
mirrorHorizontal(), mirrorHorizontal(),
context.now, context.now,
paused) context.paused)
: StickerPlayer::FrameInfo(); : StickerPlayer::FrameInfo();
if (_nextLastDiceFrame) { if (_nextLastDiceFrame) {
_nextLastDiceFrame = false; _nextLastDiceFrame = false;
@ -265,7 +261,7 @@ void Sticker::paintAnimationFrame(
const auto count = _player->framesCount(); const auto count = _player->framesCount();
_frameIndex = frame.index; _frameIndex = frame.index;
_framesCount = count; _framesCount = count;
_nextLastDiceFrame = !paused _nextLastDiceFrame = !context.paused
&& (_diceIndex > 0) && (_diceIndex > 0)
&& (_frameIndex + 2 == count); && (_frameIndex + 2 == count);
const auto playOnce = (_diceIndex > 0) const auto playOnce = (_diceIndex > 0)
@ -275,10 +271,9 @@ void Sticker::paintAnimationFrame(
: ((!customEmojiPart() && isEmojiSticker()) : ((!customEmojiPart() && isEmojiSticker())
|| !Core::App().settings().loopAnimatedStickers()); || !Core::App().settings().loopAnimatedStickers());
const auto lastDiceFrame = (_diceIndex > 0) && atTheEnd(); const auto lastDiceFrame = (_diceIndex > 0) && atTheEnd();
const auto switchToNext = /*(_externalInfo.frame >= 0) const auto switchToNext = !playOnce
|| */!playOnce
|| (!lastDiceFrame && (_frameIndex != 0 || !_oncePlayed)); || (!lastDiceFrame && (_frameIndex != 0 || !_oncePlayed));
if (!paused if (!context.paused
&& switchToNext && switchToNext
&& _player->markFrameShown() && _player->markFrameShown()
&& playOnce && playOnce
@ -539,38 +534,4 @@ std::unique_ptr<StickerPlayer> Sticker::stickerTakePlayer(
: nullptr; : nullptr;
} }
//void Sticker::externalLottieProgressing(bool external) {
// _externalInfo = !external
// ? ExternalLottieInfo{}
// : (_externalInfo.frame > 0)
// ? _externalInfo
// : ExternalLottieInfo{ 0, 2 };
//}
//
//bool Sticker::externalLottieTill(ExternalLottieInfo info) {
// if (_externalInfo.frame >= 0) {
// _externalInfo = info;
// }
// return markFramesTillExternal();
//}
//
//ExternalLottieInfo Sticker::externalLottieInfo() const {
// return _externalInfo;
//}
//
//bool Sticker::markFramesTillExternal() {
// if (_externalInfo.frame < 0 || !_lottie) {
// return true;
// } else if (!_lottie->ready()) {
// return false;
// }
// const auto till = _externalInfo.frame % _lottie->framesCount();
// while (_lottie->frameIndex() < till) {
// if (!_lottie->markFrameShown()) {
// return false;
// }
// }
// return true;
//}
} // namespace HistoryView } // namespace HistoryView

View file

@ -57,10 +57,6 @@ public:
not_null<DocumentData*> data, not_null<DocumentData*> data,
const Lottie::ColorReplacements *replacements) override; const Lottie::ColorReplacements *replacements) override;
//void externalLottieProgressing(bool external) override;
//bool externalLottieTill(ExternalLottieInfo info) override;
//ExternalLottieInfo externalLottieInfo() const override;
bool hasHeavyPart() const override; bool hasHeavyPart() const override;
void unloadHeavyPart() override; void unloadHeavyPart() override;
@ -119,7 +115,6 @@ private:
void emojiStickerClicked(); void emojiStickerClicked();
void premiumStickerClicked(); void premiumStickerClicked();
void checkPremiumEffectStart(); void checkPremiumEffectStart();
//bool markFramesTillExternal();
const not_null<Element*> _parent; const not_null<Element*> _parent;
const not_null<DocumentData*> _data; const not_null<DocumentData*> _data;
@ -130,7 +125,6 @@ private:
QSize _size; QSize _size;
QImage _lastDiceFrame; QImage _lastDiceFrame;
QString _diceEmoji; QString _diceEmoji;
//ExternalLottieInfo _externalInfo;
int _diceIndex = -1; int _diceIndex = -1;
mutable int _frameIndex = -1; mutable int _frameIndex = -1;
mutable int _framesCount = -1; mutable int _framesCount = -1;

View file

@ -566,7 +566,7 @@ void WebPage::draw(Painter &p, const PaintContext &context) const {
if (_description.hasSkipBlock()) { if (_description.hasSkipBlock()) {
endskip = _parent->skipBlockWidth(); endskip = _parent->skipBlockWidth();
} }
_parent->prepareCustomEmojiPaint(p, _description); _parent->prepareCustomEmojiPaint(p, context, _description);
if (_descriptionLines > 0) { if (_descriptionLines > 0) {
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(context.selection)); _description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(context.selection));
tshift += _descriptionLines * lineHeight; tshift += _descriptionLines * lineHeight;

View file

@ -990,7 +990,9 @@ object_ptr<Ui::RpWidget> ForwardsPrivacyController::setupAboveWidget(
auto context = theme->preparePaintContext( auto context = theme->preparePaintContext(
_chatStyle.get(), _chatStyle.get(),
widget->rect(), widget->rect(),
widget->rect()); widget->rect(),
_controller->isGifPausedAtLeastFor(
Window::GifPauseReason::Layer));
p.translate(padding / 2, padding + view->marginBottom()); p.translate(padding / 2, padding + view->marginBottom());
context.outbg = view->hasOutLayout(); context.outbg = view->hasOutLayout();
view->draw(p, context); view->draw(p, context);

View file

@ -570,7 +570,8 @@ void ConfirmContactBox::paintEvent(QPaintEvent *e) {
auto context = theme->preparePaintContext( auto context = theme->preparePaintContext(
_chatStyle.get(), _chatStyle.get(),
rect(), rect(),
rect()); rect(),
controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Layer));
p.translate(st::boxPadding.left(), 0); p.translate(st::boxPadding.left(), 0);
if (_comment) { if (_comment) {
context.outbg = _comment->hasOutLayout(); context.outbg = _comment->hasOutLayout();

View file

@ -107,6 +107,7 @@ struct ChatPaintContext {
QRect clip; QRect clip;
TextSelection selection; TextSelection selection;
bool outbg = false; bool outbg = false;
bool paused = false;
crl::time now = 0; crl::time now = 0;
void translate(int x, int y) { void translate(int x, int y) {
@ -132,7 +133,7 @@ struct ChatPaintContext {
return translated(point.x(), point.y()); return translated(point.x(), point.y());
} }
[[nodiscard]] ChatPaintContext withSelection( [[nodiscard]] ChatPaintContext withSelection(
TextSelection selection) const { TextSelection selection) const {
auto result = *this; auto result = *this;
result.selection = selection; result.selection = selection;
return result; return result;

View file

@ -459,8 +459,10 @@ void ChatTheme::finishCreateOnMain() {
ChatPaintContext ChatTheme::preparePaintContext( ChatPaintContext ChatTheme::preparePaintContext(
not_null<const ChatStyle*> st, not_null<const ChatStyle*> st,
QRect viewport, QRect viewport,
QRect clip) { QRect clip,
bool paused) {
const auto area = viewport.size(); const auto area = viewport.size();
const auto now = crl::now();
if (!_bubblesBackgroundPrepared.isNull() if (!_bubblesBackgroundPrepared.isNull()
&& _bubblesBackground.area != area) { && _bubblesBackground.area != area) {
if (!_cacheBubblesTimer) { if (!_cacheBubblesTimer) {
@ -470,7 +472,7 @@ ChatPaintContext ChatTheme::preparePaintContext(
|| (!_cacheBubblesTimer->isActive() || (!_cacheBubblesTimer->isActive()
&& !_bubblesCachingRequest)) { && !_bubblesCachingRequest)) {
_cacheBubblesArea = area; _cacheBubblesArea = area;
_lastBubblesAreaChangeTime = crl::now(); _lastBubblesAreaChangeTime = now;
_cacheBubblesTimer->callOnce(kCacheBackgroundFastTimeout); _cacheBubblesTimer->callOnce(kCacheBackgroundFastTimeout);
} }
} }
@ -479,7 +481,8 @@ ChatPaintContext ChatTheme::preparePaintContext(
.bubblesPattern = _bubblesBackgroundPattern.get(), .bubblesPattern = _bubblesBackgroundPattern.get(),
.viewport = viewport, .viewport = viewport,
.clip = clip, .clip = clip,
.now = crl::now(), .paused = paused,
.now = now,
}; };
} }

View file

@ -171,7 +171,8 @@ public:
[[nodiscard]] ChatPaintContext preparePaintContext( [[nodiscard]] ChatPaintContext preparePaintContext(
not_null<const ChatStyle*> st, not_null<const ChatStyle*> st,
QRect viewport, QRect viewport,
QRect clip); QRect clip,
bool paused);
[[nodiscard]] const BackgroundState &backgroundState(QSize area); [[nodiscard]] const BackgroundState &backgroundState(QSize area);
void clearBackgroundState(); void clearBackgroundState();
[[nodiscard]] rpl::producer<> repaintBackgroundRequests() const; [[nodiscard]] rpl::producer<> repaintBackgroundRequests() const;

View file

@ -1909,7 +1909,8 @@ HistoryView::PaintContext SessionController::preparePaintContext(
return args.theme->preparePaintContext( return args.theme->preparePaintContext(
_chatStyle.get(), _chatStyle.get(),
viewport, viewport,
args.clip); args.clip,
isGifPausedAtLeastFor(GifPauseReason::Any));
} }
void SessionController::setPremiumRef(const QString &ref) { void SessionController::setPremiumRef(const QString &ref) {