Show, send and receive interactions in single custom emoji.

This commit is contained in:
John Preston 2022-08-04 15:55:25 +03:00
parent 9e63fc5acd
commit e438cb57bc
18 changed files with 158 additions and 88 deletions

View file

@ -69,60 +69,26 @@ EmojiInteractions::~EmojiInteractions() = default;
void EmojiInteractions::checkEdition( void EmojiInteractions::checkEdition(
not_null<HistoryItem*> item, not_null<HistoryItem*> item,
base::flat_map<not_null<HistoryItem*>, std::vector<Animation>> &map) { base::flat_map<not_null<HistoryItem*>, std::vector<Animation>> &map) {
const auto &pack = _session->emojiStickersPack();
const auto i = map.find(item); const auto i = map.find(item);
if (i != end(map) if (i != end(map)
&& (i->second.front().emoji != chooseInteractionEmoji(item))) { && (i->second.front().emoji != pack.chooseInteractionEmoji(item))) {
map.erase(i); map.erase(i);
} }
} }
EmojiPtr EmojiInteractions::chooseInteractionEmoji(
not_null<HistoryItem*> item) const {
return chooseInteractionEmoji(item->originalText().text);
}
EmojiPtr EmojiInteractions::chooseInteractionEmoji(
const QString &emoticon) const {
const auto emoji = Ui::Emoji::Find(emoticon);
if (!emoji) {
return nullptr;
}
const auto &pack = _session->emojiStickersPack();
if (!pack.animationsForEmoji(emoji).empty()) {
return emoji;
}
if (const auto original = emoji->original(); original != emoji) {
if (!pack.animationsForEmoji(original).empty()) {
return original;
}
}
static const auto kHearts = {
QString::fromUtf8("\xf0\x9f\x92\x9b"),
QString::fromUtf8("\xf0\x9f\x92\x99"),
QString::fromUtf8("\xf0\x9f\x92\x9a"),
QString::fromUtf8("\xf0\x9f\x92\x9c"),
QString::fromUtf8("\xf0\x9f\xa7\xa1"),
QString::fromUtf8("\xf0\x9f\x96\xa4"),
QString::fromUtf8("\xf0\x9f\xa4\x8e"),
QString::fromUtf8("\xf0\x9f\xa4\x8d"),
};
return ranges::contains(kHearts, emoji->id())
? Ui::Emoji::Find(QString::fromUtf8("\xe2\x9d\xa4"))
: emoji;
}
void EmojiInteractions::startOutgoing( void EmojiInteractions::startOutgoing(
not_null<const HistoryView::Element*> view) { not_null<const HistoryView::Element*> view) {
const auto item = view->data(); const auto item = view->data();
if (!item->isRegular() || !item->history()->peer->isUser()) { if (!item->isRegular() || !item->history()->peer->isUser()) {
return; return;
} }
const auto &pack = _session->emojiStickersPack();
const auto emoticon = item->originalText().text; const auto emoticon = item->originalText().text;
const auto emoji = chooseInteractionEmoji(emoticon); const auto emoji = pack.chooseInteractionEmoji(emoticon);
if (!emoji) { if (!emoji) {
return; return;
} }
const auto &pack = _session->emojiStickersPack();
const auto &list = pack.animationsForEmoji(emoji); const auto &list = pack.animationsForEmoji(emoji);
if (list.empty()) { if (list.empty()) {
return; return;
@ -168,11 +134,11 @@ void EmojiInteractions::startIncoming(
if (!item || !item->isRegular()) { if (!item || !item->isRegular()) {
return; return;
} }
const auto emoji = chooseInteractionEmoji(item); const auto &pack = _session->emojiStickersPack();
if (!emoji || emoji != chooseInteractionEmoji(emoticon)) { const auto emoji = pack.chooseInteractionEmoji(item);
if (!emoji || emoji != pack.chooseInteractionEmoji(emoticon)) {
return; return;
} }
const auto &pack = _session->emojiStickersPack();
const auto &list = pack.animationsForEmoji(emoji); const auto &list = pack.animationsForEmoji(emoji);
if (list.empty()) { if (list.empty()) {
return; return;
@ -215,8 +181,9 @@ void EmojiInteractions::startIncoming(
void EmojiInteractions::seenOutgoing( void EmojiInteractions::seenOutgoing(
not_null<PeerData*> peer, not_null<PeerData*> peer,
const QString &emoticon) { const QString &emoticon) {
const auto &pack = _session->emojiStickersPack();
if (const auto i = _playsSent.find(peer); i != end(_playsSent)) { if (const auto i = _playsSent.find(peer); i != end(_playsSent)) {
if (const auto emoji = chooseInteractionEmoji(emoticon)) { if (const auto emoji = pack.chooseInteractionEmoji(emoticon)) {
if (const auto j = i->second.find(emoji); j != end(i->second)) { if (const auto j = i->second.find(emoji); j != end(i->second)) {
const auto last = j->second.lastDoneReceivedAt; const auto last = j->second.lastDoneReceivedAt;
if (!last || last + kAcceptSeenSinceRequest > crl::now()) { if (!last || last + kAcceptSeenSinceRequest > crl::now()) {

View file

@ -97,11 +97,6 @@ private:
}; };
[[nodiscard]] static CheckResult Combine(CheckResult a, CheckResult b); [[nodiscard]] static CheckResult Combine(CheckResult a, CheckResult b);
[[nodiscard]] EmojiPtr chooseInteractionEmoji(
not_null<HistoryItem*> item) const;
[[nodiscard]] EmojiPtr chooseInteractionEmoji(
const QString &emoticon) const;
void check(crl::time now = 0); void check(crl::time now = 0);
[[nodiscard]] CheckResult checkAnimations(crl::time now); [[nodiscard]] CheckResult checkAnimations(crl::time now);
[[nodiscard]] CheckResult checkAnimations( [[nodiscard]] CheckResult checkAnimations(

View file

@ -214,13 +214,58 @@ std::shared_ptr<LargeEmojiImage> EmojiPack::image(EmojiPtr emoji) {
return result; return result;
} }
EmojiPtr EmojiPack::chooseInteractionEmoji(
not_null<HistoryItem*> item) const {
return chooseInteractionEmoji(item->originalText().text);
}
EmojiPtr EmojiPack::chooseInteractionEmoji(
const QString &emoticon) const {
const auto emoji = Ui::Emoji::Find(emoticon);
if (!emoji) {
return nullptr;
}
if (!animationsForEmoji(emoji).empty()) {
return emoji;
}
if (const auto original = emoji->original(); original != emoji) {
if (!animationsForEmoji(original).empty()) {
return original;
}
}
static const auto kHearts = {
QString::fromUtf8("\xf0\x9f\x92\x9b"),
QString::fromUtf8("\xf0\x9f\x92\x99"),
QString::fromUtf8("\xf0\x9f\x92\x9a"),
QString::fromUtf8("\xf0\x9f\x92\x9c"),
QString::fromUtf8("\xf0\x9f\xa7\xa1"),
QString::fromUtf8("\xf0\x9f\x96\xa4"),
QString::fromUtf8("\xf0\x9f\xa4\x8e"),
QString::fromUtf8("\xf0\x9f\xa4\x8d"),
};
return ranges::contains(kHearts, emoji->id())
? Ui::Emoji::Find(QString::fromUtf8("\xe2\x9d\xa4"))
: emoji;
}
auto EmojiPack::animationsForEmoji(EmojiPtr emoji) const auto EmojiPack::animationsForEmoji(EmojiPtr emoji) const
-> const base::flat_map<int, not_null<DocumentData*>> & { -> const base::flat_map<int, not_null<DocumentData*>> & {
static const auto empty = base::flat_map<int, not_null<DocumentData*>>(); static const auto empty = base::flat_map<int, not_null<DocumentData*>>();
if (!emoji) {
return empty;
}
const auto i = _animations.find(emoji); const auto i = _animations.find(emoji);
return (i != end(_animations)) ? i->second : empty; return (i != end(_animations)) ? i->second : empty;
} }
bool EmojiPack::hasAnimationsFor(not_null<HistoryItem*> item) const {
return !animationsForEmoji(chooseInteractionEmoji(item)).empty();
}
bool EmojiPack::hasAnimationsFor(const QString &emoticon) const {
return !animationsForEmoji(chooseInteractionEmoji(emoticon)).empty();
}
std::unique_ptr<Lottie::SinglePlayer> EmojiPack::effectPlayer( std::unique_ptr<Lottie::SinglePlayer> EmojiPack::effectPlayer(
not_null<DocumentData*> document, not_null<DocumentData*> document,
QByteArray data, QByteArray data,
@ -371,6 +416,7 @@ void EmojiPack::applyAnimationsSet(const MTPDmessages_stickerSet &data) {
} }
}); });
} }
++_animationsVersion;
} }
auto EmojiPack::collectAnimationsIndices( auto EmojiPack::collectAnimationsIndices(

View file

@ -70,8 +70,17 @@ public:
[[nodiscard]] Sticker stickerForEmoji(const IsolatedEmoji &emoji); [[nodiscard]] Sticker stickerForEmoji(const IsolatedEmoji &emoji);
[[nodiscard]] std::shared_ptr<LargeEmojiImage> image(EmojiPtr emoji); [[nodiscard]] std::shared_ptr<LargeEmojiImage> image(EmojiPtr emoji);
[[nodiscard]] EmojiPtr chooseInteractionEmoji(
not_null<HistoryItem*> item) const;
[[nodiscard]] EmojiPtr chooseInteractionEmoji(
const QString &emoticon) const;
[[nodiscard]] auto animationsForEmoji(EmojiPtr emoji) const [[nodiscard]] auto animationsForEmoji(EmojiPtr emoji) const
-> const base::flat_map<int, not_null<DocumentData*>> &; -> const base::flat_map<int, not_null<DocumentData*>> &;
[[nodiscard]] bool hasAnimationsFor(not_null<HistoryItem*> item) const;
[[nodiscard]] bool hasAnimationsFor(const QString &emoticon) const;
[[nodiscard]] int animationsVersion() const {
return _animationsVersion;
}
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> effectPlayer( [[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> effectPlayer(
not_null<DocumentData*> document, not_null<DocumentData*> document,
@ -109,6 +118,7 @@ private:
base::flat_set<not_null<HistoryItem*>> _onlyCustomItems; base::flat_set<not_null<HistoryItem*>> _onlyCustomItems;
int _animationsVersion = 0;
base::flat_map< base::flat_map<
EmojiPtr, EmojiPtr,
base::flat_map<int, not_null<DocumentData*>>> _animations; base::flat_map<int, not_null<DocumentData*>>> _animations;

View file

@ -3106,7 +3106,7 @@ auto HistoryInner::prevItem(Element *view) -> Element* {
return nullptr; return nullptr;
} else if (const auto result = view->previousDisplayedInBlocks()) { } else if (const auto result = view->previousDisplayedInBlocks()) {
return result; return result;
} else if (view->data()->history() == _history } else if (view->history() == _history
&& _migrated && _migrated
&& _history->loadedAtTop() && _history->loadedAtTop()
&& !_migrated->isEmpty() && !_migrated->isEmpty()
@ -3121,7 +3121,7 @@ auto HistoryInner::nextItem(Element *view) -> Element* {
return nullptr; return nullptr;
} else if (const auto result = view->nextDisplayedInBlocks()) { } else if (const auto result = view->nextDisplayedInBlocks()) {
return result; return result;
} else if (view->data()->history() == _migrated } else if (view->history() == _migrated
&& _migrated->loadedAtBottom() && _migrated->loadedAtBottom()
&& _history->loadedAtTop() && _history->loadedAtTop()
&& !_history->isEmpty()) { && !_history->isEmpty()) {
@ -3730,9 +3730,9 @@ int HistoryInner::itemTop(const Element *view) const {
return -1; return -1;
} }
auto top = (view->data()->history() == _history) auto top = (view->history() == _history)
? historyTop() ? historyTop()
: (view->data()->history() == _migrated : (view->history() == _migrated
? migratedTop() ? migratedTop()
: -2); : -2);
return (top < 0) ? top : (top + view->y() + view->block()->y()); return (top < 0) ? top : (top + view->y() + view->block()->y());
@ -4020,8 +4020,8 @@ void HistoryInner::applyDragSelection(
auto toblock = _dragSelTo->block()->indexInHistory(); auto toblock = _dragSelTo->block()->indexInHistory();
auto toitem = _dragSelTo->indexInBlock(); auto toitem = _dragSelTo->indexInBlock();
if (_migrated) { if (_migrated) {
if (_dragSelFrom->data()->history() == _migrated) { if (_dragSelFrom->history() == _migrated) {
if (_dragSelTo->data()->history() == _migrated) { if (_dragSelTo->history() == _migrated) {
addSelectionRange(toItems, _migrated, fromblock, fromitem, toblock, toitem); addSelectionRange(toItems, _migrated, fromblock, fromitem, toblock, toitem);
toblock = -1; toblock = -1;
toitem = -1; toitem = -1;
@ -4030,7 +4030,7 @@ void HistoryInner::applyDragSelection(
} }
fromblock = 0; fromblock = 0;
fromitem = 0; fromitem = 0;
} else if (_dragSelTo->data()->history() == _migrated) { // wtf } else if (_dragSelTo->history() == _migrated) { // wtf
toblock = -1; toblock = -1;
toitem = -1; toitem = -1;
} }

View file

@ -6319,7 +6319,7 @@ void HistoryWidget::updatePinnedViewer() {
auto [view, offset] = _list->findViewForPinnedTracking(visibleBottom); auto [view, offset] = _list->findViewForPinnedTracking(visibleBottom);
const auto lessThanId = !view const auto lessThanId = !view
? (ServerMaxMsgId - 1) ? (ServerMaxMsgId - 1)
: (view->data()->history() != _history) : (view->history() != _history)
? (view->data()->id + (offset > 0 ? 1 : 0) - ServerMaxMsgId) ? (view->data()->id + (offset > 0 ? 1 : 0) - ServerMaxMsgId)
: (view->data()->id + (offset > 0 ? 1 : 0)); : (view->data()->id + (offset > 0 ? 1 : 0));
const auto lastClickedId = !_pinnedClickedId const auto lastClickedId = !_pinnedClickedId

View file

@ -976,7 +976,7 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
const auto context = list->elementContext(); const auto context = list->elementContext();
AddPollActions(result, poll, item, context, list->controller()); AddPollActions(result, poll, item, context, list->controller());
} else if (!request.overSelection && view && !hasSelection) { } else if (!request.overSelection && view && !hasSelection) {
const auto owner = &view->data()->history()->owner(); const auto owner = &view->history()->owner();
const auto media = view->media(); const auto media = view->media();
const auto mediaHasTextForCopy = media && media->hasTextForCopy(); const auto mediaHasTextForCopy = media && media->hasTextForCopy();
if (const auto document = media ? media->getDocument() : nullptr) { if (const auto document = media ? media->getDocument() : nullptr) {

View file

@ -579,9 +579,7 @@ void Element::refreshMedia(Element *replacing) {
&& Core::App().settings().largeEmoji()) { && Core::App().settings().largeEmoji()) {
_media = std::make_unique<UnwrappedMedia>( _media = std::make_unique<UnwrappedMedia>(
this, this,
std::make_unique<CustomEmoji>( std::make_unique<CustomEmoji>(this, _data->onlyCustomEmoji()));
this,
_data->onlyCustomEmoji()));
} else if (_data->isIsolatedEmoji() } else if (_data->isIsolatedEmoji()
&& Core::App().settings().largeEmoji()) { && Core::App().settings().largeEmoji()) {
const auto emoji = _data->isolatedEmoji(); const auto emoji = _data->isolatedEmoji();

View file

@ -57,7 +57,7 @@ Call::Call(
} }
QSize Call::countOptimalSize() { QSize Call::countOptimalSize() {
const auto user = _parent->data()->history()->peer->asUser(); const auto user = _parent->history()->peer->asUser();
const auto video = _video; const auto video = _video;
_link = std::make_shared<LambdaClickHandler>([=] { _link = std::make_shared<LambdaClickHandler>([=] {
if (user) { if (user) {

View file

@ -14,6 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_custom_emoji.h"
#include "main/main_session.h"
#include "chat_helpers/stickers_emoji_pack.h"
#include "chat_helpers/stickers_lottie.h" #include "chat_helpers/stickers_lottie.h"
#include "ui/chat/chat_style.h" #include "ui/chat/chat_style.h"
#include "ui/text/text_isolated_emoji.h" #include "ui/text/text_isolated_emoji.h"
@ -33,7 +35,7 @@ struct CustomEmojiSizeInfo {
}; };
[[nodiscard]] const base::flat_map<int, CustomEmojiSizeInfo> &SizesInfo() { [[nodiscard]] const base::flat_map<int, CustomEmojiSizeInfo> &SizesInfo() {
// size = i->second.scale * st::maxAnimatedEmojiSize. // size = i->second.scale * Sticker::EmojiSize().width()
// CustomEmojiManager::SizeTag caching uses first ::EmojiInteraction-s. // CustomEmojiManager::SizeTag caching uses first ::EmojiInteraction-s.
using Info = CustomEmojiSizeInfo; using Info = CustomEmojiSizeInfo;
static auto result = base::flat_map<int, Info>{ static auto result = base::flat_map<int, Info>{
@ -64,7 +66,7 @@ CustomEmoji::CustomEmoji(
: _parent(parent) { : _parent(parent) {
Expects(!emoji.lines.empty()); Expects(!emoji.lines.empty());
const auto owner = &parent->data()->history()->owner(); const auto owner = &parent->history()->owner();
const auto manager = &owner->customEmojiManager(); const auto manager = &owner->customEmojiManager();
const auto max = ranges::max_element( const auto max = ranges::max_element(
emoji.lines, emoji.lines,
@ -76,7 +78,8 @@ CustomEmoji::CustomEmoji(
const auto useCustomEmoji = (i == end(sizes)); const auto useCustomEmoji = (i == end(sizes));
const auto tag = EmojiSize(dimension); const auto tag = EmojiSize(dimension);
_singleSize = !useCustomEmoji _singleSize = !useCustomEmoji
? int(base::SafeRound(i->second.scale * st::maxAnimatedEmojiSize)) ? int(base::SafeRound(
i->second.scale * Sticker::EmojiSize().width()))
: Data::FrameSizeFromTag(tag); : Data::FrameSizeFromTag(tag);
if (!useCustomEmoji) { if (!useCustomEmoji) {
_cachingTag = i->second.tag; _cachingTag = i->second.tag;
@ -95,13 +98,7 @@ CustomEmoji::CustomEmoji(
const auto id = Data::ParseCustomEmojiData(data).id; const auto id = Data::ParseCustomEmojiData(data).id;
const auto document = owner->document(id); const auto document = owner->document(id);
if (document->sticker()) { if (document->sticker()) {
const auto skipPremiumEffect = false; _lines.back().push_back(createStickerPart(document));
auto sticker = std::make_unique<Sticker>(
parent,
document,
skipPremiumEffect);
sticker->setCustomEmojiPart(_singleSize, _cachingTag);
_lines.back().push_back(std::move(sticker));
} else { } else {
_lines.back().push_back(id); _lines.back().push_back(id);
manager->resolve(id, listener()); manager->resolve(id, listener());
@ -118,13 +115,7 @@ void CustomEmoji::customEmojiResolveDone(not_null<DocumentData*> document) {
for (auto &line : _lines) { for (auto &line : _lines) {
for (auto &entry : line) { for (auto &entry : line) {
if (entry == id) { if (entry == id) {
const auto skipPremiumEffect = false; entry = createStickerPart(document);
auto sticker = std::make_unique<Sticker>(
_parent,
document,
skipPremiumEffect);
sticker->setCustomEmojiPart(_singleSize, _cachingTag);
entry = std::move(sticker);
} else if (v::is<DocumentId>(entry)) { } else if (v::is<DocumentId>(entry)) {
_resolving = true; _resolving = true;
} }
@ -132,13 +123,60 @@ void CustomEmoji::customEmojiResolveDone(not_null<DocumentData*> document) {
} }
} }
std::unique_ptr<Sticker> CustomEmoji::createStickerPart(
not_null<DocumentData*> document) const {
const auto skipPremiumEffect = false;
auto result = std::make_unique<Sticker>(
_parent,
document,
skipPremiumEffect);
result->setCustomEmojiPart(_singleSize, _cachingTag);
return result;
}
void CustomEmoji::refreshInteractionLink() {
if (_lines.size() != 1 || _lines.front().size() != 1) {
return;
}
const auto &pack = _parent->history()->session().emojiStickersPack();
const auto version = pack.animationsVersion();
if (_animationsCheckVersion == version) {
return;
}
_animationsCheckVersion = version;
if (pack.hasAnimationsFor(_parent->data())) {
const auto weak = base::make_weak(this);
_interactionLink = std::make_shared<LambdaClickHandler>([weak] {
if (const auto that = weak.get()) {
that->interactionLinkClicked();
}
});
} else {
_interactionLink = nullptr;
}
}
ClickHandlerPtr CustomEmoji::link() {
refreshInteractionLink();
return _interactionLink;
}
void CustomEmoji::interactionLinkClicked() {
const auto &entry = _lines.front().front();
if (const auto sticker = std::get_if<StickerPtr>(&entry)) {
if ((*sticker)->ready()) {
_parent->delegate()->elementStartInteraction(_parent);
}
}
}
CustomEmoji::~CustomEmoji() { CustomEmoji::~CustomEmoji() {
if (_hasHeavyPart) { if (_hasHeavyPart) {
unloadHeavyPart(); unloadHeavyPart();
_parent->checkHeavyPart(); _parent->checkHeavyPart();
} }
if (_resolving) { if (_resolving) {
const auto owner = &_parent->data()->history()->owner(); const auto owner = &_parent->history()->owner();
owner->customEmojiManager().unregisterListener(listener()); owner->customEmojiManager().unregisterListener(listener());
} }
} }

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/media/history_view_media_unwrapped.h" #include "history/view/media/history_view_media_unwrapped.h"
#include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_custom_emoji.h"
#include "base/weak_ptr.h"
namespace Ui::Text { namespace Ui::Text {
struct OnlyCustomEmoji; struct OnlyCustomEmoji;
@ -33,6 +34,7 @@ using LargeCustomEmoji = std::variant<
class CustomEmoji final class CustomEmoji final
: public UnwrappedMedia::Content : public UnwrappedMedia::Content
, public base::has_weak_ptr
, private Data::CustomEmojiManager::Listener { , private Data::CustomEmojiManager::Listener {
public: public:
CustomEmoji( CustomEmoji(
@ -46,6 +48,7 @@ public:
Painter &p, Painter &p,
const PaintContext &context, const PaintContext &context,
const QRect &r) override; const QRect &r) override;
ClickHandlerPtr link() override;
bool alwaysShowOutTimestamp() override { bool alwaysShowOutTimestamp() override {
return true; return true;
@ -58,9 +61,6 @@ public:
void unloadHeavyPart() override; void unloadHeavyPart() override;
private: private:
[[nodiscard]] not_null<Data::CustomEmojiManager::Listener*> listener() {
return this;
}
void paintElement( void paintElement(
Painter &p, Painter &p,
int x, int x,
@ -83,12 +83,23 @@ private:
const PaintContext &context, const PaintContext &context,
bool paused); bool paused);
[[nodiscard]] not_null<Data::CustomEmojiManager::Listener*> listener() {
return this;
}
void customEmojiResolveDone(not_null<DocumentData*> document) override; void customEmojiResolveDone(not_null<DocumentData*> document) override;
[[nodiscard]] std::unique_ptr<Sticker> createStickerPart(
not_null<DocumentData*> document) const;
void refreshInteractionLink();
void interactionLinkClicked();
const not_null<Element*> _parent; const not_null<Element*> _parent;
std::vector<std::vector<LargeCustomEmoji>> _lines; std::vector<std::vector<LargeCustomEmoji>> _lines;
ClickHandlerPtr _interactionLink;
QImage _selectedFrame; QImage _selectedFrame;
int _singleSize = 0; int _singleSize = 0;
int _animationsCheckVersion = -1;
ChatHelpers::StickerLottieSize _cachingTag = {}; ChatHelpers::StickerLottieSize _cachingTag = {};
bool _hasHeavyPart = false; bool _hasHeavyPart = false;
bool _resolving = false; bool _resolving = false;

View file

@ -23,7 +23,7 @@ namespace {
not_null<Element*> view, not_null<Element*> view,
const QString &emoji, const QString &emoji,
int value) { int value) {
const auto &session = view->data()->history()->session(); const auto &session = view->history()->session();
return session.diceStickersPacks().lookup(emoji, value); return session.diceStickersPacks().lookup(emoji, value);
} }

View file

@ -56,7 +56,7 @@ LargeEmoji::LargeEmoji(
const Ui::Text::IsolatedEmoji &emoji) const Ui::Text::IsolatedEmoji &emoji)
: _parent(parent) : _parent(parent)
, _images(ResolveImages( , _images(ResolveImages(
&parent->data()->history()->session(), &parent->history()->session(),
[=] { parent->customEmojiRepaint(); }, [=] { parent->customEmojiRepaint(); },
emoji)) { emoji)) {
} }

View file

@ -67,7 +67,7 @@ MediaGift::MediaGift(
height); height);
const auto from = _gift->from(); const auto from = _gift->from();
const auto to = _parent->data()->history()->peer; const auto to = _parent->history()->peer;
const auto months = _gift->months(); const auto months = _gift->months();
result.link = std::make_shared<LambdaClickHandler>([=]( result.link = std::make_shared<LambdaClickHandler>([=](
ClickContext context) { ClickContext context) {
@ -225,7 +225,7 @@ void MediaGift::ensureStickerCreated() const {
if (_sticker) { if (_sticker) {
return; return;
} }
const auto &session = _parent->data()->history()->session(); const auto &session = _parent->history()->session();
auto &packs = session.giftBoxStickersPacks(); auto &packs = session.giftBoxStickersPacks();
if (const auto document = packs.lookup(_gift->months())) { if (const auto document = packs.lookup(_gift->months())) {
if (const auto sticker = document->sticker()) { if (const auto sticker = document->sticker()) {

View file

@ -37,7 +37,7 @@ const auto &kEmoji = ::Stickers::DicePacks::kSlotString;
[[nodiscard]] DocumentData *Lookup( [[nodiscard]] DocumentData *Lookup(
not_null<Element*> view, not_null<Element*> view,
int value) { int value) {
const auto &session = view->data()->history()->session(); const auto &session = view->history()->session();
return session.diceStickersPacks().lookup(kEmoji, value); return session.diceStickersPacks().lookup(kEmoji, value);
} }

View file

@ -310,7 +310,7 @@ bool Sticker::readyToDrawAnimationFrame() {
if (!_player && loaded && !waitingForPremium && sticker->isAnimated()) { if (!_player && loaded && !waitingForPremium && sticker->isAnimated()) {
setupPlayer(); setupPlayer();
} }
return (_player && _player->ready()); return ready();
} }
QSize Sticker::Size() { QSize Sticker::Size() {
@ -362,6 +362,10 @@ ClickHandlerPtr Sticker::link() {
return _link; return _link;
} }
bool Sticker::ready() const {
return _player && _player->ready();
}
DocumentData *Sticker::document() { DocumentData *Sticker::document() {
return _data; return _data;
} }

View file

@ -70,6 +70,7 @@ public:
const QRect &r) override; const QRect &r) override;
ClickHandlerPtr link() override; ClickHandlerPtr link() override;
[[nodiscard]] bool ready() const;
DocumentData *document() override; DocumentData *document() override;
void stickerClearLoopPlayed() override; void stickerClearLoopPlayed() override;
std::unique_ptr<StickerPlayer> stickerTakePlayer( std::unique_ptr<StickerPlayer> stickerTakePlayer(

View file

@ -218,7 +218,7 @@ struct ForwardedTooltip {
const auto phrase = tr::lng_forwarded( const auto phrase = tr::lng_forwarded(
tr::now, tr::now,
lt_user, lt_user,
view->data()->history()->session().user()->name); view->history()->session().user()->name);
const auto kReplacementPosition = QChar(0x0001); const auto kReplacementPosition = QChar(0x0001);
const auto possiblePosition = tr::lng_forwarded( const auto possiblePosition = tr::lng_forwarded(
tr::now, tr::now,