From 59903b0b1c26884d6987c1f418773bcfd835b7a6 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 2 Aug 2022 19:23:06 +0300 Subject: [PATCH] Suggest animated emoji in Saved Messages. --- .../SourceFiles/boxes/edit_caption_box.cpp | 8 ++- Telegram/SourceFiles/boxes/send_files_box.cpp | 8 ++- Telegram/SourceFiles/boxes/share_box.cpp | 3 +- .../chat_helpers/emoji_suggestions_widget.cpp | 56 ++++++++++--------- .../chat_helpers/emoji_suggestions_widget.h | 21 ++++--- .../SourceFiles/history/history_widget.cpp | 6 +- .../history_view_compose_controls.cpp | 6 +- 7 files changed, 67 insertions(+), 41 deletions(-) diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index 73c777cef..97432bda6 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -244,15 +244,19 @@ void EditCaptionBox::rebuildPreview() { void EditCaptionBox::setupField() { const auto peer = _historyItem->history()->peer; + const auto allow = [=](const auto&) { + return Data::AllowEmojiWithoutPremium(peer); + }; InitMessageFieldHandlers( _controller, _field.get(), Window::GifPauseReason::Layer, - [=](const auto&) { return Data::AllowEmojiWithoutPremium(peer); }); + allow); Ui::Emoji::SuggestionsController::Init( getDelegate()->outerContainer(), _field, - &_controller->session()); + &_controller->session(), + { .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow }); _field->setSubmitSettings( Core::App().settings().sendSubmitWay()); diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 046705365..d943685b7 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -674,15 +674,19 @@ void SendFilesBox::updateSendWayControlsVisibility() { } void SendFilesBox::setupCaption() { + const auto allow = [=](const auto&) { + return _allowEmojiWithoutPremium; + }; InitMessageFieldHandlers( _controller, _caption.data(), Window::GifPauseReason::Layer, - [=](const auto&) { return _allowEmojiWithoutPremium; }); + allow); Ui::Emoji::SuggestionsController::Init( getDelegate()->outerContainer(), _caption, - &_controller->session()); + &_controller->session(), + { .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow }); _caption->setSubmitSettings( Core::App().settings().sendSubmitWay()); diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 6193a097d..f47cfca12 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -299,7 +299,8 @@ void ShareBox::prepare() { Ui::Emoji::SuggestionsController::Init( getDelegate()->outerContainer(), _comment->entity(), - _descriptor.session); + _descriptor.session, + { .suggestCustomEmoji = true }); _select->raise(); } diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp index 643bd2dd7..deb825539 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp @@ -43,9 +43,13 @@ constexpr auto kAnimationDuration = crl::time(120); SuggestionsWidget::SuggestionsWidget( QWidget *parent, - not_null session) + not_null session, + bool suggestCustomEmoji, + Fn)> allowCustomWithoutPremium) : RpWidget(parent) , _session(session) +, _suggestCustomEmoji(suggestCustomEmoji) +, _allowCustomWithoutPremium(std::move(allowCustomWithoutPremium)) , _oneWidth(st::emojiSuggestionSize) , _padding(st::emojiSuggestionsPadding) { resize( @@ -71,11 +75,11 @@ void SuggestionsWidget::showWithQuery(SuggestionsQuery query, bool force) { _query = query; auto rows = [&] { if (const auto emoji = std::get_if(&query)) { - return prependCustom( + return appendCustom( {}, lookupCustom({ Row(*emoji, (*emoji)->text()) })); } - return prependCustom(getRowsByQuery(v::get(query))); + return appendCustom(getRowsByQuery(v::get(query))); }(); if (rows.empty()) { _toggleAnimated.fire(false); @@ -99,15 +103,15 @@ void SuggestionsWidget::selectFirstResult() { } } -auto SuggestionsWidget::prependCustom(std::vector rows) +auto SuggestionsWidget::appendCustom(std::vector rows) -> std::vector { const auto custom = lookupCustom(rows); - return prependCustom(std::move(rows), custom); + return appendCustom(std::move(rows), custom); } auto SuggestionsWidget::lookupCustom(const std::vector &rows) const -> base::flat_multi_map { - if (rows.empty()) { + if (rows.empty() || !_suggestCustomEmoji) { return {}; } auto custom = base::flat_multi_map(); @@ -119,20 +123,25 @@ auto SuggestionsWidget::lookupCustom(const std::vector &rows) const continue; } for (const auto &document : i->second->stickers) { - if (!premium && document->isPremiumEmoji()) { + if (!premium + && document->isPremiumEmoji() + && (!_allowCustomWithoutPremium + || !_allowCustomWithoutPremium(document))) { // Skip the whole premium emoji set. break; } if (const auto sticker = document->sticker()) { if (const auto emoji = Ui::Emoji::Find(sticker->alt)) { - const auto j = ranges::find( + const auto original = emoji->original(); + const auto j = ranges::find_if( rows, - not_null{ emoji }, - &Row::emoji); + [&](const Row &row) { + return row.emoji->original() == original; + }); if (j != end(rows)) { custom.emplace(int(j - begin(rows)), Custom{ .document = document, - .emoji = j->emoji, + .emoji = emoji, .replacement = j->replacement, }); } @@ -143,24 +152,17 @@ auto SuggestionsWidget::lookupCustom(const std::vector &rows) const return custom; } -auto SuggestionsWidget::prependCustom( +auto SuggestionsWidget::appendCustom( std::vector rows, const base::flat_multi_map &custom) -> std::vector { - if (custom.empty()) { - return rows; - } - auto result = std::vector(); - result.reserve(custom.size() + rows.size()); + rows.reserve(rows.size() + custom.size()); for (const auto &[position, one] : custom) { - result.push_back(Row(one.emoji, one.replacement)); - result.back().document = one.document; - result.back().custom = resolveCustomEmoji(one.document); + rows.push_back(Row(one.emoji, one.replacement)); + rows.back().document = one.document; + rows.back().custom = resolveCustomEmoji(one.document); } - for (auto &row : rows) { - result.push_back(std::move(row)); - } - return result; + return rows; } not_null SuggestionsWidget::resolveCustomEmoji( @@ -639,7 +641,9 @@ SuggestionsController::SuggestionsController( _suggestions = _container->setOwnedWidget( object_ptr( _container, - session)); + session, + _options.suggestCustomEmoji, + _options.allowCustomWithoutPremium)); setReplaceCallback(nullptr); @@ -689,7 +693,7 @@ SuggestionsController::SuggestionsController( handleTextChange(); } -SuggestionsController *SuggestionsController::Init( +not_null SuggestionsController::Init( not_null outer, not_null field, not_null session, diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.h b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.h index e25794c15..9e0319bfb 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.h +++ b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.h @@ -33,7 +33,11 @@ using SuggestionsQuery = std::variant; class SuggestionsWidget final : public Ui::RpWidget { public: - SuggestionsWidget(QWidget *parent, not_null session); + SuggestionsWidget( + QWidget *parent, + not_null session, + bool suggestCustomEmoji, + Fn)> allowCustomWithoutPremium); ~SuggestionsWidget(); void showWithQuery(SuggestionsQuery query, bool force = false); @@ -78,9 +82,9 @@ private: [[nodiscard]] std::vector getRowsByQuery(const QString &text) const; [[nodiscard]] base::flat_multi_map lookupCustom( const std::vector &rows) const; - [[nodiscard]] std::vector prependCustom( + [[nodiscard]] std::vector appendCustom( std::vector rows); - [[nodiscard]] std::vector prependCustom( + [[nodiscard]] std::vector appendCustom( std::vector rows, const base::flat_multi_map &custom); void resizeToRows(); @@ -110,6 +114,8 @@ private: const not_null _session; SuggestionsQuery _query; std::vector _rows; + bool _suggestCustomEmoji = false; + Fn)> _allowCustomWithoutPremium; base::flat_map< not_null, @@ -139,10 +145,9 @@ private: class SuggestionsController { public: struct Options { - Options() : suggestExactFirstWord(true) { - } - - bool suggestExactFirstWord; + bool suggestExactFirstWord = true; + bool suggestCustomEmoji = false; + Fn)> allowCustomWithoutPremium; }; SuggestionsController( @@ -158,7 +163,7 @@ public: const QString &replacement, const QString &customEmojiData)> callback); - static SuggestionsController *Init( + static not_null Init( not_null outer, not_null field, not_null session, diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index b7e3433fb..01160d0e3 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -480,10 +480,14 @@ HistoryWidget::HistoryWidget( Unexpected("action in MimeData hook."); }); + const auto allow = [=](const auto&) { + return _peer && _peer->isSelf(); + }; const auto suggestions = Ui::Emoji::SuggestionsController::Init( this, _field, - &controller->session()); + &controller->session(), + { .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow }); _raiseEmojiSuggestions = [=] { suggestions->raise(); }; updateFieldSubmitSettings(); diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index 02e76bc61..6524a6d92 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -1432,10 +1432,14 @@ void ComposeControls::initField() { return false; }); initAutocomplete(); + const auto allow = [=](const auto &) { + return _history && Data::AllowEmojiWithoutPremium(_history->peer); + }; const auto suggestions = Ui::Emoji::SuggestionsController::Init( _parent, _field, - &_window->session()); + &_window->session(), + { .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow }); _raiseEmojiSuggestions = [=] { suggestions->raise(); }; const auto rawTextEdit = _field->rawTextEdit().get();