diff --git a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp index 3ee265c3d5..c0b4cdac61 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp @@ -30,6 +30,18 @@ namespace { constexpr auto kRefreshTimeout = 7200 * crl::time(1000); +[[nodiscard]] std::optional 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() { const auto single = st::largeEmojiSize; const auto outline = st::largeEmojiOutline; @@ -207,6 +219,13 @@ std::shared_ptr EmojiPack::image(EmojiPtr emoji) { return result; } +auto EmojiPack::animationsForEmoji(EmojiPtr emoji) const +-> const base::flat_map> & { + static const auto empty = base::flat_map>(); + const auto i = _animations.find(emoji); + return (i != end(_animations)) ? i->second : empty; +} + void EmojiPack::refresh() { if (_requestId) { return; @@ -215,7 +234,7 @@ void EmojiPack::refresh() { MTP_inputStickerSetAnimatedEmoji() )).done([=](const MTPmessages_StickerSet &result) { _requestId = 0; - refreshDelayed(); + refreshAnimations(); result.match([&](const MTPDmessages_stickerSet &data) { applySet(data); }); @@ -225,6 +244,24 @@ void EmojiPack::refresh() { }).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) { const auto stickers = collectStickers(data.vdocuments().v); 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 &packs +) const -> base::flat_map> { + auto result = base::flat_map>(); + 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() { for (const auto &[emoji, list] : _items) { refreshItems(list); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.h b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.h index 06c55028f6..8f62a5d2af 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.h @@ -67,17 +67,25 @@ public: [[nodiscard]] Sticker stickerForEmoji(const IsolatedEmoji &emoji); [[nodiscard]] std::shared_ptr image(EmojiPtr emoji); + [[nodiscard]] auto animationsForEmoji(EmojiPtr emoji) const + -> const base::flat_map> &; + private: class ImageLoader; void refresh(); void refreshDelayed(); + void refreshAnimations(); void applySet(const MTPDmessages_stickerSet &data); void applyPack( const MTPDstickerPack &data, const base::flat_map> &map); - base::flat_map> collectStickers( - const QVector &list) const; + void applyAnimationsSet(const MTPDmessages_stickerSet &data); + [[nodiscard]] auto collectStickers(const QVector &list) const + -> base::flat_map>; + [[nodiscard]] auto collectAnimationsIndices( + const QVector &packs) const + -> base::flat_map>; void refreshAll(); void refreshItems(EmojiPtr emoji); void refreshItems(const base::flat_set> &list); @@ -90,6 +98,11 @@ private: base::flat_map> _images; mtpRequestId _requestId = 0; + base::flat_map< + EmojiPtr, + base::flat_map>> _animations; + mtpRequestId _animationsRequestId = 0; + rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index d3c81ba87b..36408ac03a 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -674,6 +674,9 @@ not_null InnerWidget::elementPathShiftGradient() { void InnerWidget::elementReplyTo(const FullMsgId &to) { } +void InnerWidget::elementStartInteraction(not_null view) { +} + void InnerWidget::saveState(not_null memento) { memento->setFilter(std::move(_filter)); memento->setAdmins(std::move(_admins)); diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h index ff11d6f046..3ef1f089ea 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h @@ -137,6 +137,8 @@ public: bool elementIsChatWide() override; not_null elementPathShiftGradient() override; void elementReplyTo(const FullMsgId &to) override; + void elementStartInteraction( + not_null view) override; ~InnerWidget(); diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 6ba9f5da5a..eaa84b00f8 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -2689,6 +2689,9 @@ void HistoryInner::elementReplyTo(const FullMsgId &to) { return _widget->replyToMessage(to); } +void HistoryInner::elementStartInteraction(not_null view) { +} + auto HistoryInner::getSelectionState() const -> HistoryView::TopBarWidget::SelectedState { auto result = HistoryView::TopBarWidget::SelectedState {}; @@ -3601,6 +3604,11 @@ not_null HistoryInner::ElementDelegate() { Instance->elementReplyTo(to); } } + void elementStartInteraction(not_null view) override { + if (Instance) { + Instance->elementStartInteraction(view); + } + } }; static Result result; diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index 483a694f6b..626e2f6576 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -115,6 +115,7 @@ public: bool elementIsChatWide(); not_null elementPathShiftGradient(); void elementReplyTo(const FullMsgId &to); + void elementStartInteraction(not_null view); void updateBotInfo(bool recount = true); diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 72c8e3b3ff..fef37d3982 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -177,6 +177,11 @@ auto SimpleElementDelegate::elementPathShiftGradient() void SimpleElementDelegate::elementReplyTo(const FullMsgId &to) { } + +void SimpleElementDelegate::elementStartInteraction( + not_null view) { +} + TextSelection UnshiftItemSelection( TextSelection selection, uint16 byLength) { @@ -219,24 +224,6 @@ QString DateTooltipText(not_null view) { tr::now, lt_date, 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) { dateText = tr::lng_forwarded_imported(tr::now) + "\n\n" + dateText; diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index 081a4cbfb1..22cbdeebcb 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -90,6 +90,7 @@ public: virtual bool elementIsChatWide() = 0; virtual not_null elementPathShiftGradient() = 0; virtual void elementReplyTo(const FullMsgId &to) = 0; + virtual void elementStartInteraction(not_null view) = 0; virtual ~ElementDelegate() { } @@ -146,6 +147,7 @@ public: bool elementIsChatWide() override; not_null elementPathShiftGradient() override; void elementReplyTo(const FullMsgId &to) override; + void elementStartInteraction(not_null view) override; protected: [[nodiscard]] not_null controller() const { diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index b0ece7340f..dc07d08492 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -1391,6 +1391,9 @@ void ListWidget::elementReplyTo(const FullMsgId &to) { replyToMessageRequestNotify(to); } +void ListWidget::elementStartInteraction(not_null view) { +} + void ListWidget::saveState(not_null memento) { memento->setAroundPosition(_aroundPosition); auto state = countScrollState(); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index 19347a70ed..ac9a266603 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -260,6 +260,7 @@ public: bool elementIsChatWide() override; not_null elementPathShiftGradient() override; void elementReplyTo(const FullMsgId &to) override; + void elementStartInteraction(not_null view) override; void setEmptyInfoWidget(base::unique_qptr &&w); diff --git a/Telegram/SourceFiles/history/view/media/history_view_dice.h b/Telegram/SourceFiles/history/view/media/history_view_dice.h index d6e77d7432..6a18dffa05 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_dice.h +++ b/Telegram/SourceFiles/history/view/media/history_view_dice.h @@ -41,9 +41,6 @@ public: _end->unloadHeavyPart(); } } - bool hidesForwardedInfo() override { - return false; - } private: const not_null _parent; diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.h b/Telegram/SourceFiles/history/view/media/history_view_media.h index 3d8e574983..9bcec685b1 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media.h @@ -233,10 +233,6 @@ public: return false; } - [[nodiscard]] virtual bool hidesForwardedInfo() const { - return false; - } - // Sometimes webpages can force the bubble to fit their size instead of // allowing message text to be as wide as possible (like wallpapers). [[nodiscard]] virtual bool enforceBubbleWidth() const { diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp index 6c5be08aaf..bdd3c5431c 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp @@ -461,9 +461,7 @@ int UnwrappedMedia::additionalWidth( auto UnwrappedMedia::getDisplayedForwardedInfo() const -> const HistoryMessageForwarded * { - return _content->hidesForwardedInfo() - ? nullptr - : _parent->data()->Get(); + return _parent->data()->Get(); } } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.h b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.h index fabcdddf8e..c72f7e5181 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.h @@ -47,9 +47,6 @@ public: } virtual void refreshLink() { } - [[nodiscard]] virtual bool hidesForwardedInfo() { - return true; - } [[nodiscard]] virtual bool alwaysShowOutTimestamp() { return false; } @@ -84,9 +81,6 @@ public: bool customInfoLayout() const override { return true; } - bool hidesForwardedInfo() const override { - return _content->hidesForwardedInfo(); - } void stickerClearLoopPlayed() override { _content->stickerClearLoopPlayed(); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_slot_machine.h b/Telegram/SourceFiles/history/view/media/history_view_slot_machine.h index 861969a9d4..2aef84afa3 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_slot_machine.h +++ b/Telegram/SourceFiles/history/view/media/history_view_slot_machine.h @@ -54,9 +54,6 @@ public: } } } - bool hidesForwardedInfo() override { - return false; - } private: void resolveStarts(bool initSize = false); diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp index 977c292b84..ad9672df07 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp @@ -296,9 +296,10 @@ void Sticker::refreshLink() { const auto weak = base::make_weak(this); _link = std::make_shared([weak] { const auto that = weak.get(); - if (!that) { + if (!that || !that->_lottieOncePlayed) { return; } + that->_parent->delegate()->elementStartInteraction(that->_parent); that->_lottieOncePlayed = false; that->_parent->history()->owner().requestViewRepaint( that->_parent);