From 647e3b4b4fbf040abfa66914ee71ba8d62eedc01 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 5 May 2026 23:27:28 +0400 Subject: [PATCH] Adjust width of file albums by captions. --- .../history/view/history_view_message.cpp | 8 ++- .../view/media/history_view_document.cpp | 55 +++++++++++++------ .../view/media/history_view_document.h | 2 + .../history/view/media/history_view_media.h | 8 +++ .../view/media/history_view_media_grouped.cpp | 20 +++++++ .../view/media/history_view_media_grouped.h | 1 + 6 files changed, 77 insertions(+), 17 deletions(-) diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 705befeac1..957aa73dcd 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -4222,8 +4222,14 @@ void Message::refreshDataIdHook() { } int Message::monospaceMaxWidth() const { + const auto fromText = hasVisibleText() + ? text().countMaxMonospaceWidth() + : 0; + const auto fromMedia = this->media() + ? this->media()->contributedMaxMonospaceWidth() + : 0; return st::msgPadding.left() - + (hasVisibleText() ? text().countMaxMonospaceWidth() : 0) + + std::max(fromText, fromMedia) + st::msgPadding.right(); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_document.cpp index cc8ad9f416..4d94176a66 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_document.cpp @@ -1599,35 +1599,51 @@ 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); + const auto applySkipBlock = [&](Ui::Text::String &caption) { const auto skip = last ? _parent->skipBlockWidth() : 0; if (skip) { - captioned->caption.updateSkipBlock( + caption.updateSkipBlock( _parent->skipBlockWidth(), _parent->skipBlockHeight()); } else { - captioned->caption.removeSkipBlock(); + caption.removeSkipBlock(); } - } else if (now) { - RemoveComponents(HistoryDocumentCaptioned::Bit()); + }; + if (const auto now = Get()) { + applySkipBlock(now->caption); + return; } + auto caption = createCaption(); + if (caption.isEmpty()) { + return; + } + AddComponents(HistoryDocumentCaptioned::Bit()); + const auto captioned = Get(); + captioned->caption = std::move(caption); + applySkipBlock(captioned->caption); +} + +int Document::widenGroupingMaxWidth(int current, bool last) { + refreshCaption(last); + const auto captioned = Get(); + if (!captioned) { + return current; + } + const auto &caption = captioned->caption; + const auto padding = st::msgPadding.left() + st::msgPadding.right(); + const auto proseFull = padding + caption.maxWidth(); + const auto proseCapped = std::min(proseFull, int(st::msgMaxWidth)); + const auto monospaceRaw = caption.countMaxMonospaceWidth(); + const auto monospaceFull = monospaceRaw + ? (padding + monospaceRaw) + : 0; + return std::max({ current, proseCapped, monospaceFull }); } QSize Document::sizeForGroupingOptimal(int maxWidth, bool last) const { const auto thumbed = Get(); const auto &st = (thumbed ? st::msgFileThumbLayoutGrouped : st::msgFileLayoutGrouped); auto height = st.padding.top() + st.thumbSize + st.padding.bottom(); - - const_cast(this)->refreshCaption(last); - if (const auto captioned = Get()) { auto captionw = maxWidth - st::msgPadding.left() @@ -1763,6 +1779,13 @@ Ui::Text::String Document::createCaption() const { return File::createCaption(_realParent); } +int Document::contributedMaxMonospaceWidth() const { + if (const auto captioned = Get()) { + return captioned->caption.countMaxMonospaceWidth(); + } + return 0; +} + void Document::TooltipFilename::setElided(bool value) { if (_elided != value) { _elided = value; diff --git a/Telegram/SourceFiles/history/view/media/history_view_document.h b/Telegram/SourceFiles/history/view/media/history_view_document.h index 806eed138d..309a694e7b 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_document.h +++ b/Telegram/SourceFiles/history/view/media/history_view_document.h @@ -71,6 +71,8 @@ public: QSize sizeForGroupingOptimal(int maxWidth, bool last) const override; QSize sizeForGrouping(int width) const override; + int widenGroupingMaxWidth(int current, bool last) override; + int contributedMaxMonospaceWidth() const override; void drawGrouped( Painter &p, const PaintContext &context, diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.h b/Telegram/SourceFiles/history/view/media/history_view_media.h index bab5b2e50a..db1ed752b2 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media.h @@ -346,6 +346,14 @@ public: return 0; } + [[nodiscard]] virtual int contributedMaxMonospaceWidth() const { + return 0; + } + + virtual int widenGroupingMaxWidth(int current, bool last) { + return current; + } + // Sometimes click on media in message is overloaded by the message: // (for example it can open a link or a game instead of opening media) // But the overloading click handler should be used only when media 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 a165cb1366..34cad03775 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp @@ -146,6 +146,13 @@ QSize GroupedMedia::countOptimalSize() { media->initDimensions(); accumulate_max(maxWidth, media->maxWidth()); } + auto index = 0; + for (const auto &part : _parts) { + const auto last = (++index == _parts.size()); + accumulate_max( + maxWidth, + part.content->widenGroupingMaxWidth(maxWidth, last)); + } } auto index = 0; for (const auto &part : _parts) { @@ -893,6 +900,19 @@ bool GroupedMedia::enforceBubbleWidth() const { return _mode == Mode::Grid; } +int GroupedMedia::contributedMaxMonospaceWidth() const { + if (_mode != Mode::Column) { + return 0; + } + auto result = 0; + for (const auto &part : _parts) { + accumulate_max( + result, + part.content->contributedMaxMonospaceWidth()); + } + return result; +} + bool GroupedMedia::computeNeedBubble() const { Expects(_mode == Mode::Column || _captionItem.has_value()); diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.h b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.h index 5011c33709..7845c778ed 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.h @@ -99,6 +99,7 @@ public: } QRect groupItemRect(int index) const override; bool enforceBubbleWidth() const override; + int contributedMaxMonospaceWidth() const override; void stopAnimation() override; void checkAnimation() override;