diff --git a/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp index 24e684cf9..fd8a3a89b 100644 --- a/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_compose_controls.h" #include "base/unixtime.h" +#include "data/data_messages.h" #include "data/data_web_page.h" #include "ui/widgets/input_fields.h" #include "ui/special_buttons.h" @@ -40,6 +41,12 @@ namespace { using MessageToEdit = ComposeControls::MessageToEdit; +constexpr auto kMouseEvent = { + QEvent::MouseMove, + QEvent::MouseButtonPress, + QEvent::MouseButtonRelease +}; + [[nodiscard]] auto ShowWebPagePreview(WebPageData *page) { return page && (page->pendingTill >= 0); } @@ -73,6 +80,7 @@ public: bool isDisplayed() const; bool isEditingMessage() const; rpl::producer editMsgId() const; + rpl::producer scrollToItemRequests() const; MessageToEdit queryToEdit(); WebPageId webPageId() const; @@ -107,6 +115,7 @@ private: const not_null _cancel; rpl::event_stream _visibleChanged; + rpl::event_stream _scrollToItemRequests; }; @@ -124,6 +133,7 @@ void FieldHeader::init() { updateControlsGeometry(size); }, lifetime()); + const auto leftIconPressed = lifetime().make_state(false); paintRequest( ) | rpl::start_with_next([=] { Painter p(this); @@ -134,9 +144,9 @@ void FieldHeader::init() { st::historyEditIcon.paint(p, position, width()); } - ShowWebPagePreview(_preview.data) - ? paintWebPage(p) - : paintEditMessage(p); + (!ShowWebPagePreview(_preview.data) || *leftIconPressed) + ? paintEditMessage(p) + : paintWebPage(p); }, lifetime()); const auto checkPreview = [=](not_null item) { @@ -189,6 +199,49 @@ void FieldHeader::init() { Ui::DialogTextOptions()); }, lifetime()); + setMouseTracking(true); + const auto inClickable = lifetime().make_state(false); + events( + ) | rpl::filter([=](not_null event) { + return ranges::contains(kMouseEvent, event->type()) + && isEditingMessage(); + }) | rpl::start_with_next([=](not_null event) { + const auto type = event->type(); + const auto e = static_cast(event.get()); + const auto pos = e ? e->pos() : mapFromGlobal(QCursor::pos()); + const auto inPreviewRect = QRect( + st::historyReplySkip, + 0, + width() - st::historyReplySkip - _cancel->width(), + height()).contains(pos); + + if (type == QEvent::MouseMove) { + const auto inEdit = inPreviewRect; + + if (inEdit != *inClickable) { + *inClickable = inEdit; + setCursor(*inClickable + ? style::cur_pointer + : style::cur_default); + } + return; + } + const auto isLeftIcon = (pos.x() < st::historyReplySkip); + const auto isLeftButton = (e->button() == Qt::LeftButton); + if (type == QEvent::MouseButtonPress) { + if (isLeftButton && isLeftIcon) { + *leftIconPressed = true; + update(); + } else if (isLeftButton && inPreviewRect) { + _scrollToItemRequests.fire(_editMsgId.current()); + } + } else if (type == QEvent::MouseButtonRelease) { + if (isLeftButton && *leftIconPressed) { + *leftIconPressed = false; + update(); + } + } + }, lifetime()); } void FieldHeader::previewRequested( @@ -317,6 +370,10 @@ rpl::producer FieldHeader::editMsgId() const { return _editMsgId.value(); } +rpl::producer FieldHeader::scrollToItemRequests() const { + return _scrollToItemRequests.events(); +} + MessageToEdit FieldHeader::queryToEdit() { const auto item = _data->message(_editMsgId.current()); if (!isEditingMessage() || !item) { @@ -954,4 +1011,14 @@ WebPageId ComposeControls::webPageId() const { return _header->webPageId(); } +rpl::producer ComposeControls::scrollRequests() const { + return _header->scrollToItemRequests( + ) | rpl::map([=](FullMsgId id) -> Data::MessagePosition { + if (const auto item = _window->session().data().message(id)) { + return item->position(); + } + return {}; + }); +} + } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_compose_controls.h b/Telegram/SourceFiles/history/view/history_view_compose_controls.h index 42dee7fd5..f4533c831 100644 --- a/Telegram/SourceFiles/history/view/history_view_compose_controls.h +++ b/Telegram/SourceFiles/history/view/history_view_compose_controls.h @@ -21,6 +21,10 @@ class TabbedPanel; class TabbedSelector; } // namespace ChatHelpers +namespace Data { +struct MessagePosition; +} // namespace Data + namespace InlineBots { namespace Layout { class ItemBase; @@ -83,6 +87,7 @@ public: [[nodiscard]] rpl::producer<> attachRequests() const; [[nodiscard]] rpl::producer> fileChosen() const; [[nodiscard]] rpl::producer> photoChosen() const; + [[nodiscard]] rpl::producer scrollRequests() const; [[nodiscard]] auto inlineResultChosen() const -> rpl::producer; diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 9cf9c9b5e..e1acf6404 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -202,6 +202,11 @@ void ScheduledWidget::setupComposeControls() { sendInlineResult(chosen.result, chosen.bot); }, lifetime()); + _composeControls->scrollRequests( + ) | rpl::start_with_next([=](Data::MessagePosition pos) { + showAtPosition(pos); + }, lifetime()); + _composeControls->setMimeDataHook([=]( not_null data, Ui::InputField::MimeAction action) {