Display custom emoji in custom notifications.

This commit is contained in:
John Preston 2022-07-01 20:06:23 +04:00
parent be36f07168
commit 8c8cbbbc83
4 changed files with 80 additions and 31 deletions

View file

@ -237,7 +237,8 @@ void CustomEmojiLoader::lookupDone(
auto loader = [=] { auto loader = [=] {
return std::make_unique<CustomEmojiLoader>(document, tag); return std::make_unique<CustomEmojiLoader>(document, tag);
}; };
lookup->process->loaded(Ui::CustomEmoji::Cached( auto done = std::move(lookup->process->loaded);
done(Ui::CustomEmoji::Cached(
SerializeCustomEmojiId(document), SerializeCustomEmojiId(document),
std::move(loader), std::move(loader),
std::move(*result))); std::move(*result)));

View file

@ -527,6 +527,7 @@ void Instance::paint(
_state = std::move(*caching); _state = std::move(*caching);
} else if (auto cached = std::get_if<Cached>(&result)) { } else if (auto cached = std::get_if<Cached>(&result)) {
_state = std::move(*cached); _state = std::move(*cached);
repaint();
} else { } else {
Unexpected("Value in Loader::LoadResult."); Unexpected("Value in Loader::LoadResult.");
} }

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/platform_notifications_manager.h" #include "platform/platform_notifications_manager.h"
#include "platform/platform_specific.h" #include "platform/platform_specific.h"
#include "core/application.h" #include "core/application.h"
#include "core/ui_integration.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
@ -732,7 +733,7 @@ void Notification::updateGeometry(int x, int y, int width, int height) {
void Notification::paintEvent(QPaintEvent *e) { void Notification::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
p.setClipRect(e->rect()); p.setClipRect(e->rect());
p.drawPixmap(0, 0, _cache); p.drawImage(0, 0, _cache);
auto buttonsTop = st::notifyTextTop + st::msgNameFont->height; auto buttonsTop = st::notifyTextTop + st::msgNameFont->height;
if (a_actionsOpacity.animating()) { if (a_actionsOpacity.animating()) {
@ -750,8 +751,40 @@ void Notification::actionsOpacityCallback() {
} }
} }
void Notification::customEmojiCallback() {
if (_textRepaintScheduled) {
return;
}
_textRepaintScheduled = true;
InvokeQueued(this, [=] {
_textRepaintScheduled = false;
if (_cache.isNull()) {
return;
}
Painter p(&_cache);
p.fillRect(_textRect, st::notificationBg);
paintText(p);
update();
});
}
void Notification::paintText(Painter &p) {
p.setTextPalette(st::dialogsTextPalette);
p.setPen(st::dialogsTextFg);
p.setFont(st::dialogsTextFont);
_textCache.drawElided(
p,
_textRect.left(),
_textRect.top(),
_textRect.width(),
_textRect.height() / st::dialogsTextFont->height);
p.restoreTextPalette();
}
void Notification::updateNotifyDisplay() { void Notification::updateNotifyDisplay() {
if (!_history || (!_item && _forwardedCount < 2)) return; if (!_history || (!_item && _forwardedCount < 2)) {
return;
}
const auto options = manager()->getNotificationOptions( const auto options = manager()->getNotificationOptions(
_item, _item,
@ -810,15 +843,13 @@ void Notification::updateNotifyDisplay() {
const auto composeText = !options.hideMessageText const auto composeText = !options.hideMessageText
|| (!_reaction.isEmpty() && !options.hideNameAndPhoto); || (!_reaction.isEmpty() && !options.hideNameAndPhoto);
if (composeText) { if (composeText) {
auto itemTextCache = Ui::Text::String(itemWidth); auto old = base::take(_textCache);
_textCache = Ui::Text::String(itemWidth);
auto r = QRect( auto r = QRect(
st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft,
st::notifyItemTop + st::msgNameFont->height, st::notifyItemTop + st::msgNameFont->height,
itemWidth, itemWidth,
2 * st::dialogsTextFont->height); 2 * st::dialogsTextFont->height);
p.setTextPalette(st::dialogsTextPalette);
p.setPen(st::dialogsTextFg);
p.setFont(st::dialogsTextFont);
const auto text = !_reaction.isEmpty() const auto text = !_reaction.isEmpty()
? (!_author.isEmpty() ? (!_author.isEmpty()
? Ui::Text::PlainLink(_author).append(' ') ? Ui::Text::PlainLink(_author).append(' ')
@ -842,20 +873,27 @@ void Notification::updateNotifyDisplay() {
_forwardedCount)) _forwardedCount))
: QString())); : QString()));
const auto options = TextParseOptions{ const auto options = TextParseOptions{
TextParsePlainLinks (TextParsePlainLinks
| (_forwardedCount > 1 ? TextParseMultiline : 0), | TextParseMarkdown
| (_forwardedCount > 1 ? TextParseMultiline : 0)),
0, 0,
0, 0,
Qt::LayoutDirectionAuto, Qt::LayoutDirectionAuto,
}; };
itemTextCache.setMarkedText(st::dialogsTextStyle, text, options); const auto context = Core::MarkedTextContext{
itemTextCache.drawElided( .session = &_history->session(),
p, .customEmojiRepaint = [=] { customEmojiCallback(); },
r.left(), };
r.top(), _textCache.setMarkedText(
r.width(), st::dialogsTextStyle,
r.height() / st::dialogsTextFont->height); text,
p.restoreTextPalette(); options,
context);
_textRect = r;
paintText(p);
if (!_textCache.hasCustomEmoji()) {
_textCache = Ui::Text::String();
}
} else { } else {
p.setFont(st::dialogsTextFont); p.setFont(st::dialogsTextFont);
p.setPen(st::dialogsTextFgService); p.setPen(st::dialogsTextFgService);
@ -881,7 +919,7 @@ void Notification::updateNotifyDisplay() {
titleText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); titleText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
} }
_cache = Ui::PixmapFromImage(std::move(img)); _cache = std::move(img);
if (!canReply()) { if (!canReply()) {
toggleActionButtons(false); toggleActionButtons(false);
} }
@ -898,18 +936,21 @@ void Notification::updatePeerPhoto() {
} }
_userpicLoaded = true; _userpicLoaded = true;
auto img = _cache.toImage(); Painter p(&_cache);
{ p.fillRect(
Painter p(&img); style::rtlrect(
_peer->paintUserpicLeft( QRect(
p, st::notifyPhotoPos,
_userpicView, QSize(st::notifyPhotoSize, st::notifyPhotoSize)),
st::notifyPhotoPos.x(), width()),
st::notifyPhotoPos.y(), st::notificationBg);
width(), _peer->paintUserpicLeft(
st::notifyPhotoSize); p,
} _userpicView,
_cache = Ui::PixmapFromImage(std::move(img)); st::notifyPhotoPos.x(),
st::notifyPhotoPos.y(),
width(),
st::notifyPhotoSize);
_userpicView = nullptr; _userpicView = nullptr;
update(); update();
} }

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/text/text.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "base/timer.h" #include "base/timer.h"
#include "base/binary_guard.h" #include "base/binary_guard.h"
@ -260,15 +261,20 @@ private:
void changeHeight(int newHeight); void changeHeight(int newHeight);
void updateGeometry(int x, int y, int width, int height) override; void updateGeometry(int x, int y, int width, int height) override;
void actionsOpacityCallback(); void actionsOpacityCallback();
void paintText(Painter &p);
void customEmojiCallback();
[[nodiscard]] Notifications::Manager::NotificationId myId() const; [[nodiscard]] Notifications::Manager::NotificationId myId() const;
const not_null<PeerData*> _peer; const not_null<PeerData*> _peer;
QPixmap _cache; QImage _cache;
Ui::Text::String _textCache;
QRect _textRect;
bool _hideReplyButton = false; bool _hideReplyButton = false;
bool _actionsVisible = false; bool _actionsVisible = false;
bool _textRepaintScheduled = false;
Ui::Animations::Simple a_actionsOpacity; Ui::Animations::Simple a_actionsOpacity;
QPixmap _buttonsCache; QPixmap _buttonsCache;