Load and reload interaction stickers.

This commit is contained in:
John Preston 2021-09-14 19:55:35 +03:00
parent 35356a1736
commit d152782115
16 changed files with 130 additions and 41 deletions

View File

@ -30,6 +30,18 @@ namespace {
constexpr auto kRefreshTimeout = 7200 * crl::time(1000); constexpr auto kRefreshTimeout = 7200 * crl::time(1000);
[[nodiscard]] std::optional<int> IndexFromEmoticon(const QString &emoticon) {
if (emoticon.size() < 2) {
return -1;
}
const auto first = emoticon[0].unicode();
return (first >= '1' && first <= '9')
? (first - '1')
: (first == 55357 && emoticon[1].unicode() == 56607)
? 9
: -1;
}
[[nodiscard]] QSize SingleSize() { [[nodiscard]] QSize SingleSize() {
const auto single = st::largeEmojiSize; const auto single = st::largeEmojiSize;
const auto outline = st::largeEmojiOutline; const auto outline = st::largeEmojiOutline;
@ -207,6 +219,13 @@ std::shared_ptr<LargeEmojiImage> EmojiPack::image(EmojiPtr emoji) {
return result; return result;
} }
auto EmojiPack::animationsForEmoji(EmojiPtr emoji) const
-> const base::flat_map<int, not_null<DocumentData*>> & {
static const auto empty = base::flat_map<int, not_null<DocumentData*>>();
const auto i = _animations.find(emoji);
return (i != end(_animations)) ? i->second : empty;
}
void EmojiPack::refresh() { void EmojiPack::refresh() {
if (_requestId) { if (_requestId) {
return; return;
@ -215,7 +234,7 @@ void EmojiPack::refresh() {
MTP_inputStickerSetAnimatedEmoji() MTP_inputStickerSetAnimatedEmoji()
)).done([=](const MTPmessages_StickerSet &result) { )).done([=](const MTPmessages_StickerSet &result) {
_requestId = 0; _requestId = 0;
refreshDelayed(); refreshAnimations();
result.match([&](const MTPDmessages_stickerSet &data) { result.match([&](const MTPDmessages_stickerSet &data) {
applySet(data); applySet(data);
}); });
@ -225,6 +244,24 @@ void EmojiPack::refresh() {
}).send(); }).send();
} }
void EmojiPack::refreshAnimations() {
if (_animationsRequestId) {
return;
}
_animationsRequestId = _session->api().request(MTPmessages_GetStickerSet(
MTP_inputStickerSetAnimatedEmojiAnimations()
)).done([=](const MTPmessages_StickerSet &result) {
_animationsRequestId = 0;
refreshDelayed();
result.match([&](const MTPDmessages_stickerSet &data) {
applyAnimationsSet(data);
});
}).fail([=](const MTP::Error &error) {
_animationsRequestId = 0;
refreshDelayed();
}).send();
}
void EmojiPack::applySet(const MTPDmessages_stickerSet &data) { void EmojiPack::applySet(const MTPDmessages_stickerSet &data) {
const auto stickers = collectStickers(data.vdocuments().v); const auto stickers = collectStickers(data.vdocuments().v);
auto was = base::take(_map); auto was = base::take(_map);
@ -251,6 +288,55 @@ void EmojiPack::applySet(const MTPDmessages_stickerSet &data) {
} }
} }
void EmojiPack::applyAnimationsSet(const MTPDmessages_stickerSet &data) {
const auto stickers = collectStickers(data.vdocuments().v);
const auto &packs = data.vpacks().v;
const auto indices = collectAnimationsIndices(packs);
_animations.clear();
for (const auto &pack : packs) {
pack.match([&](const MTPDstickerPack &data) {
const auto emoticon = qs(data.vemoticon());
if (IndexFromEmoticon(emoticon).has_value()) {
return;
}
const auto emoji = Ui::Emoji::Find(emoticon);
if (!emoji) {
return;
}
for (const auto &id : data.vdocuments().v) {
const auto i = indices.find(id.v);
if (i == end(indices)) {
continue;
}
const auto j = stickers.find(id.v);
if (j == end(stickers)) {
continue;
}
for (const auto index : i->second) {
_animations[emoji].emplace(index, j->second);
}
}
});
}
}
auto EmojiPack::collectAnimationsIndices(
const QVector<MTPStickerPack> &packs
) const -> base::flat_map<uint64, base::flat_set<int>> {
auto result = base::flat_map<uint64, base::flat_set<int>>();
for (const auto &pack : packs) {
pack.match([&](const MTPDstickerPack &data) {
if (const auto index = IndexFromEmoticon(qs(data.vemoticon()))) {
for (const auto &id : data.vdocuments().v) {
result[id.v].emplace(*index);
}
}
});
}
return result;
}
void EmojiPack::refreshAll() { void EmojiPack::refreshAll() {
for (const auto &[emoji, list] : _items) { for (const auto &[emoji, list] : _items) {
refreshItems(list); refreshItems(list);

View File

@ -67,17 +67,25 @@ 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]] auto animationsForEmoji(EmojiPtr emoji) const
-> const base::flat_map<int, not_null<DocumentData*>> &;
private: private:
class ImageLoader; class ImageLoader;
void refresh(); void refresh();
void refreshDelayed(); void refreshDelayed();
void refreshAnimations();
void applySet(const MTPDmessages_stickerSet &data); void applySet(const MTPDmessages_stickerSet &data);
void applyPack( void applyPack(
const MTPDstickerPack &data, const MTPDstickerPack &data,
const base::flat_map<uint64, not_null<DocumentData*>> &map); const base::flat_map<uint64, not_null<DocumentData*>> &map);
base::flat_map<uint64, not_null<DocumentData*>> collectStickers( void applyAnimationsSet(const MTPDmessages_stickerSet &data);
const QVector<MTPDocument> &list) const; [[nodiscard]] auto collectStickers(const QVector<MTPDocument> &list) const
-> base::flat_map<uint64, not_null<DocumentData*>>;
[[nodiscard]] auto collectAnimationsIndices(
const QVector<MTPStickerPack> &packs) const
-> base::flat_map<uint64, base::flat_set<int>>;
void refreshAll(); void refreshAll();
void refreshItems(EmojiPtr emoji); void refreshItems(EmojiPtr emoji);
void refreshItems(const base::flat_set<not_null<HistoryItem*>> &list); void refreshItems(const base::flat_set<not_null<HistoryItem*>> &list);
@ -90,6 +98,11 @@ private:
base::flat_map<EmojiPtr, std::weak_ptr<LargeEmojiImage>> _images; base::flat_map<EmojiPtr, std::weak_ptr<LargeEmojiImage>> _images;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
base::flat_map<
EmojiPtr,
base::flat_map<int, not_null<DocumentData*>>> _animations;
mtpRequestId _animationsRequestId = 0;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;
}; };

View File

@ -674,6 +674,9 @@ not_null<Ui::PathShiftGradient*> InnerWidget::elementPathShiftGradient() {
void InnerWidget::elementReplyTo(const FullMsgId &to) { void InnerWidget::elementReplyTo(const FullMsgId &to) {
} }
void InnerWidget::elementStartInteraction(not_null<const Element*> view) {
}
void InnerWidget::saveState(not_null<SectionMemento*> memento) { void InnerWidget::saveState(not_null<SectionMemento*> memento) {
memento->setFilter(std::move(_filter)); memento->setFilter(std::move(_filter));
memento->setAdmins(std::move(_admins)); memento->setAdmins(std::move(_admins));

View File

@ -137,6 +137,8 @@ public:
bool elementIsChatWide() override; bool elementIsChatWide() override;
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override; not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override;
void elementReplyTo(const FullMsgId &to) override; void elementReplyTo(const FullMsgId &to) override;
void elementStartInteraction(
not_null<const HistoryView::Element*> view) override;
~InnerWidget(); ~InnerWidget();

View File

@ -2689,6 +2689,9 @@ void HistoryInner::elementReplyTo(const FullMsgId &to) {
return _widget->replyToMessage(to); return _widget->replyToMessage(to);
} }
void HistoryInner::elementStartInteraction(not_null<const Element*> view) {
}
auto HistoryInner::getSelectionState() const auto HistoryInner::getSelectionState() const
-> HistoryView::TopBarWidget::SelectedState { -> HistoryView::TopBarWidget::SelectedState {
auto result = HistoryView::TopBarWidget::SelectedState {}; auto result = HistoryView::TopBarWidget::SelectedState {};
@ -3601,6 +3604,11 @@ not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() {
Instance->elementReplyTo(to); Instance->elementReplyTo(to);
} }
} }
void elementStartInteraction(not_null<const Element*> view) override {
if (Instance) {
Instance->elementStartInteraction(view);
}
}
}; };
static Result result; static Result result;

View File

@ -115,6 +115,7 @@ public:
bool elementIsChatWide(); bool elementIsChatWide();
not_null<Ui::PathShiftGradient*> elementPathShiftGradient(); not_null<Ui::PathShiftGradient*> elementPathShiftGradient();
void elementReplyTo(const FullMsgId &to); void elementReplyTo(const FullMsgId &to);
void elementStartInteraction(not_null<const Element*> view);
void updateBotInfo(bool recount = true); void updateBotInfo(bool recount = true);

View File

@ -177,6 +177,11 @@ auto SimpleElementDelegate::elementPathShiftGradient()
void SimpleElementDelegate::elementReplyTo(const FullMsgId &to) { void SimpleElementDelegate::elementReplyTo(const FullMsgId &to) {
} }
void SimpleElementDelegate::elementStartInteraction(
not_null<const Element*> view) {
}
TextSelection UnshiftItemSelection( TextSelection UnshiftItemSelection(
TextSelection selection, TextSelection selection,
uint16 byLength) { uint16 byLength) {
@ -219,24 +224,6 @@ QString DateTooltipText(not_null<Element*> view) {
tr::now, tr::now,
lt_date, lt_date,
base::unixtime::parse(forwarded->originalDate).toString(format)); base::unixtime::parse(forwarded->originalDate).toString(format));
if (const auto media = view->media()) {
if (media->hidesForwardedInfo()) {
const auto from = forwarded->originalSender
? forwarded->originalSender->shortName()
: forwarded->hiddenSenderInfo->firstName;
if (forwarded->imported) {
dateText += '\n' + tr::lng_signed_author(
tr::now,
lt_user,
from);
} else {
dateText += '\n' + tr::lng_forwarded(
tr::now,
lt_user,
from);
}
}
}
if (forwarded->imported) { if (forwarded->imported) {
dateText = tr::lng_forwarded_imported(tr::now) dateText = tr::lng_forwarded_imported(tr::now)
+ "\n\n" + dateText; + "\n\n" + dateText;

View File

@ -90,6 +90,7 @@ public:
virtual bool elementIsChatWide() = 0; virtual bool elementIsChatWide() = 0;
virtual not_null<Ui::PathShiftGradient*> elementPathShiftGradient() = 0; virtual not_null<Ui::PathShiftGradient*> elementPathShiftGradient() = 0;
virtual void elementReplyTo(const FullMsgId &to) = 0; virtual void elementReplyTo(const FullMsgId &to) = 0;
virtual void elementStartInteraction(not_null<const Element*> view) = 0;
virtual ~ElementDelegate() { virtual ~ElementDelegate() {
} }
@ -146,6 +147,7 @@ public:
bool elementIsChatWide() override; bool elementIsChatWide() override;
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override; not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override;
void elementReplyTo(const FullMsgId &to) override; void elementReplyTo(const FullMsgId &to) override;
void elementStartInteraction(not_null<const Element*> view) override;
protected: protected:
[[nodiscard]] not_null<Window::SessionController*> controller() const { [[nodiscard]] not_null<Window::SessionController*> controller() const {

View File

@ -1391,6 +1391,9 @@ void ListWidget::elementReplyTo(const FullMsgId &to) {
replyToMessageRequestNotify(to); replyToMessageRequestNotify(to);
} }
void ListWidget::elementStartInteraction(not_null<const Element*> view) {
}
void ListWidget::saveState(not_null<ListMemento*> memento) { void ListWidget::saveState(not_null<ListMemento*> memento) {
memento->setAroundPosition(_aroundPosition); memento->setAroundPosition(_aroundPosition);
auto state = countScrollState(); auto state = countScrollState();

View File

@ -260,6 +260,7 @@ public:
bool elementIsChatWide() override; bool elementIsChatWide() override;
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override; not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override;
void elementReplyTo(const FullMsgId &to) override; void elementReplyTo(const FullMsgId &to) override;
void elementStartInteraction(not_null<const Element*> view) override;
void setEmptyInfoWidget(base::unique_qptr<Ui::RpWidget> &&w); void setEmptyInfoWidget(base::unique_qptr<Ui::RpWidget> &&w);

View File

@ -41,9 +41,6 @@ public:
_end->unloadHeavyPart(); _end->unloadHeavyPart();
} }
} }
bool hidesForwardedInfo() override {
return false;
}
private: private:
const not_null<Element*> _parent; const not_null<Element*> _parent;

View File

@ -233,10 +233,6 @@ public:
return false; return false;
} }
[[nodiscard]] virtual bool hidesForwardedInfo() const {
return false;
}
// Sometimes webpages can force the bubble to fit their size instead of // Sometimes webpages can force the bubble to fit their size instead of
// allowing message text to be as wide as possible (like wallpapers). // allowing message text to be as wide as possible (like wallpapers).
[[nodiscard]] virtual bool enforceBubbleWidth() const { [[nodiscard]] virtual bool enforceBubbleWidth() const {

View File

@ -461,9 +461,7 @@ int UnwrappedMedia::additionalWidth(
auto UnwrappedMedia::getDisplayedForwardedInfo() const auto UnwrappedMedia::getDisplayedForwardedInfo() const
-> const HistoryMessageForwarded * { -> const HistoryMessageForwarded * {
return _content->hidesForwardedInfo() return _parent->data()->Get<HistoryMessageForwarded>();
? nullptr
: _parent->data()->Get<HistoryMessageForwarded>();
} }
} // namespace HistoryView } // namespace HistoryView

View File

@ -47,9 +47,6 @@ public:
} }
virtual void refreshLink() { virtual void refreshLink() {
} }
[[nodiscard]] virtual bool hidesForwardedInfo() {
return true;
}
[[nodiscard]] virtual bool alwaysShowOutTimestamp() { [[nodiscard]] virtual bool alwaysShowOutTimestamp() {
return false; return false;
} }
@ -84,9 +81,6 @@ public:
bool customInfoLayout() const override { bool customInfoLayout() const override {
return true; return true;
} }
bool hidesForwardedInfo() const override {
return _content->hidesForwardedInfo();
}
void stickerClearLoopPlayed() override { void stickerClearLoopPlayed() override {
_content->stickerClearLoopPlayed(); _content->stickerClearLoopPlayed();
} }

View File

@ -54,9 +54,6 @@ public:
} }
} }
} }
bool hidesForwardedInfo() override {
return false;
}
private: private:
void resolveStarts(bool initSize = false); void resolveStarts(bool initSize = false);

View File

@ -296,9 +296,10 @@ void Sticker::refreshLink() {
const auto weak = base::make_weak(this); const auto weak = base::make_weak(this);
_link = std::make_shared<LambdaClickHandler>([weak] { _link = std::make_shared<LambdaClickHandler>([weak] {
const auto that = weak.get(); const auto that = weak.get();
if (!that) { if (!that || !that->_lottieOncePlayed) {
return; return;
} }
that->_parent->delegate()->elementStartInteraction(that->_parent);
that->_lottieOncePlayed = false; that->_lottieOncePlayed = false;
that->_parent->history()->owner().requestViewRepaint( that->_parent->history()->owner().requestViewRepaint(
that->_parent); that->_parent);