From 86c04424f670ed709c0e513c089d7bca813c3f19 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 30 Sep 2024 13:45:36 +0400 Subject: [PATCH] Add mention/hashtag autocomplete to GIF caption. --- .../boxes/send_gif_with_caption_box.cpp | 72 ++++++++++++++++++- .../boxes/send_gif_with_caption_box.h | 2 + .../chat_helpers/gifs_list_widget.cpp | 4 +- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/boxes/send_gif_with_caption_box.cpp b/Telegram/SourceFiles/boxes/send_gif_with_caption_box.cpp index 3ee0ac3c4..b27102876 100644 --- a/Telegram/SourceFiles/boxes/send_gif_with_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/send_gif_with_caption_box.cpp @@ -7,7 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/send_gif_with_caption_box.h" +#include "base/event_filter.h" #include "boxes/premium_preview_box.h" +#include "chat_helpers/field_autocomplete.h" #include "chat_helpers/message_field.h" #include "chat_helpers/tabbed_panel.h" #include "chat_helpers/tabbed_selector.h" @@ -30,9 +32,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/controls/emoji_button.h" #include "ui/controls/emoji_button_factory.h" #include "ui/layers/generic_box.h" -#include "ui/rect.h" -#include "ui/vertical_list.h" #include "ui/widgets/fields/input_field.h" +#include "ui/rect.h" +#include "ui/ui_utility.h" +#include "ui/vertical_list.h" #include "window/window_controller.h" #include "window/window_session_controller.h" #include "styles/style_boxes.h" @@ -226,6 +229,7 @@ namespace { void SendGifWithCaptionBox( not_null box, not_null document, + not_null peer, const SendMenu::Details &details, Fn done) { const auto window = Core::App().findWindow(box); @@ -255,6 +259,61 @@ void SendGifWithCaptionBox( return true; }); + const auto sendMenuDetails = [=] { return details; }; + struct Autocomplete { + std::unique_ptr dropdown; + bool geometryUpdateScheduled = false; + }; + const auto autocomplete = box->lifetime().make_state(); + const auto outer = box->getDelegate()->outerContainer(); + ChatHelpers::InitFieldAutocomplete(autocomplete->dropdown, { + .parent = outer, + .show = controller->uiShow(), + .field = input, + .peer = peer, + .features = [=] { + auto result = ChatHelpers::ComposeFeatures(); + result.autocompleteCommands = false; + result.suggestStickersByEmoji = false; + return result; + }, + .sendMenuDetails = sendMenuDetails, + }); + const auto raw = autocomplete->dropdown.get(); + const auto recountPostponed = [=] { + if (autocomplete->geometryUpdateScheduled) { + return; + } + autocomplete->geometryUpdateScheduled = true; + Ui::PostponeCall(raw, [=] { + autocomplete->geometryUpdateScheduled = false; + + const auto from = input->parentWidget(); + auto field = Ui::MapFrom(outer, from, input->geometry()); + const auto &st = st::defaultComposeFiles; + autocomplete->dropdown->setBoundings(QRect( + field.x() - input->x(), + st::defaultBox.margin.top(), + input->width(), + (field.y() + + st.caption.textMargins.top() + + st.caption.placeholderShift + + st.caption.placeholderFont->height + - st::defaultBox.margin.top()))); + }); + }; + for (auto w = (QWidget*)input; w; w = w->parentWidget()) { + base::install_event_filter(raw, w, [=](not_null e) { + if (e->type() == QEvent::Move || e->type() == QEvent::Resize) { + recountPostponed(); + } + return base::EventFilterResult::Continue; + }); + if (w == outer) { + break; + } + } + const auto send = [=](Api::SendOptions options) { done(std::move(options), input->getTextWithTags()); }; @@ -264,8 +323,15 @@ void SendGifWithCaptionBox( SendMenu::SetupMenuAndShortcuts( confirm, controller->uiShow(), - [=] { return details; }, + sendMenuDetails, SendMenu::DefaultCallback(controller->uiShow(), send)); + box->setShowFinishedCallback([=] { + if (const auto raw = autocomplete->dropdown.get()) { + InvokeQueued(raw, [=] { + raw->raise(); + }); + } + }); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); diff --git a/Telegram/SourceFiles/boxes/send_gif_with_caption_box.h b/Telegram/SourceFiles/boxes/send_gif_with_caption_box.h index df78366d5..0247cf5e3 100644 --- a/Telegram/SourceFiles/boxes/send_gif_with_caption_box.h +++ b/Telegram/SourceFiles/boxes/send_gif_with_caption_box.h @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +class PeerData; class DocumentData; namespace Api { @@ -24,6 +25,7 @@ class GenericBox; void SendGifWithCaptionBox( not_null box, not_null document, + not_null peer, const SendMenu::Details &details, Fn done); diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 4ed82d5f1..c04823295 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -409,17 +409,19 @@ base::unique_qptr GifsListWidget::fillContextMenu( SendMenu::DefaultCallback(_show, send), icons); - if (!isInlineResult) { + if (!isInlineResult && _inlineQueryPeer) { auto done = crl::guard(this, [=]( Api::SendOptions options, TextWithTags text) { selectInlineResult(selected, options, true, std::move(text)); }); const auto show = _show; + const auto peer = _inlineQueryPeer; menu->addAction(tr::lng_send_gif_with_caption(tr::now), [=] { show->show(Box( Ui::SendGifWithCaptionBox, item->getDocument(), + peer, copyDetails, std::move(done))); }, &st::menuIconEdit);