mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Display reply background emoji.
This commit is contained in:
parent
60fb5fdaf0
commit
9c23de7f1a
6 changed files with 211 additions and 10 deletions
|
@ -627,9 +627,9 @@ bool PeerData::changeColorIndex(
|
|||
: clearColorIndex();
|
||||
}
|
||||
|
||||
bool PeerData::changeBackgroundEmoji(
|
||||
bool PeerData::changeBackgroundEmojiId(
|
||||
const tl::conditional<MTPlong> &cloudBackgroundEmoji) {
|
||||
return changeBackgroundEmoji(cloudBackgroundEmoji
|
||||
return changeBackgroundEmojiId(cloudBackgroundEmoji
|
||||
? cloudBackgroundEmoji->v
|
||||
: DocumentId());
|
||||
}
|
||||
|
@ -869,7 +869,11 @@ bool PeerData::clearColorIndex() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PeerData::changeBackgroundEmoji(uint64 id) {
|
||||
DocumentId PeerData::backgroundEmojiId() const {
|
||||
return _backgroundEmojiId;
|
||||
}
|
||||
|
||||
bool PeerData::changeBackgroundEmojiId(DocumentId id) {
|
||||
if (_backgroundEmojiId == id) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -169,7 +169,8 @@ public:
|
|||
}
|
||||
bool changeColorIndex(uint8 index);
|
||||
bool clearColorIndex();
|
||||
bool changeBackgroundEmoji(uint64 id);
|
||||
[[nodiscard]] DocumentId backgroundEmojiId() const;
|
||||
bool changeBackgroundEmojiId(DocumentId id);
|
||||
|
||||
[[nodiscard]] bool isUser() const {
|
||||
return peerIsUser(id);
|
||||
|
@ -361,7 +362,7 @@ public:
|
|||
|
||||
void setSettings(const MTPPeerSettings &data);
|
||||
bool changeColorIndex(const tl::conditional<MTPint> &cloudColorIndex);
|
||||
bool changeBackgroundEmoji(
|
||||
bool changeBackgroundEmojiId(
|
||||
const tl::conditional<MTPlong> &cloudBackgroundEmoji);
|
||||
|
||||
enum class BlockStatus : char {
|
||||
|
|
|
@ -711,7 +711,7 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
|
|||
flags |= UpdateFlag::Color;
|
||||
decorationsUpdated = true;
|
||||
}
|
||||
if (result->changeBackgroundEmoji(data.vbackground_emoji_id())) {
|
||||
if (result->changeBackgroundEmojiId(data.vbackground_emoji_id())) {
|
||||
flags |= UpdateFlag::BackgroundEmoji;
|
||||
decorationsUpdated = true;
|
||||
}
|
||||
|
@ -997,7 +997,7 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
|
|||
flags |= UpdateFlag::Color;
|
||||
decorationsUpdated = true;
|
||||
}
|
||||
if (result->changeBackgroundEmoji(data.vbackground_emoji_id())) {
|
||||
if (result->changeBackgroundEmojiId(data.vbackground_emoji_id())) {
|
||||
flags |= UpdateFlag::BackgroundEmoji;
|
||||
decorationsUpdated = true;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mainwindow.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
#include "media/player/media_player_instance.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
|
@ -55,6 +56,127 @@ namespace {
|
|||
|
||||
const auto kPsaForwardedPrefix = "cloud_lng_forwarded_psa_";
|
||||
|
||||
void ValidateBackgroundEmoji(
|
||||
DocumentId backgroundEmojiId,
|
||||
not_null<Ui::BackgroundEmojiData*> data,
|
||||
not_null<Ui::BackgroundEmojiCache*> cache,
|
||||
not_null<Ui::Text::QuotePaintCache*> quote,
|
||||
not_null<const HistoryView::Element*> holder) {
|
||||
if (data->firstFrameMask.isNull()) {
|
||||
if (!cache->frames[0].isNull()) {
|
||||
for (auto &frame : cache->frames) {
|
||||
frame = QImage();
|
||||
}
|
||||
}
|
||||
const auto tag = Data::CustomEmojiSizeTag::Isolated;
|
||||
if (!data->emoji) {
|
||||
const auto owner = &holder->history()->owner();
|
||||
const auto repaint = crl::guard(holder, [=] {
|
||||
holder->history()->owner().requestViewRepaint(holder);
|
||||
});
|
||||
data->emoji = owner->customEmojiManager().create(
|
||||
backgroundEmojiId,
|
||||
repaint,
|
||||
tag);
|
||||
}
|
||||
if (!data->emoji->ready()) {
|
||||
return;
|
||||
}
|
||||
const auto size = Data::FrameSizeFromTag(tag);
|
||||
data->firstFrameMask = QImage(
|
||||
QSize(size, size),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
data->firstFrameMask.fill(Qt::transparent);
|
||||
data->firstFrameMask.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
auto p = Painter(&data->firstFrameMask);
|
||||
data->emoji->paint(p, {
|
||||
.textColor = QColor(255, 255, 255),
|
||||
.position = QPoint(0, 0),
|
||||
.internal = {
|
||||
.forceFirstFrame = true,
|
||||
},
|
||||
});
|
||||
p.end();
|
||||
|
||||
data->emoji = nullptr;
|
||||
}
|
||||
if (!cache->frames[0].isNull() && cache->color == quote->icon) {
|
||||
return;
|
||||
}
|
||||
cache->color = quote->icon;
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
auto colorized = QImage(
|
||||
data->firstFrameMask.size(),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
colorized.setDevicePixelRatio(ratio);
|
||||
style::colorizeImage(
|
||||
data->firstFrameMask,
|
||||
cache->color,
|
||||
&colorized,
|
||||
QRect(), // src
|
||||
QPoint(), // dst
|
||||
true); // use alpha
|
||||
const auto make = [&](int size) {
|
||||
size = style::ConvertScale(size) * ratio;
|
||||
auto result = colorized.scaled(
|
||||
size,
|
||||
size,
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
result.setDevicePixelRatio(ratio);
|
||||
return result;
|
||||
};
|
||||
|
||||
constexpr auto kSize1 = 12;
|
||||
constexpr auto kSize2 = 16;
|
||||
constexpr auto kSize3 = 20;
|
||||
cache->frames[0] = make(kSize1);
|
||||
cache->frames[1] = make(kSize2);
|
||||
cache->frames[2] = make(kSize3);
|
||||
}
|
||||
|
||||
void FillBackgroundEmoji(
|
||||
Painter &p,
|
||||
const QRect &rect,
|
||||
bool quote,
|
||||
const Ui::BackgroundEmojiCache &cache) {
|
||||
p.setClipRect(rect);
|
||||
|
||||
const auto &frames = cache.frames;
|
||||
const auto right = rect.x() + rect.width();
|
||||
const auto paint = [&](int x, int y, int index, float64 opacity) {
|
||||
y = style::ConvertScale(y);
|
||||
if (y >= rect.height()) {
|
||||
return;
|
||||
}
|
||||
p.setOpacity(opacity);
|
||||
p.drawImage(
|
||||
right - style::ConvertScale(x + (quote ? 12 : 0)),
|
||||
rect.y() + y,
|
||||
frames[index]);
|
||||
};
|
||||
|
||||
paint(28, 4, 2, 0.32);
|
||||
paint(51, 15, 1, 0.32);
|
||||
paint(64, -2, 0, 0.28);
|
||||
paint(87, 11, 1, 0.24);
|
||||
paint(125, -2, 2, 0.16);
|
||||
|
||||
paint(28, 31, 1, 0.24);
|
||||
paint(72, 33, 2, 0.2);
|
||||
|
||||
paint(46, 52, 1, 0.24);
|
||||
paint(24, 55, 2, 0.18);
|
||||
|
||||
if (quote) {
|
||||
paint(4, 23, 1, 0.28);
|
||||
paint(0, 48, 0, 0.24);
|
||||
}
|
||||
|
||||
p.setClipping(false);
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void HistoryMessageVia::create(
|
||||
|
@ -676,10 +798,18 @@ void HistoryMessageReply::paint(
|
|||
const auto rect = QRect(x, y, w, _height);
|
||||
const auto hasQuote = !_fields.quote.empty();
|
||||
const auto selected = context.selected();
|
||||
const auto colorIndexPlusOne = resolvedMessage
|
||||
? (resolvedMessage->colorIndex() + 1)
|
||||
const auto colorPeer = resolvedMessage
|
||||
? resolvedMessage->displayFrom()
|
||||
: resolvedStory
|
||||
? (resolvedStory->peer()->colorIndex() + 1)
|
||||
? resolvedStory->peer().get()
|
||||
: nullptr;
|
||||
const auto backgroundEmojiId = colorPeer
|
||||
? colorPeer->backgroundEmojiId()
|
||||
: DocumentId();
|
||||
const auto colorIndexPlusOne = colorPeer
|
||||
? (colorPeer->colorIndex() + 1)
|
||||
: resolvedMessage
|
||||
? (resolvedMessage->hiddenSenderInfo()->colorIndex + 1)
|
||||
: 0;
|
||||
const auto useColorIndex = colorIndexPlusOne && !context.outbg;
|
||||
const auto twoColored = colorIndexPlusOne
|
||||
|
@ -698,12 +828,33 @@ void HistoryMessageReply::paint(
|
|||
const auto "eSt = hasQuote
|
||||
? st::messageTextStyle.blockquote
|
||||
: st::messageQuoteStyle;
|
||||
const auto backgroundEmoji = backgroundEmojiId
|
||||
? st->backgroundEmojiData(backgroundEmojiId).get()
|
||||
: nullptr;
|
||||
const auto backgroundEmojiCache = backgroundEmoji
|
||||
? &backgroundEmoji->caches[Ui::BackgroundEmojiData::CacheIndex(
|
||||
selected,
|
||||
context.outbg,
|
||||
inBubble,
|
||||
colorIndexPlusOne)]
|
||||
: nullptr;
|
||||
const auto rippleColor = cache->bg;
|
||||
if (!inBubble) {
|
||||
cache->bg = QColor(0, 0, 0, 0);
|
||||
}
|
||||
Ui::Text::ValidateQuotePaintCache(*cache, quoteSt);
|
||||
Ui::Text::FillQuotePaint(p, rect, *cache, quoteSt);
|
||||
if (backgroundEmoji) {
|
||||
ValidateBackgroundEmoji(
|
||||
backgroundEmojiId,
|
||||
backgroundEmoji,
|
||||
backgroundEmojiCache,
|
||||
cache,
|
||||
holder);
|
||||
if (!backgroundEmojiCache->frames[0].isNull()) {
|
||||
FillBackgroundEmoji(p, rect, hasQuote, *backgroundEmojiCache);
|
||||
}
|
||||
}
|
||||
if (!inBubble) {
|
||||
cache->bg = rippleColor;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "ui/chat/chat_theme.h"
|
||||
#include "ui/image/image_prepare.h" // ImageRoundRadius
|
||||
#include "ui/text/text_custom_emoji.h"
|
||||
#include "ui/color_contrast.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/ui_utility.h"
|
||||
|
@ -190,6 +191,17 @@ ColorIndexValues SimpleColorIndexValues(QColor color, bool twoColored) {
|
|||
};
|
||||
}
|
||||
|
||||
int BackgroundEmojiData::CacheIndex(
|
||||
bool selected,
|
||||
bool outbg,
|
||||
bool inbubble,
|
||||
uint8 colorIndexPlusOne) {
|
||||
const auto base = colorIndexPlusOne
|
||||
? (colorIndexPlusOne - 1)
|
||||
: (kColorIndexCount + (!inbubble ? 0 : outbg ? 1 : 2));
|
||||
return (base * 2) + (selected ? 1 : 0);
|
||||
};
|
||||
|
||||
ChatStyle::ChatStyle() {
|
||||
finalize();
|
||||
make(_historyPsaForwardPalette, st::historyPsaForwardPalette);
|
||||
|
@ -553,6 +565,8 @@ ChatStyle::ChatStyle(not_null<const style::palette*> isolated)
|
|||
assignPalette(isolated);
|
||||
}
|
||||
|
||||
ChatStyle::~ChatStyle() = default;
|
||||
|
||||
void ChatStyle::apply(not_null<ChatTheme*> theme) {
|
||||
applyCustomPalette(theme->palette());
|
||||
}
|
||||
|
@ -802,6 +816,11 @@ const style::TextPalette &ChatStyle::coloredTextPalette(
|
|||
return result.data;
|
||||
}
|
||||
|
||||
not_null<BackgroundEmojiData*> ChatStyle::backgroundEmojiData(
|
||||
uint64 id) const {
|
||||
return &_backgroundEmojis[id];
|
||||
}
|
||||
|
||||
not_null<Text::QuotePaintCache*> ChatStyle::coloredQuoteCache(
|
||||
bool selected,
|
||||
uint8 colorIndex) const {
|
||||
|
|
|
@ -21,6 +21,10 @@ struct TwoIconButton;
|
|||
struct ScrollArea;
|
||||
} // namespace style
|
||||
|
||||
namespace Ui::Text {
|
||||
class CustomEmoji;
|
||||
} // namespace Ui::Text
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class ChatTheme;
|
||||
|
@ -112,6 +116,23 @@ struct ReactionPaintInfo {
|
|||
Fn<QRect(QPainter&)> effectPaint;
|
||||
};
|
||||
|
||||
struct BackgroundEmojiCache {
|
||||
QColor color;
|
||||
std::array<QImage, 3> frames;
|
||||
};
|
||||
|
||||
struct BackgroundEmojiData {
|
||||
std::unique_ptr<Text::CustomEmoji> emoji;
|
||||
QImage firstFrameMask;
|
||||
std::array<BackgroundEmojiCache, 2 * (3 + kColorIndexCount)> caches;
|
||||
|
||||
[[nodiscard]] static int CacheIndex(
|
||||
bool selected,
|
||||
bool outbg,
|
||||
bool inbubble,
|
||||
uint8 colorIndexPlusOne);
|
||||
};
|
||||
|
||||
struct ChatPaintContext {
|
||||
not_null<const ChatStyle*> st;
|
||||
const BubblePattern *bubblesPattern = nullptr;
|
||||
|
@ -185,6 +206,7 @@ class ChatStyle final : public style::palette {
|
|||
public:
|
||||
ChatStyle();
|
||||
explicit ChatStyle(not_null<const style::palette*> isolated);
|
||||
~ChatStyle();
|
||||
|
||||
void apply(not_null<ChatTheme*> theme);
|
||||
void applyCustomPalette(const style::palette *palette);
|
||||
|
@ -242,6 +264,9 @@ public:
|
|||
bool selected,
|
||||
uint8 colorIndex) const;
|
||||
|
||||
[[nodiscard]] not_null<BackgroundEmojiData*> backgroundEmojiData(
|
||||
uint64 id) const;
|
||||
|
||||
[[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCornersSmall() const;
|
||||
[[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCornersLarge() const;
|
||||
[[nodiscard]] const CornersPixmaps &msgSelectOverlayCorners(
|
||||
|
@ -408,6 +433,7 @@ private:
|
|||
mutable std::array<
|
||||
ColoredPalette,
|
||||
2 * kColorIndexCount> _coloredTextPalettes;
|
||||
mutable base::flat_map<uint64, BackgroundEmojiData> _backgroundEmojis;
|
||||
|
||||
style::TextPalette _historyPsaForwardPalette;
|
||||
style::TextPalette _imgReplyTextPalette;
|
||||
|
|
Loading…
Add table
Reference in a new issue