From ea438aeb8509b23e7789e9d198cf03f537d90fc5 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 29 May 2026 23:59:47 +0400 Subject: [PATCH] Correctly host rich message in the item. --- .../data/data_file_click_handler.cpp | 3 +- .../SourceFiles/data/data_file_origin.cpp | 6 +++ Telegram/SourceFiles/history/history_item.cpp | 10 ++++- .../view/history_view_context_menu.cpp | 1 - .../history/view/history_view_element.cpp | 44 ++++++++++++++----- .../history/view/history_view_message.h | 1 + .../view/media/history_view_document.cpp | 5 +++ Telegram/SourceFiles/iv/iv_cached_media.cpp | 39 +++++++++++----- .../iv/markdown/iv_markdown_article.cpp | 3 ++ .../iv_markdown_history_view_media.cpp | 28 ++++++++++++ .../markdown/iv_markdown_history_view_media.h | 3 ++ 11 files changed, 117 insertions(+), 26 deletions(-) diff --git a/Telegram/SourceFiles/data/data_file_click_handler.cpp b/Telegram/SourceFiles/data/data_file_click_handler.cpp index e42397d197..7f0a593b4f 100644 --- a/Telegram/SourceFiles/data/data_file_click_handler.cpp +++ b/Telegram/SourceFiles/data/data_file_click_handler.cpp @@ -96,8 +96,7 @@ void DocumentSaveClickHandler::Save( return; } const auto filepath = data->filepath(true); - const auto fileinfo = QFileInfo( - ); + const auto fileinfo = QFileInfo(filepath); const auto filedir = filepath.isEmpty() ? QDir() : fileinfo.dir(); diff --git a/Telegram/SourceFiles/data/data_file_origin.cpp b/Telegram/SourceFiles/data/data_file_origin.cpp index 505d6bb74a..4a3c759f63 100644 --- a/Telegram/SourceFiles/data/data_file_origin.cpp +++ b/Telegram/SourceFiles/data/data_file_origin.cpp @@ -43,6 +43,11 @@ struct FileReferenceAccumulator { push(data.data().vphotos()); push(data.data().vdocuments()); } + void push(const MTPRichMessage &data) { + const auto &fields = data.data(); + push(fields.vphotos()); + push(fields.vdocuments()); + } void push(const MTPWallPaper &data) { data.match([&](const MTPDwallPaper &data) { push(data.vdocument()); @@ -142,6 +147,7 @@ struct FileReferenceAccumulator { data.match([&](const MTPDmessage &data) { push(data.vmedia()); push(data.vreply_to()); + push(data.vrich_message()); }, [&](const MTPDmessageService &data) { data.vaction().match( [&](const MTPDmessageActionChatEditPhoto &data) { diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 6875d86ca2..6886e76dc5 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -4160,17 +4160,23 @@ void HistoryItem::applyLocalRichPage( void HistoryItem::setRichPage(std::shared_ptr page) { if (page) { - AddComponents(HistoryMessageRichPageSource::Bit()); + AddComponents(HistoryMessageRichPageSource::Bit() + | HistoryMessageMediaForInstantView::Bit()); const auto source = Get(); + const auto media = Get(); source->page = std::move(page); source->canEdit = Iv::Editor::CanEditRichPage(source->page); + media->url = QString(); + media->documents.clear(); + media->photos.clear(); } else { clearRichPage(); } } void HistoryItem::clearRichPage() { - RemoveComponents(HistoryMessageRichPageSource::Bit()); + RemoveComponents(HistoryMessageRichPageSource::Bit() + | HistoryMessageMediaForInstantView::Bit()); } void HistoryItem::setTextValue(TextWithEntities text, bool force) { diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 5e6b57675b..7fb4cb8290 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -81,7 +81,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "data/data_chat.h" #include "data/data_file_click_handler.h" -#include "data/data_file_origin.h" #include "data/data_message_reactions.h" #include "data/data_user.h" #include "data/stickers/data_custom_emoji.h" diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index d025740129..874001c6e7 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/ui_integration.h" #include "main/main_app_config.h" #include "main/main_session.h" +#include "spellcheck/spellcheck_highlight_syntax.h" #include "chat_helpers/stickers_emoji_pack.h" #include "payments/payments_reaction_process.h" // TryAddingPaidReaction. #include "window/window_session_controller.h" @@ -1855,19 +1856,40 @@ void Element::validateText() { AddComponents(HistoryMessageRichPage::Bit()); } const auto runtime = Get(); - runtime->host.owner = base::make_weak(message); - runtime->article.setMediaBlockHost(&runtime->host); - runtime->article.setTextRepaintCallbacks( - [weak = runtime->host.owner] { + const auto needsBinding = (runtime->article.mediaBlockHost() + != &runtime->host); + const auto needsHighlightSubscription = !runtime->highlightReadyLifetime; + if (needsBinding || needsHighlightSubscription) { + const auto weak = base::make_weak(message); + runtime->host.owner = weak; + if (needsBinding) { + runtime->article.setMediaBlockHost(&runtime->host); + runtime->article.setTextRepaintCallbacks( + [weak] { + if (const auto owner = weak.get()) { + owner->requestRichPageRepaint(QRect()); + } + }, + [weak](QRect articleRect) { + if (const auto owner = weak.get()) { + owner->requestRichPageRepaint(articleRect); + } + }); + } + } + if (needsHighlightSubscription) { + Spellchecker::HighlightReady( + ) | rpl::on_next([weak = runtime->host.owner]( + Spellchecker::HighlightProcessId processId) { if (const auto owner = weak.get()) { - owner->requestRichPageRepaint(QRect()); + if (const auto rich = owner->richpage()) { + if (rich->article.highlightProcessDone(processId)) { + owner->requestRichPageRepaint(QRect()); + } + } } - }, - [weak = runtime->host.owner](QRect articleRect) { - if (const auto owner = weak.get()) { - owner->requestRichPageRepaint(articleRect); - } - }); + }, runtime->highlightReadyLifetime); + } if (runtime->page == page && runtime->mediaRuntime) { return; } diff --git a/Telegram/SourceFiles/history/view/history_view_message.h b/Telegram/SourceFiles/history/view/history_view_message.h index 836bc66667..03b38e79c6 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.h +++ b/Telegram/SourceFiles/history/view/history_view_message.h @@ -85,6 +85,7 @@ struct HistoryMessageRichPage std::shared_ptr mediaRuntime; Iv::Markdown::MarkdownArticle article; Iv::Markdown::MarkdownArticleThinkingPaintCache thinkingPaintCache; + rpl::lifetime highlightReadyLifetime; int paletteVersion = -1; Host host; mutable ClickHandlerPtr handler; diff --git a/Telegram/SourceFiles/history/view/media/history_view_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_document.cpp index a2ff1be7d6..f150e96f13 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_document.cpp @@ -1846,6 +1846,11 @@ void Document::refreshParentId(not_null realParent) { if (auto thumbed = Get()) { if (thumbed->linksavel) { thumbed->linksavel->setMessageId(fullId); + } + if (thumbed->linkopenwithl) { + thumbed->linkopenwithl->setMessageId(fullId); + } + if (thumbed->linkcancell) { thumbed->linkcancell->setMessageId(fullId); } } diff --git a/Telegram/SourceFiles/iv/iv_cached_media.cpp b/Telegram/SourceFiles/iv/iv_cached_media.cpp index 8d47613b11..e5f3b909e9 100644 --- a/Telegram/SourceFiles/iv/iv_cached_media.cpp +++ b/Telegram/SourceFiles/iv/iv_cached_media.cpp @@ -956,8 +956,7 @@ public: [[nodiscard]] std::shared_ptr hostedMediaHost( - not_null controller, - not_null history) const; + not_null controller) const; [[nodiscard]] std::shared_ptr hostedMediaBlockFactory() const override; @@ -971,6 +970,7 @@ private: const not_null _session; const ::Data::FileOrigin _origin; + const FullMsgId _itemId; const QString _pageUrl; const Fn _openChannel; const Fn _joinChannel; @@ -987,6 +987,7 @@ CachedPageMediaRuntime::CachedPageMediaRuntime( Fn joinChannel) : _session(session) , _origin(::Data::FileOriginWebPage{ page->url }) +, _itemId() , _pageUrl(page->url) , _openChannel(std::move(openChannel)) , _joinChannel(std::move(joinChannel)) { @@ -999,6 +1000,7 @@ CachedPageMediaRuntime::CachedPageMediaRuntime( Fn joinChannel) : _session(session) , _origin(itemId) +, _itemId(itemId) , _pageUrl() , _openChannel(std::move(openChannel)) , _joinChannel(std::move(joinChannel)) { @@ -1090,9 +1092,29 @@ QString CachedPageMediaRuntime::mentionNameEntityData(uint64 userId) const { } auto CachedPageMediaRuntime::hostedMediaHost( - not_null controller, - not_null history) const + not_null controller) const -> std::shared_ptr { + if (_itemId) { + const auto item = _session->data().message(_itemId); + if (!item) { + return nullptr; + } + if (!_hostedMediaHost) { + _hostedMediaHost + = std::make_shared( + controller, + not_null{ item }); + } + return _hostedMediaHost; + } + if (!_session->data().peerLoaded(PeerData::kServiceNotificationsId)) { + return nullptr; + } + const auto history = _session->data().history( + PeerData::kServiceNotificationsId); + if (!history->peer->isUser()) { + return nullptr; + } if (!_hostedMediaHost) { _hostedMediaHost = std::make_shared( @@ -1106,16 +1128,13 @@ auto CachedPageMediaRuntime::hostedMediaHost( auto CachedPageMediaRuntime::hostedMediaBlockFactory() const -> std::shared_ptr { const auto controller = CurrentSessionController(_session); - if (!controller || !_session->data().peerLoaded( - PeerData::kServiceNotificationsId)) { + if (!controller) { return nullptr; } - const auto history = _session->data().history( - PeerData::kServiceNotificationsId); - if (!history->peer->isUser()) { + const auto host = hostedMediaHost(not_null{ controller }); + if (!host) { return nullptr; } - const auto host = hostedMediaHost(not_null{ controller }, history); return std::make_shared( base::make_weak(controller), [session = _session, host, origin = fileOrigin()]( diff --git a/Telegram/SourceFiles/iv/markdown/iv_markdown_article.cpp b/Telegram/SourceFiles/iv/markdown/iv_markdown_article.cpp index d5844299b1..6b21b82d21 100644 --- a/Telegram/SourceFiles/iv/markdown/iv_markdown_article.cpp +++ b/Telegram/SourceFiles/iv/markdown/iv_markdown_article.cpp @@ -1310,6 +1310,9 @@ void MarkdownArticle::Impl::setRenderer(std::shared_ptr renderer) } void MarkdownArticle::Impl::setMediaBlockHost(MediaBlockHost *host) { + if (_mediaBlockHost == host) { + return; + } _mediaBlockHost = host; refreshMediaBlockHosts(); } diff --git a/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.cpp b/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.cpp index 8c30a0ad4b..595932e7ff 100644 --- a/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.cpp +++ b/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.cpp @@ -500,12 +500,16 @@ struct IvHistoryViewMediaHost::State { not_null controller, not_null history, QString pageUrl); + State( + not_null controller, + not_null item); const not_null<::Data::Session*> session; const QString pageUrl; const std::unique_ptr delegate; const not_null item; AdminLog::OwnedItem owned; + std::unique_ptr realView; HistoryView::Message *view = nullptr; }; @@ -529,6 +533,24 @@ IvHistoryViewMediaHost::State::State( view->setInstantViewMediaRuntime(this->pageUrl); } +IvHistoryViewMediaHost::State::State( + not_null controller, + not_null item) +: session(&item->history()->owner()) +, delegate(std::make_unique( + controller, + session, + [=] { + if (view) { + view->repaint(); + } + })) +, item(item) +, realView(this->item->createView(delegate.get())) +, view(static_cast(realView.get())) { + view->setInstantViewMediaRuntime(this->pageUrl); +} + IvHistoryViewMediaHost::IvHistoryViewMediaHost( not_null controller, not_null history, @@ -539,6 +561,12 @@ IvHistoryViewMediaHost::IvHistoryViewMediaHost( std::move(pageUrl))) { } +IvHistoryViewMediaHost::IvHistoryViewMediaHost( + not_null controller, + not_null item) +: _state(std::make_unique(controller, item)) { +} + IvHistoryViewMediaHost::~IvHistoryViewMediaHost() = default; not_null<::Data::Session*> IvHistoryViewMediaHost::session() const { diff --git a/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.h b/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.h index 85fe59b874..ef32103954 100644 --- a/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.h +++ b/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.h @@ -41,6 +41,9 @@ public: not_null controller, not_null history, QString pageUrl); + IvHistoryViewMediaHost( + not_null controller, + not_null item); ~IvHistoryViewMediaHost(); [[nodiscard]] not_null<::Data::Session*> session() const;