From 817e9aa43de1aafb1522ae89d1f7d8c7f7465739 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 29 Mar 2019 16:21:11 +0400 Subject: [PATCH] Fix crash in emoji keywords init. --- .../chat_helpers/emoji_keywords.cpp | 41 +++++++++++++++---- .../SourceFiles/chat_helpers/emoji_keywords.h | 1 + .../chat_helpers/emoji_suggestions_widget.cpp | 19 +++++---- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp b/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp index 4be4d8d44..a569c526d 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp @@ -20,6 +20,7 @@ namespace ChatHelpers { namespace { constexpr auto kRefreshEach = 60 * 60 * crl::time(1000); // 1 hour. +constexpr auto kKeepNotUsedLangPacksCount = 10; using namespace Ui::Emoji; @@ -208,6 +209,8 @@ public: LangPack &operator=(const LangPack &other) = delete; ~LangPack(); + [[nodiscard]] QString id() const; + void refresh(); void apiChanged(); @@ -270,6 +273,10 @@ void EmojiKeywords::LangPack::readLocalCache() { }); } +QString EmojiKeywords::LangPack::id() const { + return _id; +} + void EmojiKeywords::LangPack::refresh() { if (_state != State::Refreshed) { return; @@ -417,14 +424,16 @@ void EmojiKeywords::handleAuthSessionChanges() { void EmojiKeywords::apiChanged(ApiWrap *api) { _api = api; if (_api) { - base::ObservableViewer( - Lang::CurrentCloudManager().firstLanguageSuggestion() - ) | rpl::filter([=] { - // Refresh with the suggested language if we already were asked. - return !_data.empty(); - }) | rpl::start_with_next([=] { - refresh(); - }, _suggestedChangeLifetime); + crl::on_main(&Auth(), crl::guard(&_guard, [=] { + base::ObservableViewer( + Lang::CurrentCloudManager().firstLanguageSuggestion() + ) | rpl::filter([=] { + // Refresh with the suggested language if we already were asked. + return !_data.empty(); + }) | rpl::start_with_next([=] { + refresh(); + }, _suggestedChangeLifetime); + })); } else { _langsRequestId = 0; _suggestedChangeLifetime.destroy(); @@ -452,6 +461,9 @@ std::vector EmojiKeywords::query( const QString &query, bool exact) const { const auto normalized = NormalizeQuery(query); + if (normalized.isEmpty()) { + return {}; + } auto result = std::vector(); for (const auto &[language, item] : _data) { const auto oldcount = result.size(); @@ -514,6 +526,10 @@ void EmojiKeywords::setRemoteList(std::vector &&list) { if (ranges::find(_remoteList, i->first) != end(_remoteList)) { ++i; } else { + if (_notUsedData.size() > kKeepNotUsedLangPacksCount) { + _notUsedData.pop_front(); + } + _notUsedData.push_back(std::move(i->second)); i = _data.erase(i); } } @@ -524,6 +540,15 @@ void EmojiKeywords::refreshFromRemoteList() { for (const auto &id : _remoteList) { if (const auto i = _data.find(id); i != end(_data)) { i->second->refresh(); + continue; + } + const auto i = ranges::find( + _notUsedData, + id, + [](const std::unique_ptr &p) { return p->id(); }); + if (i != end(_notUsedData)) { + _data.emplace(id, std::move(*i)); + _notUsedData.erase(i); } else { _data.emplace( id, diff --git a/Telegram/SourceFiles/chat_helpers/emoji_keywords.h b/Telegram/SourceFiles/chat_helpers/emoji_keywords.h index bdd03822f..7d4e6f13a 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_keywords.h +++ b/Telegram/SourceFiles/chat_helpers/emoji_keywords.h @@ -62,6 +62,7 @@ private: std::vector _remoteList; mtpRequestId _langsRequestId = 0; base::flat_map> _data; + std::deque> _notUsedData; rpl::event_stream<> _refreshed; rpl::lifetime _suggestedChangeLifetime; diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp index 0f4b2b3a4..5041cab1f 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp @@ -112,7 +112,7 @@ std::vector SuggestionsWidget::getRowsByQuery() const { return result; } auto suggestions = std::vector(); - const auto results = Core::App().emojiKeywords().query(_query.mid(1)); + const auto results = Core::App().emojiKeywords().query(_query); for (const auto &result : results) { suggestions.emplace_back( result.emoji, @@ -475,13 +475,13 @@ QString SuggestionsController::getEmojiQuery() { return QString(); } - auto cursor = _field->textCursor(); + const auto cursor = _field->textCursor(); if (cursor.hasSelection()) { return QString(); } - auto position = cursor.position(); - auto findTextPart = [this, &position] { + const auto position = cursor.position(); + const auto findTextPart = [&] { auto document = _field->document(); auto block = document->findBlock(position); for (auto i = block.begin(); !i.atEnd(); ++i) { @@ -496,18 +496,21 @@ QString SuggestionsController::getEmojiQuery() { if (fragment.charFormat().isImageFormat()) { continue; } - position -= from; _queryStartPosition = from; return fragment.text(); } return QString(); }; - auto text = findTextPart(); + const auto text = findTextPart(); if (text.isEmpty()) { return QString(); } - + for (auto i = position - _queryStartPosition; i != 0;) { + if (text[--i] == ':') { + return text.mid(i + 1); + } + } const auto isUpperCaseLetter = [](QChar ch) { return (ch >= 'A' && ch <= 'Z'); }; @@ -568,7 +571,7 @@ QString SuggestionsController::getEmojiQuery() { } void SuggestionsController::replaceCurrent(const QString &replacement) { - auto suggestion = getEmojiQuery(); + const auto suggestion = getEmojiQuery(); if (suggestion.isEmpty()) { _suggestions->showWithQuery(QString()); } else {