Move FieldAutocomplete to ChatHelpers.

This commit is contained in:
John Preston 2024-09-13 13:13:28 +04:00
parent b78443cf2d
commit 969152e949
6 changed files with 78 additions and 58 deletions

View file

@ -53,6 +53,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtWidgets/QApplication>
namespace ChatHelpers {
namespace {
[[nodiscard]] QString PrimaryUsername(not_null<UserData*> user) {
@ -60,6 +61,18 @@ namespace {
return usernames.empty() ? user->username() : usernames.front();
}
template <typename T, typename U>
inline int indexOfInFirstN(const T &v, const U &elem, int last) {
for (auto b = v.cbegin(), i = b, e = b + std::max(int(v.size()), last)
; i != e
; ++i) {
if (i->user == elem) {
return (i - b);
}
}
return -1;
}
} // namespace
class FieldAutocomplete::Inner final : public Ui::RpWidget {
@ -70,7 +83,7 @@ public:
};
Inner(
std::shared_ptr<ChatHelpers::Show> show,
std::shared_ptr<Show> show,
const style::EmojiPan &st,
not_null<FieldAutocomplete*> parent,
not_null<MentionRows*> mrows,
@ -127,7 +140,7 @@ private:
Media::Clip::Notification notification,
not_null<DocumentData*> document);
const std::shared_ptr<ChatHelpers::Show> _show;
const std::shared_ptr<Show> _show;
const not_null<Main::Session*> _session;
const style::EmojiPan &_st;
const not_null<FieldAutocomplete*> _parent;
@ -197,7 +210,7 @@ FieldAutocomplete::FieldAutocomplete(
FieldAutocomplete::FieldAutocomplete(
QWidget *parent,
std::shared_ptr<ChatHelpers::Show> show,
std::shared_ptr<Show> show,
const style::EmojiPan *stOverride)
: RpWidget(parent)
, _show(std::move(show))
@ -235,7 +248,7 @@ FieldAutocomplete::FieldAutocomplete(
}), lifetime());
}
std::shared_ptr<ChatHelpers::Show> FieldAutocomplete::uiShow() const {
std::shared_ptr<Show> FieldAutocomplete::uiShow() const {
return _show;
}
@ -373,18 +386,6 @@ bool FieldAutocomplete::clearFilteredBotCommands() {
return true;
}
namespace {
template <typename T, typename U>
inline int indexOfInFirstN(const T &v, const U &elem, int last) {
for (auto b = v.cbegin(), i = b, e = b + std::max(int(v.size()), last); i != e; ++i) {
if (i->user == elem) {
return (i - b);
}
}
return -1;
}
}
FieldAutocomplete::StickerRows FieldAutocomplete::getStickerSuggestions() {
const auto data = &_session->data().stickers();
const auto list = data->getListByEmoji({ _emoji }, _stickersSeed);
@ -871,7 +872,7 @@ bool FieldAutocomplete::eventFilter(QObject *obj, QEvent *e) {
}
FieldAutocomplete::Inner::Inner(
std::shared_ptr<ChatHelpers::Show> show,
std::shared_ptr<Show> show,
const style::EmojiPan &st,
not_null<FieldAutocomplete*> parent,
not_null<MentionRows*> mrows,
@ -963,8 +964,8 @@ void FieldAutocomplete::Inner::paintEvent(QPaintEvent *e) {
media->checkStickerSmall();
const auto paused = _show->paused(
ChatHelpers::PauseReason::TabbedPanel);
const auto size = ChatHelpers::ComputeStickerSize(
PauseReason::TabbedPanel);
const auto size = ComputeStickerSize(
document,
stickerBoundingBox());
const auto ppos = pos + QPoint(
@ -989,7 +990,7 @@ void FieldAutocomplete::Inner::paintEvent(QPaintEvent *e) {
} else if (const auto image = media->getStickerSmall()) {
p.drawPixmapLeft(ppos, width(), image->pix(size));
} else {
ChatHelpers::PaintStickerThumbnailPath(
PaintStickerThumbnailPath(
p,
media.get(),
QRect(ppos, size),
@ -1250,7 +1251,7 @@ bool FieldAutocomplete::Inner::chooseAtIndex(
const auto bounding = selectedRect(index);
auto contentRect = QRect(
QPoint(),
ChatHelpers::ComputeStickerSize(
ComputeStickerSize(
document,
stickerBoundingBox()));
contentRect.moveCenter(bounding.center());
@ -1464,9 +1465,9 @@ auto FieldAutocomplete::Inner::getLottieRenderer()
void FieldAutocomplete::Inner::setupLottie(StickerSuggestion &suggestion) {
const auto document = suggestion.document;
suggestion.lottie = ChatHelpers::LottiePlayerFromDocument(
suggestion.lottie = LottiePlayerFromDocument(
suggestion.documentMedia.get(),
ChatHelpers::StickerLottieSize::InlineResults,
StickerLottieSize::InlineResults,
stickerBoundingBox() * style::DevicePixelRatio(),
Lottie::Quality::Default,
getLottieRenderer());
@ -1534,7 +1535,7 @@ void FieldAutocomplete::Inner::clipCallback(
} else if (i->webm->state() == State::Error) {
i->webm.setBad();
} else if (i->webm->ready() && !i->webm->started()) {
const auto size = ChatHelpers::ComputeStickerSize(
const auto size = ComputeStickerSize(
i->document,
stickerBoundingBox());
i->webm->start({ .frame = size, .keepAlpha = true });
@ -1632,3 +1633,5 @@ auto FieldAutocomplete::Inner::scrollToRequested() const
-> rpl::producer<ScrollTo> {
return _scrollToRequested.events();
}
} // namespace ChatHelpers

View file

@ -46,9 +46,15 @@ struct Details;
} // namespace SendMenu
namespace ChatHelpers {
struct FileChosen;
class Show;
} // namespace ChatHelpers
enum class FieldAutocompleteChooseMethod {
ByEnter,
ByTab,
ByClick,
};
class FieldAutocomplete final : public Ui::RpWidget {
public:
@ -57,11 +63,11 @@ public:
not_null<Window::SessionController*> controller);
FieldAutocomplete(
QWidget *parent,
std::shared_ptr<ChatHelpers::Show> show,
std::shared_ptr<Show> show,
const style::EmojiPan *stOverride = nullptr);
~FieldAutocomplete();
[[nodiscard]] std::shared_ptr<ChatHelpers::Show> uiShow() const;
[[nodiscard]] std::shared_ptr<Show> uiShow() const;
bool clearFilteredBotCommands();
void showFiltered(
@ -81,11 +87,7 @@ public:
bool eventFilter(QObject *obj, QEvent *e) override;
enum class ChooseMethod {
ByEnter,
ByTab,
ByClick,
};
using ChooseMethod = FieldAutocompleteChooseMethod;
struct MentionChosen {
not_null<UserData*> user;
QString mention;
@ -100,7 +102,7 @@ public:
QString command;
ChooseMethod method = ChooseMethod::ByEnter;
};
using StickerChosen = ChatHelpers::FileChosen;
using StickerChosen = FileChosen;
enum class Type {
Mentions,
Hashtags,
@ -157,7 +159,7 @@ private:
void recount(bool resetScroll = false);
StickerRows getStickerSuggestions();
const std::shared_ptr<ChatHelpers::Show> _show;
const std::shared_ptr<Show> _show;
const not_null<Main::Session*> _session;
const style::EmojiPan &_st;
QPixmap _cache;
@ -193,3 +195,5 @@ private:
Fn<bool(int)> _moderateKeyActivateCallback;
};
} // namespace ChatHelpers

View file

@ -118,6 +118,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/media/history_view_media.h"
#include "profile/profile_block_group_members.h"
#include "core/click_handler_types.h"
#include "chat_helpers/field_autocomplete.h"
#include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_selector.h"
#include "chat_helpers/tabbed_section.h"
@ -473,7 +474,8 @@ HistoryWidget::HistoryWidget(
}, lifetime());
_fieldAutocomplete->mentionChosen(
) | rpl::start_with_next([=](FieldAutocomplete::MentionChosen data) {
) | rpl::start_with_next([=](
ChatHelpers::FieldAutocomplete::MentionChosen data) {
auto replacement = QString();
auto entityTag = QString();
if (data.mention.isEmpty()) {
@ -489,13 +491,15 @@ HistoryWidget::HistoryWidget(
}, lifetime());
_fieldAutocomplete->hashtagChosen(
) | rpl::start_with_next([=](FieldAutocomplete::HashtagChosen data) {
) | rpl::start_with_next([=](
ChatHelpers::FieldAutocomplete::HashtagChosen data) {
insertHashtagOrBotCommand(data.hashtag, data.method);
}, lifetime());
_fieldAutocomplete->botCommandChosen(
) | rpl::start_with_next([=](FieldAutocomplete::BotCommandChosen data) {
using Method = FieldAutocomplete::ChooseMethod;
) | rpl::start_with_next([=](
ChatHelpers::FieldAutocomplete::BotCommandChosen data) {
using Method = ChatHelpers::FieldAutocompleteChooseMethod;
const auto messages = &data.user->owner().shortcutMessages();
const auto shortcut = data.user->isSelf();
const auto command = data.command.mid(1);
@ -528,11 +532,11 @@ HistoryWidget::HistoryWidget(
});
_fieldAutocomplete->choosingProcesses(
) | rpl::start_with_next([=](FieldAutocomplete::Type type) {
) | rpl::start_with_next([=](ChatHelpers::FieldAutocomplete::Type type) {
if (!_history) {
return;
}
if (type == FieldAutocomplete::Type::Stickers) {
if (type == ChatHelpers::FieldAutocomplete::Type::Stickers) {
session().sendProgressManager().update(
_history,
Api::SendProgressType::ChooseSticker);
@ -1488,13 +1492,14 @@ void HistoryWidget::start() {
void HistoryWidget::insertHashtagOrBotCommand(
QString str,
FieldAutocomplete::ChooseMethod method) {
ChatHelpers::FieldAutocompleteChooseMethod method) {
if (!_peer) {
return;
}
// Send bot command at once, if it was not inserted by pressing Tab.
if (str.at(0) == '/' && method != FieldAutocomplete::ChooseMethod::ByTab) {
using Method = ChatHelpers::FieldAutocompleteChooseMethod;
if (str.at(0) == '/' && method != Method::ByTab) {
sendBotCommand({ _peer, str, FullMsgId(), replyTo() });
session().api().finishForwarding(prepareSendAction({}));
setFieldText(_field->getTextWithTagsPart(_field->textCursor().position()));
@ -6935,7 +6940,8 @@ void HistoryWidget::fieldTabbed() {
if (_supportAutocomplete) {
_supportAutocomplete->activate(_field.data());
} else if (!_fieldAutocomplete->isHidden()) {
_fieldAutocomplete->chooseSelected(FieldAutocomplete::ChooseMethod::ByTab);
_fieldAutocomplete->chooseSelected(
ChatHelpers::FieldAutocomplete::ChooseMethod::ByTab);
}
}

View file

@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_view_highlight_manager.h"
#include "history/history_view_top_toast.h"
#include "history/history.h"
#include "chat_helpers/field_autocomplete.h"
#include "chat_helpers/field_characters_count_manager.h"
#include "window/section_widget.h"
#include "ui/widgets/fields/input_field.h"
@ -84,6 +83,8 @@ class SessionController;
namespace ChatHelpers {
class TabbedPanel;
class TabbedSelector;
class FieldAutocomplete;
enum class FieldAutocompleteChooseMethod;
} // namespace ChatHelpers
namespace HistoryView {
@ -368,7 +369,7 @@ private:
void insertHashtagOrBotCommand(
QString str,
FieldAutocomplete::ChooseMethod method);
ChatHelpers::FieldAutocompleteChooseMethod method);
void cancelInlineBot();
void saveDraft(bool delayed = false);
void saveCloudDraft();
@ -739,7 +740,7 @@ private:
HistoryView::CornerButtons _cornerButtons;
const object_ptr<FieldAutocomplete> _fieldAutocomplete;
const object_ptr<ChatHelpers::FieldAutocomplete> _fieldAutocomplete;
object_ptr<Support::Autocomplete> _supportAutocomplete;
UserData *_inlineBot = nullptr;

View file

@ -859,7 +859,7 @@ ComposeControls::ComposeControls(
_wrap.get(),
st::historyBotCommandStart)
: nullptr)
, _autocomplete(std::make_unique<FieldAutocomplete>(
, _autocomplete(std::make_unique<ChatHelpers::FieldAutocomplete>(
parent,
_show,
&_st.tabbed))
@ -1701,9 +1701,10 @@ void ComposeControls::updateSubmitSettings() {
void ComposeControls::initAutocomplete() {
const auto insertHashtagOrBotCommand = [=](
const QString &string,
FieldAutocomplete::ChooseMethod method) {
ChatHelpers::FieldAutocompleteChooseMethod method) {
// Send bot command at once, if it was not inserted by pressing Tab.
if (string.at(0) == '/' && method != FieldAutocomplete::ChooseMethod::ByTab) {
using Method = ChatHelpers::FieldAutocompleteChooseMethod;
if (string.at(0) == '/' && method != Method::ByTab) {
_sendCommandRequests.fire_copy(string);
setText(
_field->getTextWithTagsPart(_field->textCursor().position()));
@ -1713,7 +1714,8 @@ void ComposeControls::initAutocomplete() {
};
_autocomplete->mentionChosen(
) | rpl::start_with_next([=](FieldAutocomplete::MentionChosen data) {
) | rpl::start_with_next([=](
ChatHelpers::FieldAutocomplete::MentionChosen data) {
const auto user = data.user;
if (data.mention.isEmpty()) {
_field->insertTag(
@ -1725,17 +1727,20 @@ void ComposeControls::initAutocomplete() {
}, _autocomplete->lifetime());
_autocomplete->hashtagChosen(
) | rpl::start_with_next([=](FieldAutocomplete::HashtagChosen data) {
) | rpl::start_with_next([=](
ChatHelpers::FieldAutocomplete::HashtagChosen data) {
insertHashtagOrBotCommand(data.hashtag, data.method);
}, _autocomplete->lifetime());
_autocomplete->botCommandChosen(
) | rpl::start_with_next([=](FieldAutocomplete::BotCommandChosen data) {
) | rpl::start_with_next([=](
ChatHelpers::FieldAutocomplete::BotCommandChosen data) {
insertHashtagOrBotCommand(data.command, data.method);
}, _autocomplete->lifetime());
_autocomplete->stickerChosen(
) | rpl::start_with_next([=](FieldAutocomplete::StickerChosen data) {
) | rpl::start_with_next([=](
ChatHelpers::FieldAutocomplete::StickerChosen data) {
if (!_showSlowmodeError || !_showSlowmodeError()) {
setText({});
}
@ -1747,8 +1752,8 @@ void ComposeControls::initAutocomplete() {
}, _autocomplete->lifetime());
_autocomplete->choosingProcesses(
) | rpl::start_with_next([=](FieldAutocomplete::Type type) {
if (type == FieldAutocomplete::Type::Stickers) {
) | rpl::start_with_next([=](ChatHelpers::FieldAutocomplete::Type type) {
if (type == ChatHelpers::FieldAutocomplete::Type::Stickers) {
_sendActionUpdates.fire({
.type = Api::SendProgressType::ChooseSticker,
});
@ -2125,7 +2130,8 @@ void ComposeControls::cancelForward() {
void ComposeControls::fieldTabbed() {
if (!_autocomplete->isHidden()) {
_autocomplete->chooseSelected(FieldAutocomplete::ChooseMethod::ByTab);
_autocomplete->chooseSelected(
ChatHelpers::FieldAutocomplete::ChooseMethod::ByTab);
}
}

View file

@ -21,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class History;
class DocumentData;
class FieldAutocomplete;
class Image;
namespace style {
@ -39,6 +38,7 @@ struct FileChosen;
struct PhotoChosen;
class Show;
enum class PauseReason;
class FieldAutocomplete;
} // namespace ChatHelpers
namespace Data {
@ -391,7 +391,7 @@ private:
std::unique_ptr<InlineBots::Layout::Widget> _inlineResults;
std::unique_ptr<ChatHelpers::TabbedPanel> _tabbedPanel;
std::unique_ptr<Ui::DropdownMenu> _attachBotsMenu;
std::unique_ptr<FieldAutocomplete> _autocomplete;
std::unique_ptr<ChatHelpers::FieldAutocomplete> _autocomplete;
friend class FieldHeader;
const std::unique_ptr<FieldHeader> _header;