From 40fbd415ef8a4d0c287a5fadf379bdb7699edd44 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 30 May 2024 15:05:13 +0400 Subject: [PATCH] Support collapsible blockquotes in Ui::Text::String. --- Telegram/CMakeLists.txt | 4 ++-- Telegram/SourceFiles/api/api_text_entities.cpp | 8 +++++++- .../SourceFiles/chat_helpers/message_field.cpp | 3 ++- Telegram/SourceFiles/data/data_session.cpp | 15 +++++++++++---- .../SourceFiles/export/data/export_data_types.cpp | 2 ++ .../export/output/export_output_json.cpp | 4 ++++ .../history/view/history_view_element.cpp | 10 ++++++++-- .../history/view/history_view_element.h | 1 + ...k_handler.cpp => history_view_text_helper.cpp} | 14 ++++++++++---- ...click_handler.h => history_view_text_helper.h} | 4 +--- .../history/view/media/history_view_document.cpp | 8 ++++++-- .../history/view/media/history_view_media.cpp | 4 ++-- .../view/media/history_view_media_grouped.cpp | 8 +++++++- .../history/view/media/history_view_web_page.cpp | 15 +++++++++------ Telegram/SourceFiles/ui/chat/chat.style | 13 +++++++++++-- Telegram/lib_ui | 2 +- 16 files changed, 84 insertions(+), 31 deletions(-) rename Telegram/SourceFiles/history/view/{history_view_spoiler_click_handler.cpp => history_view_text_helper.cpp} (68%) rename Telegram/SourceFiles/history/view/{history_view_spoiler_click_handler.h => history_view_text_helper.h} (78%) diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 6e786a6cd..fa06b446a 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -837,14 +837,14 @@ PRIVATE history/view/history_view_send_action.h history/view/history_view_service_message.cpp history/view/history_view_service_message.h - history/view/history_view_spoiler_click_handler.cpp - history/view/history_view_spoiler_click_handler.h history/view/history_view_sponsored_click_handler.cpp history/view/history_view_sponsored_click_handler.h history/view/history_view_sticker_toast.cpp history/view/history_view_sticker_toast.h history/view/history_view_sublist_section.cpp history/view/history_view_sublist_section.h + history/view/history_view_text_helper.cpp + history/view/history_view_text_helper.h history/view/history_view_transcribe_button.cpp history/view/history_view_transcribe_button.h history/view/history_view_translate_bar.cpp diff --git a/Telegram/SourceFiles/api/api_text_entities.cpp b/Telegram/SourceFiles/api/api_text_entities.cpp index 3c5098911..93d5cc5f3 100644 --- a/Telegram/SourceFiles/api/api_text_entities.cpp +++ b/Telegram/SourceFiles/api/api_text_entities.cpp @@ -217,6 +217,7 @@ EntitiesInText EntitiesFromMTP( EntityType::Blockquote, d.voffset().v, d.vlength().v, + d.is_collapsed() ? u"1"_q : QString(), }); }); } @@ -311,8 +312,13 @@ MTPVector EntitiesToMTP( MTP_string(entity.data()))); } break; case EntityType::Blockquote: { + using Flag = MTPDmessageEntityBlockquote::Flag; + const auto collapsed = !entity.data().isEmpty(); v.push_back( - MTP_messageEntityBlockquote(MTP_flags(0), offset, length)); + MTP_messageEntityBlockquote( + MTP_flags(collapsed ? Flag::f_collapsed : Flag()), + offset, + length)); } break; case EntityType::Spoiler: { v.push_back(MTP_messageEntitySpoiler(offset, length)); diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index 836459ad8..8b5f3c373 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -748,7 +748,8 @@ void MessageLinksParser::parse() { || (tag == Ui::InputField::kTagUnderline) || (tag == Ui::InputField::kTagStrikeOut) || (tag == Ui::InputField::kTagSpoiler) - || (tag == Ui::InputField::kTagBlockquote); + || (tag == Ui::InputField::kTagBlockquote) + || (tag == Ui::InputField::kTagBlockquoteCollapsed); }; _ranges.clear(); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 529b933d4..dba1c3d69 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -1820,12 +1820,19 @@ rpl::producer> Session::itemDataChanges() const { } void Session::requestItemTextRefresh(not_null item) { - if (const auto i = _views.find(item); i != _views.end()) { - for (const auto &view : i->second) { - view->itemTextUpdated(); + const auto call = [&](not_null item) { + if (const auto i = _views.find(item); i != _views.end()) { + for (const auto &view : i->second) { + view->itemTextUpdated(); + } } - requestItemResize(item); + }; + if (const auto group = groups().find(item)) { + call(group->items.front()); + } else { + call(item); } + requestItemResize(item); } void Session::registerHighlightProcess( diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index c4b55f346..71750a575 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -307,6 +307,8 @@ std::vector ParseText( return NumberToString(data.vuser_id().v); }, [](const MTPDmessageEntityCustomEmoji &data) { return NumberToString(data.vdocument_id().v); + }, [](const MTPDmessageEntityBlockquote &data) { + return data.is_collapsed() ? Utf8String("1") : Utf8String(); }, [](const auto &) { return Utf8String(); }); result.push_back(std::move(part)); diff --git a/Telegram/SourceFiles/export/output/export_output_json.cpp b/Telegram/SourceFiles/export/output/export_output_json.cpp index 67814e5b2..b485e615b 100644 --- a/Telegram/SourceFiles/export/output/export_output_json.cpp +++ b/Telegram/SourceFiles/export/output/export_output_json.cpp @@ -195,6 +195,8 @@ QByteArray SerializeText( ? "language" : (part.type == Type::TextUrl) ? "href" + : (part.type == Type::Blockquote) + ? "collapsed" : "none"; const auto additionalValue = (part.type == Type::MentionName) ? part.additional @@ -202,6 +204,8 @@ QByteArray SerializeText( || part.type == Type::TextUrl || part.type == Type::CustomEmoji) ? SerializeString(part.additional) + : (part.type == Type::Blockquote) + ? (part.additional.isEmpty() ? "false" : "true") : QByteArray(); return SerializeObject(context, { { "type", SerializeString(typeString) }, diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 3cdb44ed0..df32ee082 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -18,7 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/reactions/history_view_reactions.h" #include "history/view/history_view_cursor_state.h" #include "history/view/history_view_reply.h" -#include "history/view/history_view_spoiler_click_handler.h" +#include "history/view/history_view_text_helper.h" #include "history/history.h" #include "history/history_item_components.h" #include "history/history_item_helpers.h" @@ -1027,7 +1027,7 @@ void Element::setTextWithLinks( refreshMedia(nullptr); } } - FillTextWithAnimatedSpoilers(this, _text); + InitElementTextPart(this, _text); _textWidth = -1; _textHeight = 0; } @@ -1464,6 +1464,12 @@ void Element::itemTextUpdated() { } } +void Element::blockquoteExpandChanged() { + _textWidth = -1; + _textHeight = 0; + history()->owner().requestViewResize(this); +} + void Element::unloadHeavyPart() { history()->owner().unregisterHeavyViewPart(this); if (_media) { diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index fdac9a583..0c01e9767 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -498,6 +498,7 @@ public: virtual void itemDataChanged(); void itemTextUpdated(); + void blockquoteExpandChanged(); [[nodiscard]] virtual bool hasHeavyPart() const; virtual void unloadHeavyPart(); diff --git a/Telegram/SourceFiles/history/view/history_view_spoiler_click_handler.cpp b/Telegram/SourceFiles/history/view/history_view_text_helper.cpp similarity index 68% rename from Telegram/SourceFiles/history/view/history_view_spoiler_click_handler.cpp rename to Telegram/SourceFiles/history/view/history_view_text_helper.cpp index eb72db0f2..fbe97ed56 100644 --- a/Telegram/SourceFiles/history/view/history_view_spoiler_click_handler.cpp +++ b/Telegram/SourceFiles/history/view/history_view_text_helper.cpp @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "history/view/history_view_spoiler_click_handler.h" +#include "history/view/history_view_text_helper.h" #include "data/data_session.h" #include "history/view/history_view_element.h" @@ -15,9 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace HistoryView { -void FillTextWithAnimatedSpoilers( - not_null view, - Ui::Text::String &text) { +void InitElementTextPart(not_null view, Ui::Text::String &text) { if (text.hasSpoilers()) { text.setSpoilerLinkFilter([weak = base::make_weak(view)]( const ClickContext &context) { @@ -30,6 +28,14 @@ void FillTextWithAnimatedSpoilers( return true; }); } + if (text.hasCollapsedBlockquots()) { + const auto weak = base::make_weak(view); + text.setBlockquoteExpandCallback([=](int quoteIndex, bool expanded) { + if (const auto view = weak.get()) { + view->blockquoteExpandChanged(); + } + }); + } } } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_spoiler_click_handler.h b/Telegram/SourceFiles/history/view/history_view_text_helper.h similarity index 78% rename from Telegram/SourceFiles/history/view/history_view_spoiler_click_handler.h rename to Telegram/SourceFiles/history/view/history_view_text_helper.h index 3bef398b6..d7a604b53 100644 --- a/Telegram/SourceFiles/history/view/history_view_spoiler_click_handler.h +++ b/Telegram/SourceFiles/history/view/history_view_text_helper.h @@ -11,8 +11,6 @@ namespace HistoryView { class Element; -void FillTextWithAnimatedSpoilers( - not_null view, - Ui::Text::String &text); +void InitElementTextPart(not_null view, Ui::Text::String &text); } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/media/history_view_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_document.cpp index e415264b3..b1c972053 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_document.cpp @@ -1490,8 +1490,12 @@ QMargins Document::bubbleMargins() const { } void Document::refreshCaption(bool last) { + const auto now = Get(); auto caption = createCaption(); if (!caption.isEmpty()) { + if (now) { + return; + } AddComponents(HistoryDocumentCaptioned::Bit()); auto captioned = Get(); captioned->caption = std::move(caption); @@ -1503,7 +1507,7 @@ void Document::refreshCaption(bool last) { } else { captioned->caption.removeSkipBlock(); } - } else { + } else if (now) { RemoveComponents(HistoryDocumentCaptioned::Bit()); } } @@ -1637,7 +1641,7 @@ void Document::refreshParentId(not_null realParent) { } void Document::parentTextUpdated() { - history()->owner().requestViewResize(_parent); + RemoveComponents(HistoryDocumentCaptioned::Bit()); } void Document::hideSpoilers() { diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.cpp b/Telegram/SourceFiles/history/view/media/history_view_media.cpp index 65c209153..4f8c8096b 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media.cpp @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item.h" #include "history/view/history_view_element.h" #include "history/view/history_view_cursor_state.h" -#include "history/view/history_view_spoiler_click_handler.h" +#include "history/view/history_view_text_helper.h" #include "history/view/media/history_view_sticker.h" #include "history/view/media/history_view_media_spoiler.h" #include "storage/storage_shared_media.h" @@ -319,7 +319,7 @@ Ui::Text::String Media::createCaption(not_null item) const { item->translatedTextWithLocalEntities(), Ui::ItemTextOptions(item), context); - FillTextWithAnimatedSpoilers(_parent, result); + InitElementTextPart(_parent, result); if (const auto width = _parent->skipBlockWidth()) { result.updateSkipBlock(width, _parent->skipBlockHeight()); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp index c4e51f174..b1c8ba33d 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp @@ -781,7 +781,13 @@ void GroupedMedia::unloadHeavyPart() { void GroupedMedia::parentTextUpdated() { if (_parent->media() == this) { - _captionItem = std::nullopt; + if (_mode == Mode::Column) { + for (const auto &part : _parts) { + part.content->parentTextUpdated(); + } + } else { + _captionItem = std::nullopt; + } } } diff --git a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp index 0275ed2c2..44863dd41 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp @@ -282,7 +282,9 @@ WebPage::WebPage( not_null data, MediaWebPageFlags flags) : Media(parent) -, _st(st::historyPagePreview) +, _st(data->type == WebPageType::Factcheck + ? st::factcheckPage + : st::historyPagePreview) , _data(data) , _flags(flags) , _siteName(st::msgMinWidth - _st.padding.left() - _st.padding.right()) @@ -859,13 +861,14 @@ void WebPage::draw(Painter &p, const PaintContext &context) const { FillBackgroundEmoji(p, outer, false, *backgroundEmojiCache); } } else if (factcheck && factcheck->expandable) { - const auto &icon = factcheck->expanded - ? st::factcheckIconCollapse - : st::factcheckIconExpand; + const auto &icon = factcheck->expanded ? _st.collapse : _st.expand; + const auto &position = factcheck->expanded + ? _st.collapsePosition + : _st.expandPosition; icon.paint( p, - outer.x() + outer.width() - icon.width() - _st.padding.right(), - outer.y() + _st.padding.top(), + outer.x() + outer.width() - icon.width() - position.x(), + outer.y() + outer.height() - icon.height() - position.y(), width()); } diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 3069b6f90..622ba8357 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -66,6 +66,10 @@ messageTextStyle: TextStyle(defaultTextStyle) { padding: margins(10px, 2px, 20px, 2px); icon: icon{{ "chat/mini_quote", windowFg }}; iconPosition: point(4px, 4px); + expand: icon{{ "intro_country_dropdown", windowFg }}; + expandPosition: point(6px, 4px); + collapse: icon{{ "intro_country_dropdown-flip_vertical", windowFg }}; + collapsePosition: point(6px, 4px); } pre: QuoteStyle(messageQuoteStyle) { header: 20px; @@ -1137,8 +1141,13 @@ factcheckFooterSkip: 16px; factcheckFooterStyle: TextStyle(defaultTextStyle) { font: font(11px); } -factcheckIconExpand: icon {{ "fast_to_original-rotate_cw", historyPeer1NameFg }}; -factcheckIconCollapse: icon {{ "fast_to_original-rotate_ccw", historyPeer1NameFg }}; +factcheckPage: QuoteStyle(historyPagePreview) { + padding: margins(10px, 5px, 22px, 7px); + expand: icon {{ "intro_country_dropdown", historyPeer1NameFg }}; + expandPosition: point(6px, 4px); + collapse: icon {{ "intro_country_dropdown-flip_vertical", historyPeer1NameFg }}; + collapsePosition: point(6px, 4px); +} factcheckField: InputField(defaultInputField) { textBg: transparent; textMargins: margins(0px, 0px, 0px, 4px); diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 0835adcc2..495ea0af5 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 0835adcc2d3cb1f2cf0d3630f6d95485864621f9 +Subproject commit 495ea0af50da469fb30769ac2d78251e4279a746