Fix custom emoji in service messages.

This commit is contained in:
John Preston 2022-07-01 19:17:29 +04:00
parent 289602528c
commit be36f07168
19 changed files with 85 additions and 67 deletions

View file

@ -376,8 +376,8 @@ void HistoryItem::invalidateChatListEntry() {
} }
void HistoryItem::customEmojiRepaint() { void HistoryItem::customEmojiRepaint() {
if (!_textRepaintScheduled) { if (!_customEmojiRepaintScheduled) {
_textRepaintScheduled = true; _customEmojiRepaintScheduled = true;
history()->owner().requestItemRepaint(this); history()->owner().requestItemRepaint(this);
} }
} }

View file

@ -474,7 +474,7 @@ protected:
Ui::Text::String _text = { st::msgMinWidth }; Ui::Text::String _text = { st::msgMinWidth };
int _textWidth = -1; int _textWidth = -1;
int _textHeight = 0; int _textHeight = 0;
bool _textRepaintScheduled = false; bool _customEmojiRepaintScheduled = false;
struct SavedMediaData { struct SavedMediaData {
TextWithEntities text; TextWithEntities text;

View file

@ -42,8 +42,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/style_window.h" #include "styles/style_window.h"
#include "data/stickers/data_custom_emoji.h"
namespace { namespace {
[[nodiscard]] MessageFlags NewForwardedFlags( [[nodiscard]] MessageFlags NewForwardedFlags(

View file

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_group_call.h" // Data::GroupCall::id(). #include "data/data_group_call.h" // Data::GroupCall::id().
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "core/ui_integration.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "base/timer_rpl.h" #include "base/timer_rpl.h"
#include "calls/calls_instance.h" // Core::App().calls().joinGroupCall. #include "calls/calls_instance.h" // Core::App().calls().joinGroupCall.
@ -925,7 +926,12 @@ HistoryService::PreparedText HistoryService::preparePinnedText() {
original = Ui::Text::Wrapped( original = Ui::Text::Wrapped(
Ui::Text::Filtered( Ui::Text::Filtered(
std::move(original), std::move(original),
{ EntityType::Spoiler, EntityType::StrikeOut }), {
EntityType::Spoiler,
EntityType::StrikeOut,
EntityType::Italic,
EntityType::CustomEmoji,
}),
EntityType::CustomUrl, EntityType::CustomUrl,
Ui::Text::Link({}, 2).entities.front().data()); Ui::Text::Link({}, 2).entities.front().data());
result.text = tr::lng_action_pinned_message( result.text = tr::lng_action_pinned_message(
@ -1251,10 +1257,15 @@ ClickHandlerPtr HistoryService::fromLink() const {
} }
void HistoryService::setServiceText(const PreparedText &prepared) { void HistoryService::setServiceText(const PreparedText &prepared) {
const auto context = Core::MarkedTextContext{
.session = &history()->session(),
.customEmojiRepaint = [=] { customEmojiRepaint(); },
};
_text.setMarkedText( _text.setMarkedText(
st::serviceTextStyle, st::serviceTextStyle,
prepared.text, prepared.text,
Ui::ItemTextServiceOptions()); Ui::ItemTextServiceOptions(),
context);
HistoryView::FillTextWithAnimatedSpoilers(_text); HistoryView::FillTextWithAnimatedSpoilers(_text);
auto linkIndex = 0; auto linkIndex = 0;
for (const auto &link : prepared.links) { for (const auto &link : prepared.links) {

View file

@ -413,6 +413,26 @@ void Element::refreshDataIdHook() {
} }
void Element::customEmojiRepaint() { void Element::customEmojiRepaint() {
if (!_customEmojiRepaintScheduled) {
_customEmojiRepaintScheduled = true;
history()->owner().requestViewRepaint(this);
}
}
void Element::prepareCustomEmojiPaint(
Painter &p,
const Ui::Text::String &text) const {
const auto item = data();
if (!text.hasCustomEmoji()) {
return;
}
_customEmojiRepaintScheduled = false;
item->_customEmojiRepaintScheduled = false;
p.setInactive(delegate()->elementIsGifPaused());
if (!_heavyCustomEmoji) {
_heavyCustomEmoji = true;
history()->owner().registerHeavyViewPart(const_cast<Element*>(this));
}
} }
//void Element::externalLottieProgressing(bool external) const { //void Element::externalLottieProgressing(bool external) const {
@ -900,7 +920,7 @@ auto Element::verticalRepaintRange() const -> VerticalRepaintRange {
} }
bool Element::hasHeavyPart() const { bool Element::hasHeavyPart() const {
return false; return _heavyCustomEmoji;
} }
void Element::checkHeavyPart() { void Element::checkHeavyPart() {
@ -921,6 +941,10 @@ void Element::unloadHeavyPart() {
if (_media) { if (_media) {
_media->unloadHeavyPart(); _media->unloadHeavyPart();
} }
if (_heavyCustomEmoji) {
_heavyCustomEmoji = false;
data()->_text.unloadCustomEmoji();
}
} }
HistoryBlock *Element::block() { HistoryBlock *Element::block() {
@ -1094,6 +1118,11 @@ auto Element::takeReactionAnimations()
Element::~Element() { Element::~Element() {
// Delete media while owner still exists. // Delete media while owner still exists.
base::take(_media); base::take(_media);
if (_heavyCustomEmoji) {
_heavyCustomEmoji = false;
data()->_text.unloadCustomEmoji();
checkHeavyPart();
}
if (_data->mainView() == this) { if (_data->mainView() == this) {
_data->clearMainView(); _data->clearMainView();
} }

View file

@ -427,7 +427,10 @@ public:
virtual QRect innerGeometry() const = 0; virtual QRect innerGeometry() const = 0;
virtual void customEmojiRepaint(); void customEmojiRepaint();
void prepareCustomEmojiPaint(
Painter &p,
const Ui::Text::String &text) const;
[[nodiscard]] ClickHandlerPtr fromPhotoLink() const { [[nodiscard]] ClickHandlerPtr fromPhotoLink() const {
return fromLink(); return fromLink();
@ -491,6 +494,9 @@ private:
std::unique_ptr<Media> _media; std::unique_ptr<Media> _media;
mutable ClickHandlerPtr _fromLink; mutable ClickHandlerPtr _fromLink;
bool _isScheduledUntilOnline = false; bool _isScheduledUntilOnline = false;
mutable bool _heavyCustomEmoji = false;
mutable bool _customEmojiRepaintScheduled = false;
const QDateTime _dateTime; const QDateTime _dateTime;
int _y = 0; int _y = 0;

View file

@ -275,12 +275,8 @@ Message::Message(
} }
Message::~Message() { Message::~Message() {
if (_comments || _heavyCustomEmoji) { if (_comments) {
_comments = nullptr; _comments = nullptr;
if (_heavyCustomEmoji) {
_heavyCustomEmoji = false;
message()->_text.unloadCustomEmoji();
}
checkHeavyPart(); checkHeavyPart();
} }
} }
@ -849,7 +845,6 @@ void Message::draw(Painter &p, const PaintContext &context) const {
auto mediaPosition = QPoint( auto mediaPosition = QPoint(
inner.left(), inner.left(),
trect.y() + trect.height() - mediaHeight); trect.y() + trect.height() - mediaHeight);
_mediaRepaintScheduled = false;
p.translate(mediaPosition); p.translate(mediaPosition);
media->draw(p, context.translated( media->draw(p, context.translated(
-mediaPosition -mediaPosition
@ -918,7 +913,6 @@ void Message::draw(Painter &p, const PaintContext &context) const {
media->paintBubbleFireworks(p, g, context.now); media->paintBubbleFireworks(p, g, context.now);
} }
} else if (media && media->isDisplayed()) { } else if (media && media->isDisplayed()) {
_mediaRepaintScheduled = false;
p.translate(g.topLeft()); p.translate(g.topLeft());
media->draw(p, context.translated( media->draw(p, context.translated(
-g.topLeft() -g.topLeft()
@ -1246,10 +1240,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);
const auto custom = item->_text.hasCustomEmoji(); prepareCustomEmojiPaint(p, item->_text);
if (custom) {
p.setInactive(delegate()->elementIsGifPaused());
}
item->_text.draw( item->_text.draw(
p, p,
trect.x(), trect.x(),
@ -1259,11 +1250,6 @@ void Message::paintText(
0, 0,
-1, -1,
context.selection); context.selection);
item->_textRepaintScheduled = false;
if (!_heavyCustomEmoji && custom) {
_heavyCustomEmoji = true;
history()->owner().registerHeavyViewPart(const_cast<Message*>(this));
}
} }
PointState Message::pointState(QPoint point) const { PointState Message::pointState(QPoint point) const {
@ -1390,16 +1376,12 @@ void Message::toggleCommentsButtonRipple(bool pressed) {
} }
bool Message::hasHeavyPart() const { bool Message::hasHeavyPart() const {
return _heavyCustomEmoji || _comments || Element::hasHeavyPart(); return _comments || Element::hasHeavyPart();
} }
void Message::unloadHeavyPart() { void Message::unloadHeavyPart() {
Element::unloadHeavyPart(); Element::unloadHeavyPart();
_comments = nullptr; _comments = nullptr;
if (_heavyCustomEmoji) {
_heavyCustomEmoji = false;
message()->_text.unloadCustomEmoji();
}
} }
bool Message::showForwardsFromSender( bool Message::showForwardsFromSender(
@ -2824,13 +2806,6 @@ QRect Message::innerGeometry() const {
return result; return result;
} }
void Message::customEmojiRepaint() {
if (!_mediaRepaintScheduled) {
_mediaRepaintScheduled = true;
history()->owner().requestViewRepaint(this);
}
}
QRect Message::countGeometry() const { QRect Message::countGeometry() const {
const auto commentsRoot = (context() == Context::Replies) const auto commentsRoot = (context() == Context::Replies)
&& data()->isDiscussionPost(); && data()->isDiscussionPost();

View file

@ -140,8 +140,6 @@ public:
QRect innerGeometry() const override; QRect innerGeometry() const override;
void customEmojiRepaint() override;
protected: protected:
void refreshDataIdHook() override; void refreshDataIdHook() override;
@ -254,8 +252,6 @@ private:
Ui::Text::String _rightBadge; Ui::Text::String _rightBadge;
int _bubbleWidthLimit = 0; int _bubbleWidthLimit = 0;
mutable bool _heavyCustomEmoji = false;
mutable bool _mediaRepaintScheduled = false;
BottomInfo _bottomInfo; BottomInfo _bottomInfo;

View file

@ -541,6 +541,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);
item->_text.draw(p, trect.x(), trect.y(), trect.width(), Qt::AlignCenter, 0, -1, context.selection, false); item->_text.draw(p, trect.x(), trect.y(), trect.width(), Qt::AlignCenter, 0, -1, context.selection, false);
p.restoreTextPalette(); p.restoreTextPalette();

View file

@ -672,7 +672,7 @@ void Document::draw(
} }
if (const auto captioned = Get<HistoryDocumentCaptioned>()) { if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
p.setPen(stm->historyTextFg); p.setPen(stm->historyTextFg);
applyCustomEmojiPause(p, captioned->_caption); _parent->prepareCustomEmojiPaint(p, 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);
} }
} }
@ -683,6 +683,9 @@ bool Document::hasHeavyPart() const {
void Document::unloadHeavyPart() { void Document::unloadHeavyPart() {
_dataMedia = nullptr; _dataMedia = nullptr;
if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
captioned->_caption.unloadCustomEmoji();
}
} }
void Document::ensureDataMediaCreated() const { void Document::ensureDataMediaCreated() const {

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();
} }
applyCustomEmojiPause(p, _description); _parent->prepareCustomEmojiPaint(p, _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;
} }
@ -445,6 +445,17 @@ void Game::parentTextUpdated() {
} }
} }
bool Game::hasHeavyPart() const {
return _attach ? _attach->hasHeavyPart() : false;
}
void Game::unloadHeavyPart() {
if (_attach) {
_attach->unloadHeavyPart();
}
_description.unloadCustomEmoji();
}
Game::~Game() { Game::~Game() {
history()->owner().unregisterGameView(_data, _parent); history()->owner().unregisterGameView(_data, _parent);
} }

View file

@ -80,14 +80,8 @@ public:
void parentTextUpdated() override; void parentTextUpdated() override;
bool hasHeavyPart() const override { bool hasHeavyPart() const override;
return _attach ? _attach->hasHeavyPart() : false; void unloadHeavyPart() override;
}
void unloadHeavyPart() override {
if (_attach) {
_attach->unloadHeavyPart();
}
}
~Game(); ~Game();

View file

@ -670,7 +670,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);
applyCustomEmojiPause(p, _caption); _parent->prepareCustomEmojiPaint(p, _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;
@ -1471,6 +1471,7 @@ void Gif::unloadHeavyPart() {
stopAnimation(); stopAnimation();
_dataMedia = nullptr; _dataMedia = nullptr;
_videoThumbnailFrame = nullptr; _videoThumbnailFrame = nullptr;
_caption.unloadCustomEmoji();
} }
void Gif::refreshParentId(not_null<HistoryItem*> realParent) { void Gif::refreshParentId(not_null<HistoryItem*> realParent) {

View file

@ -191,14 +191,6 @@ void Media::repaint() const {
history()->owner().requestViewRepaint(_parent); history()->owner().requestViewRepaint(_parent);
} }
void Media::applyCustomEmojiPause(
Painter &p,
const Ui::Text::String &text) const {
if (text.hasCustomEmoji()) {
p.setInactive(_parent->delegate()->elementIsGifPaused());
}
}
Ui::Text::String Media::createCaption(not_null<HistoryItem*> item) const { Ui::Text::String Media::createCaption(not_null<HistoryItem*> item) const {
if (item->emptyText()) { if (item->emptyText()) {
return {}; return {};

View file

@ -329,9 +329,6 @@ protected:
[[nodiscard]] bool usesBubblePattern(const PaintContext &context) const; [[nodiscard]] bool usesBubblePattern(const PaintContext &context) const;
void repaint() const; void repaint() const;
void applyCustomEmojiPause(
Painter &p,
const Ui::Text::String &text) const;
const not_null<Element*> _parent; const not_null<Element*> _parent;
MediaInBubbleState _inBubbleState = MediaInBubbleState::None; MediaInBubbleState _inBubbleState = MediaInBubbleState::None;

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);
applyCustomEmojiPause(p, _caption); _parent->prepareCustomEmojiPaint(p, _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();
@ -721,6 +721,7 @@ void GroupedMedia::unloadHeavyPart() {
part.cacheKey = 0; part.cacheKey = 0;
part.cache = QPixmap(); part.cache = QPixmap();
} }
_caption.unloadCustomEmoji();
} }
void GroupedMedia::parentTextUpdated() { void GroupedMedia::parentTextUpdated() {

View file

@ -133,6 +133,7 @@ bool Photo::hasHeavyPart() const {
void Photo::unloadHeavyPart() { void Photo::unloadHeavyPart() {
stopAnimation(); stopAnimation();
_dataMedia = nullptr; _dataMedia = nullptr;
_caption.unloadCustomEmoji();
} }
QSize Photo::countOptimalSize() { QSize Photo::countOptimalSize() {
@ -335,7 +336,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);
applyCustomEmojiPause(p, _caption); _parent->prepareCustomEmojiPaint(p, _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;

View file

@ -464,6 +464,7 @@ void WebPage::unloadHeavyPart() {
if (_attach) { if (_attach) {
_attach->unloadHeavyPart(); _attach->unloadHeavyPart();
} }
_description.unloadCustomEmoji();
_photoMedia = nullptr; _photoMedia = nullptr;
} }
@ -565,7 +566,7 @@ void WebPage::draw(Painter &p, const PaintContext &context) const {
if (_description.hasSkipBlock()) { if (_description.hasSkipBlock()) {
endskip = _parent->skipBlockWidth(); endskip = _parent->skipBlockWidth();
} }
applyCustomEmojiPause(p, _description); _parent->prepareCustomEmojiPaint(p, _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

@ -40,7 +40,8 @@ TextParseOptions HistoryServiceOptions = {
TextParseLinks TextParseLinks
| TextParseMentions | TextParseMentions
//| TextParseMultiline //| TextParseMultiline
| TextParseHashtags, // flags | TextParseHashtags
| TextParseMarkdown, // flags
0, // maxw 0, // maxw
0, // maxh 0, // maxh
Qt::LayoutDirectionAuto, // lang-dependent Qt::LayoutDirectionAuto, // lang-dependent