diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index e2aafdc72d..b658e8fd89 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -290,6 +290,7 @@ SendFilesBox::Block::Block( not_null*> items, int from, int till, + const Ui::Text::MarkedContext &captionContext, Fn gifPaused, SendFilesWay way, Fn actionAllowed) @@ -309,6 +310,7 @@ SendFilesBox::Block::Block( parent.get(), st, my, + captionContext, way, [=](int index, Ui::AttachActionType type) { return actionAllowed((*_items)[from + index], type); @@ -332,7 +334,8 @@ SendFilesBox::Block::Block( _preview.reset(Ui::CreateChild( parent.get(), st, - first)); + first, + captionContext)); } } _preview->show(); @@ -530,6 +533,22 @@ bool SendFilesBox::Block::setSingleFileDisplayName( return true; } +bool SendFilesBox::Block::setSingleFileCaption( + int index, + const TextWithTags &caption) { + if (_isSingleMedia || index < _from || index >= _till) { + return false; + } + if (_isAlbum) { + const auto album = static_cast(_preview.get()); + album->setCaption(index - _from, caption); + return true; + } + const auto single = static_cast(_preview.get()); + single->setCaption(caption); + return true; +} + SendFilesBox::SendFilesBox( QWidget*, not_null controller, @@ -1138,12 +1157,16 @@ void SendFilesBox::pushBlock(int from, int till) { const auto gifPaused = [show = _show] { return show->paused(Window::GifPauseReason::Layer); }; + const auto captionContext = Core::TextContext({ + .session = &_show->session(), + }); _blocks.emplace_back( _inner.data(), _st, &_list.files, from, till, + captionContext, gifPaused, _sendWay.current(), [=](const Ui::PreparedFile &file, Ui::AttachActionType type) { diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index 5582f6ea2c..18d1fec84f 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -16,6 +16,10 @@ namespace style { struct ComposeControls; } // namespace style +namespace Ui::Text { +struct MarkedContext; +} // namespace Ui::Text + namespace Window { class SessionController; } // namespace Window @@ -153,6 +157,7 @@ private: not_null*> items, int from, int till, + const Ui::Text::MarkedContext &captionContext, Fn gifPaused, Ui::SendFilesWay way, Fn _preview; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_file_preview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_file_preview.cpp index 5ad8e15d18..862b6a4f4f 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_file_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_file_preview.cpp @@ -22,12 +22,26 @@ namespace Ui { AbstractSingleFilePreview::AbstractSingleFilePreview( QWidget *parent, const style::ComposeControls &st, - AttachControls::Type type) + AttachControls::Type type, + const Text::MarkedContext &captionContext) : AbstractSinglePreview(parent) , _st(st) , _type(type) +, _captionContext(captionContext) , _editMedia(this, _st.files.buttonFile) , _deleteMedia(this, _st.files.buttonFile) { + const auto repaint = _captionContext.repaint; + _captionContext.repaint = [=] { + if (repaint) { + repaint(); + } + const auto rect = captionRect(); + if (rect.isEmpty()) { + update(); + } else { + update(rect); + } + }; _editMedia->setIconOverride(&_st.files.buttonFileEdit); _deleteMedia->setIconOverride(&_st.files.buttonFileDelete); @@ -69,9 +83,25 @@ rpl::producer<> AbstractSingleFilePreview::clearCoverRequests() const { } void AbstractSingleFilePreview::setDisplayName(const QString &displayName) { - auto data = _data; - data.name = displayName; - setData(data); + _data.name = displayName; + updateTextWidthFor(_data); + updateDataGeometry(); + update(); +} + +void AbstractSingleFilePreview::setCaption(const TextWithTags &caption) { + auto marked = TextWithEntities{ + caption.text, + TextUtilities::ConvertTextTagsToEntities(caption.tags), + }; + marked = TextUtilities::SingleLine(marked); + _data.caption.setMarkedText( + st::defaultTextStyle, + marked, + kMarkupTextOptions, + _captionContext); + updateTextWidthFor(_data); + updateDataGeometry(); update(); } @@ -151,6 +181,23 @@ void AbstractSingleFilePreview::paintEvent(QPaintEvent *e) { width(), _data.statusText, _data.statusWidth); + if (!_data.caption.isEmpty()) { + p.setPen(_st.files.nameFg); + const auto captionTop = y + + st.thumbSize + + st::attachPreviewCaptionTopOffset; + _data.caption.draw(p, { + .position = { + x, + captionTop, + }, + .outerWidth = width(), + .availableWidth = _data.captionAvailableWidth, + .align = style::al_left, + .elisionLines = 1, + .elisionBreakEverywhere = true, + }); + } } void AbstractSingleFilePreview::resizeEvent(QResizeEvent *e) { @@ -167,7 +214,7 @@ void AbstractSingleFilePreview::resizeEvent(QResizeEvent *e) { _editMedia->moveToRight(right, top); } -bool AbstractSingleFilePreview::isThumbedLayout(Data &data) const { +bool AbstractSingleFilePreview::isThumbedLayout(const Data &data) const { return (!data.fileThumb.isNull() && !data.fileIsAudio); } @@ -187,6 +234,10 @@ void AbstractSingleFilePreview::updateTextWidthFor(Data &data) { - _st.files.buttonFile.width * buttonsCount - st::sendBoxAlbumGroupEditInternalSkip * buttonsCount - st::sendBoxAlbumGroupSkipRight; + const auto availableCaptionWidth = st::sendMediaPreviewSize + - _st.files.buttonFile.width * buttonsCount + - st::sendBoxAlbumGroupEditInternalSkip * buttonsCount + - st::sendBoxAlbumGroupSkipRight; data.nameWidth = st::semiboldFont->width(data.name); if (data.nameWidth > availableFileWidth) { data.name = st::semiboldFont->elided( @@ -196,17 +247,44 @@ void AbstractSingleFilePreview::updateTextWidthFor(Data &data) { data.nameWidth = st::semiboldFont->width(data.name); } data.statusWidth = st::normalFont->width(data.statusText); + data.captionAvailableWidth = availableCaptionWidth; } -void AbstractSingleFilePreview::setData(const Data &data) { - _data = data; - - updateTextWidthFor(_data); - +void AbstractSingleFilePreview::updateDataGeometry() { const auto &st = !isThumbedLayout(_data) ? st::attachPreviewLayout : st::attachPreviewThumbLayout; - resize(width(), st.thumbSize); + const auto height = st.thumbSize + (_data.caption.isEmpty() + ? 0 + : (st::attachPreviewCaptionTopOffset + _data.caption.lineHeight())); + resize(width(), height); +} + +QRect AbstractSingleFilePreview::captionRect() const { + if (_data.caption.isEmpty()) { + return {}; + } + const auto w = width() + - st::boxPhotoPadding.left() + - st::boxPhotoPadding.right(); + const auto &st = !isThumbedLayout(_data) + ? st::attachPreviewLayout + : st::attachPreviewThumbLayout; + const auto x = (width() - w) / 2; + const auto captionLineHeight = _data.caption.lineHeight(); + const auto top = st.thumbSize + + st::attachPreviewCaptionTopOffset; + return QRect( + x, + top, + _data.captionAvailableWidth, + captionLineHeight) + st::attachPreviewCaptionRepaintMargin; +} + +void AbstractSingleFilePreview::setData(Data data) { + _data = std::move(data); + updateTextWidthFor(_data); + updateDataGeometry(); } } // namespace Ui diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_file_preview.h b/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_file_preview.h index 5fd830725a..aaae3e44a7 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_file_preview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_file_preview.h @@ -24,7 +24,8 @@ public: AbstractSingleFilePreview( QWidget *parent, const style::ComposeControls &st, - AttachControls::Type type); + AttachControls::Type type, + const Text::MarkedContext &captionContext); ~AbstractSingleFilePreview(); [[nodiscard]] rpl::producer<> deleteRequests() const override; @@ -33,31 +34,40 @@ public: [[nodiscard]] rpl::producer<> editCoverRequests() const override; [[nodiscard]] rpl::producer<> clearCoverRequests() const override; virtual void setDisplayName(const QString &displayName); + virtual void setCaption(const TextWithTags &caption); protected: struct Data { QPixmap fileThumb; QString name; QString statusText; + Text::String caption; int nameWidth = 0; int statusWidth = 0; + int captionAvailableWidth = 0; bool fileIsAudio = false; bool fileIsImage = false; }; void prepareThumbFor(Data &data, const QImage &preview); - bool isThumbedLayout(Data &data) const; + bool isThumbedLayout(const Data &data) const; + [[nodiscard]] const Text::MarkedContext &captionContext() const { + return _captionContext; + } - void setData(const Data &data); + void setData(Data data); private: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; void updateTextWidthFor(Data &data); + void updateDataGeometry(); + [[nodiscard]] QRect captionRect() const; const style::ComposeControls &_st; const AttachControls::Type _type; + Text::MarkedContext _captionContext; Data _data; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp index 28431418ad..176e30556a 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp @@ -37,10 +37,12 @@ AlbumPreview::AlbumPreview( QWidget *parent, const style::ComposeControls &st, gsl::span items, + const Text::MarkedContext &captionContext, SendFilesWay way, Fn actionAllowed) : RpWidget(parent) , _st(st) +, _captionContext(captionContext) , _sendWay(way) , _actionAllowed(std::move(actionAllowed)) , _dragTimer([=] { switchToDrag(); }) { @@ -62,6 +64,37 @@ void AlbumPreview::setSendWay(SendFilesWay way) { update(); } +void AlbumPreview::setCaption(int index, const TextWithTags &caption) { + if (index < 0 || index >= _thumbs.size()) { + return; + } + const auto realIndex = _order[index]; + const auto oldHeight = _thumbs[realIndex]->fileHeight(); + _thumbs[realIndex]->setCaption(caption); + const auto newHeight = _thumbs[realIndex]->fileHeight(); + if (oldHeight == newHeight) { + return; + } + const auto firstFileHeight = _thumbs.front()->fileHeight(); + _hasMixedFileHeights = ranges::any_of( + _thumbs, + [=](const auto &thumb) { + return thumb->fileHeight() != firstFileHeight; + }); + _filesHeight = ranges::accumulate(ranges::views::all( + _thumbs + ) | ranges::views::transform([](const auto &thumb) { + return thumb->fileHeight(); + }), 0) + (int(_thumbs.size()) - 1) * st::sendMediaRowSkip; + updateSize(); + updateFileRows(); +} + +int AlbumPreview::indexFromPoint(QPoint position) const { + const auto thumb = findThumb(position); + return thumb ? orderIndex(thumb) : -1; +} + void AlbumPreview::updateFileRows() { Expects(_order.size() == _thumbs.size()); @@ -148,9 +181,11 @@ void AlbumPreview::prepareThumbs(gsl::span items) { _thumbs.push_back(std::make_unique( _st, items[i], + _captionContext, layout[i], this, [=] { update(); }, + [=](QRect rect) { update(rect); }, [=] { changeThumbByIndex(orderIndex(thumbUnderCursor())); }, [=] { deleteThumbByIndex(orderIndex(thumbUnderCursor())); })); if (_thumbs.back()->isCompressedSticker()) { @@ -164,16 +199,17 @@ void AlbumPreview::prepareThumbs(gsl::span items) { return thumb->photoHeight(); }), 0) + (count - 1) * st::sendMediaRowSkip; - if (!_hasMixedFileHeights) { - _filesHeight = count * _thumbs.front()->fileHeight() - + (count - 1) * st::sendMediaRowSkip; - } else { - _filesHeight = ranges::accumulate(ranges::views::all( - _thumbs - ) | ranges::views::transform([](const auto &thumb) { - return thumb->fileHeight(); - }), 0) + (count - 1) * st::sendMediaRowSkip; - } + const auto firstFileHeight = _thumbs.front()->fileHeight(); + _hasMixedFileHeights = _hasMixedFileHeights || ranges::any_of( + _thumbs, + [=](const auto &thumb) { + return thumb->fileHeight() != firstFileHeight; + }); + _filesHeight = ranges::accumulate(ranges::views::all( + _thumbs + ) | ranges::views::transform([](const auto &thumb) { + return thumb->fileHeight(); + }), 0) + (count - 1) * st::sendMediaRowSkip; } int AlbumPreview::contentLeft() const { @@ -375,7 +411,7 @@ void AlbumPreview::paintFiles(Painter &p, QRect clip) const { const auto left = (st::boxWideWidth - st::sendMediaPreviewSize) / 2; const auto outerWidth = width(); if (!_hasMixedFileHeights) { - const auto fileHeight = st::attachPreviewThumbLayout.thumbSize + const auto fileHeight = _thumbs.front()->fileHeight() + st::sendMediaRowSkip; const auto bottom = clip.y() + clip.height(); const auto from = std::clamp( diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h index 9a740eb5bf..a7b26ad73c 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" #include "ui/chat/attach/attach_send_files_way.h" +#include "ui/text/text.h" #include "base/timer.h" namespace style { @@ -28,11 +29,14 @@ public: QWidget *parent, const style::ComposeControls &st, gsl::span items, + const Text::MarkedContext &captionContext, SendFilesWay way, Fn actionAllowed); ~AlbumPreview(); void setSendWay(SendFilesWay way); + void setCaption(int index, const TextWithTags &caption); + [[nodiscard]] int indexFromPoint(QPoint position) const; [[nodiscard]] base::flat_set collectSpoileredIndices(); [[nodiscard]] bool canHaveSpoiler(int index) const; @@ -103,6 +107,7 @@ private: void showContextMenu(not_null thumb, QPoint position); const style::ComposeControls &_st; + const Text::MarkedContext _captionContext; SendFilesWay _sendWay; Fn _actionAllowed; style::cursor _cursor = style::cur_default; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.cpp index 562ae2d442..df101b8cc1 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/chat/attach/attach_prepare.h" #include "ui/image/image_prepare.h" #include "ui/text/format_values.h" +#include "ui/text/text_utilities.h" #include "ui/widgets/buttons.h" #include "ui/effects/spoiler_mess.h" #include "ui/ui_utility.h" @@ -28,9 +29,11 @@ namespace Ui { AlbumThumbnail::AlbumThumbnail( const style::ComposeControls &st, const PreparedFile &file, + const Text::MarkedContext &captionContext, const GroupMediaLayout &layout, QWidget *parent, Fn repaint, + Fn repaintRect, Fn editCallback, Fn deleteCallback) : _st(st) @@ -40,7 +43,8 @@ AlbumThumbnail::AlbumThumbnail( , _isPhoto(file.type == PreparedFile::Type::Photo) , _isVideo(file.type == PreparedFile::Type::Video) , _isCompressedSticker(Core::IsMimeSticker(file.information->filemime)) -, _repaint(std::move(repaint)) { +, _repaint(std::move(repaint)) +, _repaintRect(std::move(repaintRect)) { Expects(!_fullPreview.isNull()); moveToLayout(layout); @@ -82,13 +86,22 @@ AlbumThumbnail::AlbumThumbnail( - st::sendBoxAlbumGroupButtonFile.width * 2 - st::sendBoxAlbumGroupEditInternalSkip * 2 - st::sendBoxAlbumGroupSkipRight; + const auto availableCaptionWidth = st::sendMediaPreviewSize + - st::sendBoxAlbumGroupButtonFile.width * 2 + - st::sendBoxAlbumGroupEditInternalSkip * 2 + - st::sendBoxAlbumGroupSkipRight; + _captionAvailableWidth = availableCaptionWidth; const auto filepath = file.path; if (filepath.isEmpty()) { - _name = "image.png"; + _name = file.displayName.isEmpty() + ? "image.png" + : file.displayName; _status = FormatImageSizeText(file.originalDimensions); } else { auto fileinfo = QFileInfo(filepath); - _name = fileinfo.fileName(); + _name = file.displayName.isEmpty() + ? fileinfo.fileName() + : file.displayName; _status = FormatSizeText(fileinfo.size()); } _nameWidth = st::semiboldFont->width(_name); @@ -100,6 +113,29 @@ AlbumThumbnail::AlbumThumbnail( _nameWidth = st::semiboldFont->width(_name); } _statusWidth = st::normalFont->width(_status); + auto caption = TextWithEntities{ + file.caption.text, + TextUtilities::ConvertTextTagsToEntities(file.caption.tags), + }; + caption = TextUtilities::SingleLine(caption); + auto context = captionContext; + const auto repaintCaption = context.repaint; + context.repaint = [=] { + if (repaintCaption) { + repaintCaption(); + } + if (!_lastRectOfCaption.isEmpty() && _repaintRect) { + _repaintRect(_lastRectOfCaption); + } else { + _repaint(); + } + }; + _captionContext = context; + _caption.setMarkedText( + st::defaultTextStyle, + caption, + kMarkupTextOptions, + _captionContext); _editMedia.create(parent, _st.files.buttonFile); _deleteMedia.create(parent, _st.files.buttonFile); @@ -126,6 +162,20 @@ void AlbumThumbnail::setSpoiler(bool spoiler) { _repaint(); } +void AlbumThumbnail::setCaption(const TextWithTags &caption) { + auto marked = TextWithEntities{ + caption.text, + TextUtilities::ConvertTextTagsToEntities(caption.tags), + }; + marked = TextUtilities::SingleLine(marked); + _caption.setMarkedText( + st::defaultTextStyle, + marked, + kMarkupTextOptions, + _captionContext); + _repaint(); +} + bool AlbumThumbnail::hasSpoiler() const { return _spoiler != nullptr; } @@ -186,7 +236,9 @@ int AlbumThumbnail::photoHeight() const { int AlbumThumbnail::fileHeight() const { return _isCompressedSticker ? photoHeight() - : st::attachPreviewThumbLayout.thumbSize; + : st::attachPreviewThumbLayout.thumbSize + (_caption.isEmpty() + ? 0 + : (st::attachPreviewCaptionTopOffset + _caption.lineHeight())); } bool AlbumThumbnail::isCompressedSticker() const { @@ -497,6 +549,28 @@ void AlbumThumbnail::paintFile( outerWidth, _status, _statusWidth); + if (!_caption.isEmpty()) { + p.setPen(_st.files.nameFg); + const auto captionLineHeight = _caption.lineHeight(); + const auto captionTop = top + + st.thumbSize + + st::attachPreviewCaptionTopOffset; + _lastRectOfCaption = QRect( + left, + captionTop, + _captionAvailableWidth, + captionLineHeight) + st::attachPreviewCaptionRepaintMargin; + _caption.draw(p, { + .position = { left, captionTop }, + .outerWidth = outerWidth, + .availableWidth = _captionAvailableWidth, + .align = style::al_left, + .elisionLines = 1, + .elisionBreakEverywhere = true, + }); + } else { + _lastRectOfCaption = {}; + } _lastRectOfModify = QRect( QPoint(left, top), diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.h b/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.h index 209f864cde..d10b77723c 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.h @@ -29,9 +29,11 @@ public: AlbumThumbnail( const style::ComposeControls &st, const PreparedFile &file, + const Text::MarkedContext &captionContext, const GroupMediaLayout &layout, QWidget *parent, Fn repaint, + Fn repaintRect, Fn editCallback, Fn deleteCallback); @@ -40,6 +42,7 @@ public: void resetLayoutAnimation(); void setSpoiler(bool spoiler); + void setCaption(const TextWithTags &caption); [[nodiscard]] bool hasSpoiler() const; [[nodiscard]] int photoHeight() const; @@ -101,8 +104,11 @@ private: QPixmap _fileThumb; QString _name; QString _status; + Text::String _caption; + Text::MarkedContext _captionContext; int _nameWidth = 0; int _statusWidth = 0; + int _captionAvailableWidth = 0; float64 _suggestedMove = 0.; Animations::Simple _suggestedMoveAnimation; int _lastShrinkValue = 0; @@ -112,9 +118,11 @@ private: std::unique_ptr _spoiler; QImage _cornerCache; Fn _repaint; + Fn _repaintRect; QRect _lastRectOfModify; QRect _lastRectOfButtons; + QRect _lastRectOfCaption; object_ptr _editMedia = { nullptr }; object_ptr _deleteMedia = { nullptr }; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_item_single_file_preview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_item_single_file_preview.cpp index 0dfff6b52c..8e60e74bfe 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_item_single_file_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_item_single_file_preview.cpp @@ -40,7 +40,7 @@ ItemSingleFilePreview::ItemSingleFilePreview( const style::ComposeControls &st, not_null item, AttachControls::Type type) -: AbstractSingleFilePreview(parent, st, CheckControlsType(item, type)) { +: AbstractSingleFilePreview(parent, st, CheckControlsType(item, type), {}) { const auto media = item->media(); Assert(media != nullptr); const auto document = media->document(); @@ -109,7 +109,7 @@ void ItemSingleFilePreview::preparePreview(not_null document) { } data.statusText = FormatSizeText(document->size); - setData(data); + setData(std::move(data)); } } // namespace Ui diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h index 5eddcf8ad1..bee70e6421 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h @@ -80,6 +80,7 @@ struct PreparedFile { QString path; QString displayName; + TextWithTags caption; QByteArray content; int64 size = 0; std::unique_ptr information; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.cpp index c7ad3d0bef..0eef6b959a 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/chat/attach/attach_prepare.h" #include "ui/text/format_song_name.h" #include "ui/text/format_values.h" +#include "ui/text/text_utilities.h" #include "ui/ui_utility.h" #include "core/mime_type.h" #include "styles/style_chat.h" @@ -22,15 +23,28 @@ SingleFilePreview::SingleFilePreview( QWidget *parent, const style::ComposeControls &st, const PreparedFile &file, + const Text::MarkedContext &captionContext, AttachControls::Type type) -: AbstractSingleFilePreview(parent, st, type) { +: AbstractSingleFilePreview(parent, st, type, captionContext) { preparePreview(file); } +SingleFilePreview::SingleFilePreview( + QWidget *parent, + const style::ComposeControls &st, + const PreparedFile &file, + AttachControls::Type type) +: SingleFilePreview(parent, st, file, {}, type) { +} + void SingleFilePreview::setDisplayName(const QString &displayName) { AbstractSingleFilePreview::setDisplayName(displayName); } +void SingleFilePreview::setCaption(const TextWithTags &caption) { + AbstractSingleFilePreview::setCaption(caption); +} + void SingleFilePreview::preparePreview(const PreparedFile &file) { AbstractSingleFilePreview::Data data; @@ -82,8 +96,18 @@ void SingleFilePreview::preparePreview(const PreparedFile &file) { .string(); data.statusText = FormatSizeText(fileinfo.size()); } + auto caption = TextWithEntities{ + file.caption.text, + TextUtilities::ConvertTextTagsToEntities(file.caption.tags), + }; + caption = TextUtilities::SingleLine(caption); + data.caption.setMarkedText( + st::defaultTextStyle, + caption, + kMarkupTextOptions, + captionContext()); - setData(data); + setData(std::move(data)); } } // namespace Ui diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.h b/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.h index 4fc1f3b53a..a388c0473e 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.h @@ -15,12 +15,19 @@ struct PreparedFile; class SingleFilePreview final : public AbstractSingleFilePreview { public: + SingleFilePreview( + QWidget *parent, + const style::ComposeControls &st, + const PreparedFile &file, + const Text::MarkedContext &captionContext, + AttachControls::Type type = AttachControls::Type::Full); SingleFilePreview( QWidget *parent, const style::ComposeControls &st, const PreparedFile &file, AttachControls::Type type = AttachControls::Type::Full); void setDisplayName(const QString &displayName) override; + void setCaption(const TextWithTags &caption) override; private: void preparePreview(const PreparedFile &file); diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 6a42ed7b89..e3ff85c83f 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -534,6 +534,8 @@ attachPreviewThumbLayout: HistoryFileLayout { thumbSize: 64px; thumbSkip: 10px; } +attachPreviewCaptionTopOffset: 6px; +attachPreviewCaptionRepaintMargin: margins(0px, 2px, 0px, 2px); msgFileMinWidth: 268px; msgFileTopMinus: 6px;