Suggest animated emoji in Saved Messages.

This commit is contained in:
John Preston 2022-08-02 19:23:06 +03:00
parent 2319278c92
commit 59903b0b1c
7 changed files with 67 additions and 41 deletions

View File

@ -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());

View File

@ -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());

View File

@ -299,7 +299,8 @@ void ShareBox::prepare() {
Ui::Emoji::SuggestionsController::Init(
getDelegate()->outerContainer(),
_comment->entity(),
_descriptor.session);
_descriptor.session,
{ .suggestCustomEmoji = true });
_select->raise();
}

View File

@ -43,9 +43,13 @@ constexpr auto kAnimationDuration = crl::time(120);
SuggestionsWidget::SuggestionsWidget(
QWidget *parent,
not_null<Main::Session*> session)
not_null<Main::Session*> session,
bool suggestCustomEmoji,
Fn<bool(not_null<DocumentData*>)> 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<EmojiPtr>(&query)) {
return prependCustom(
return appendCustom(
{},
lookupCustom({ Row(*emoji, (*emoji)->text()) }));
}
return prependCustom(getRowsByQuery(v::get<QString>(query)));
return appendCustom(getRowsByQuery(v::get<QString>(query)));
}();
if (rows.empty()) {
_toggleAnimated.fire(false);
@ -99,15 +103,15 @@ void SuggestionsWidget::selectFirstResult() {
}
}
auto SuggestionsWidget::prependCustom(std::vector<Row> rows)
auto SuggestionsWidget::appendCustom(std::vector<Row> rows)
-> std::vector<Row> {
const auto custom = lookupCustom(rows);
return prependCustom(std::move(rows), custom);
return appendCustom(std::move(rows), custom);
}
auto SuggestionsWidget::lookupCustom(const std::vector<Row> &rows) const
-> base::flat_multi_map<int, Custom> {
if (rows.empty()) {
if (rows.empty() || !_suggestCustomEmoji) {
return {};
}
auto custom = base::flat_multi_map<int, Custom>();
@ -119,20 +123,25 @@ auto SuggestionsWidget::lookupCustom(const std::vector<Row> &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<Row> &rows) const
return custom;
}
auto SuggestionsWidget::prependCustom(
auto SuggestionsWidget::appendCustom(
std::vector<Row> rows,
const base::flat_multi_map<int, Custom> &custom)
-> std::vector<Row> {
if (custom.empty()) {
return rows;
}
auto result = std::vector<Row>();
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<Ui::Text::CustomEmoji*> SuggestionsWidget::resolveCustomEmoji(
@ -639,7 +641,9 @@ SuggestionsController::SuggestionsController(
_suggestions = _container->setOwnedWidget(
object_ptr<Ui::Emoji::SuggestionsWidget>(
_container,
session));
session,
_options.suggestCustomEmoji,
_options.allowCustomWithoutPremium));
setReplaceCallback(nullptr);
@ -689,7 +693,7 @@ SuggestionsController::SuggestionsController(
handleTextChange();
}
SuggestionsController *SuggestionsController::Init(
not_null<SuggestionsController*> SuggestionsController::Init(
not_null<QWidget*> outer,
not_null<Ui::InputField*> field,
not_null<Main::Session*> session,

View File

@ -33,7 +33,11 @@ using SuggestionsQuery = std::variant<QString, EmojiPtr>;
class SuggestionsWidget final : public Ui::RpWidget {
public:
SuggestionsWidget(QWidget *parent, not_null<Main::Session*> session);
SuggestionsWidget(
QWidget *parent,
not_null<Main::Session*> session,
bool suggestCustomEmoji,
Fn<bool(not_null<DocumentData*>)> allowCustomWithoutPremium);
~SuggestionsWidget();
void showWithQuery(SuggestionsQuery query, bool force = false);
@ -78,9 +82,9 @@ private:
[[nodiscard]] std::vector<Row> getRowsByQuery(const QString &text) const;
[[nodiscard]] base::flat_multi_map<int, Custom> lookupCustom(
const std::vector<Row> &rows) const;
[[nodiscard]] std::vector<Row> prependCustom(
[[nodiscard]] std::vector<Row> appendCustom(
std::vector<Row> rows);
[[nodiscard]] std::vector<Row> prependCustom(
[[nodiscard]] std::vector<Row> appendCustom(
std::vector<Row> rows,
const base::flat_multi_map<int, Custom> &custom);
void resizeToRows();
@ -110,6 +114,8 @@ private:
const not_null<Main::Session*> _session;
SuggestionsQuery _query;
std::vector<Row> _rows;
bool _suggestCustomEmoji = false;
Fn<bool(not_null<DocumentData*>)> _allowCustomWithoutPremium;
base::flat_map<
not_null<DocumentData*>,
@ -139,10 +145,9 @@ private:
class SuggestionsController {
public:
struct Options {
Options() : suggestExactFirstWord(true) {
}
bool suggestExactFirstWord;
bool suggestExactFirstWord = true;
bool suggestCustomEmoji = false;
Fn<bool(not_null<DocumentData*>)> allowCustomWithoutPremium;
};
SuggestionsController(
@ -158,7 +163,7 @@ public:
const QString &replacement,
const QString &customEmojiData)> callback);
static SuggestionsController *Init(
static not_null<SuggestionsController*> Init(
not_null<QWidget*> outer,
not_null<Ui::InputField*> field,
not_null<Main::Session*> session,

View File

@ -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();

View File

@ -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();