From 5bee6310c0508bacd3fb992a9b1a870cc5145b59 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 13 Dec 2022 16:11:52 +0400 Subject: [PATCH] Allow sending media with spoilers. --- Telegram/Resources/langs/lang.strings | 3 + Telegram/SourceFiles/api/api_editing.cpp | 2 +- Telegram/SourceFiles/api/api_media.cpp | 25 +-- Telegram/SourceFiles/api/api_media.h | 4 +- Telegram/SourceFiles/api/api_sending.cpp | 8 +- Telegram/SourceFiles/apiwrap.cpp | 13 +- Telegram/SourceFiles/boxes/send_files_box.cpp | 48 ++++-- Telegram/SourceFiles/boxes/send_files_box.h | 4 +- .../chat_helpers/stickers_dice_pack.cpp | 3 +- .../SourceFiles/data/data_media_types.cpp | 12 ++ Telegram/SourceFiles/data/data_media_types.h | 3 + .../history/view/media/history_view_gif.cpp | 17 +- .../passport/passport_form_controller.cpp | 1 + .../SourceFiles/storage/localimageloader.cpp | 9 +- .../SourceFiles/storage/localimageloader.h | 4 + .../attach_abstract_single_media_preview.cpp | 118 +++++++++++-- .../attach_abstract_single_media_preview.h | 27 ++- .../ui/chat/attach/attach_album_preview.cpp | 62 +++++-- .../ui/chat/attach/attach_album_preview.h | 9 +- .../ui/chat/attach/attach_album_thumbnail.cpp | 158 +++++++++++++----- .../ui/chat/attach/attach_album_thumbnail.h | 11 ++ .../ui/chat/attach/attach_prepare.cpp | 24 +++ .../ui/chat/attach/attach_prepare.h | 6 + .../attach/attach_single_media_preview.cpp | 4 +- .../chat/attach/attach_single_media_preview.h | 1 + 25 files changed, 465 insertions(+), 111 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index efb865661..b15e8f2ed 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2327,6 +2327,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_context_animated_reactions_many#one" = "Reactions contain emoji from **{count} pack**."; "lng_context_animated_reactions_many#other" = "Reactions contain emoji from **{count} packs**."; +"lng_context_spoiler_effect" = "Spoiler Effect"; +"lng_context_disable_spoiler" = "Disable Spoiler Effect"; + "lng_downloads_section" = "Downloads"; "lng_downloads_view_in_chat" = "View in chat"; "lng_downloads_view_in_section" = "View in downloads"; diff --git a/Telegram/SourceFiles/api/api_editing.cpp b/Telegram/SourceFiles/api/api_editing.cpp index 2c9325ef8..70dbc6a45 100644 --- a/Telegram/SourceFiles/api/api_editing.cpp +++ b/Telegram/SourceFiles/api/api_editing.cpp @@ -206,7 +206,7 @@ void EditMessageWithUploadedPhoto( EditMessageWithUploadedMedia( item, options, - PrepareUploadedPhoto(std::move(info))); + PrepareUploadedPhoto(item, std::move(info))); } mtpRequestId EditCaption( diff --git a/Telegram/SourceFiles/api/api_media.cpp b/Telegram/SourceFiles/api/api_media.cpp index b778aa59b..7dd916140 100644 --- a/Telegram/SourceFiles/api/api_media.cpp +++ b/Telegram/SourceFiles/api/api_media.cpp @@ -75,10 +75,14 @@ MTPVector ComposeSendingDocumentAttributes( } // namespace -MTPInputMedia PrepareUploadedPhoto(RemoteFileInfo info) { - const auto flags = info.attachedStickers.empty() - ? MTPDinputMediaUploadedPhoto::Flags(0) - : MTPDinputMediaUploadedPhoto::Flag::f_stickers; +MTPInputMedia PrepareUploadedPhoto( + not_null item, + RemoteFileInfo info) { + using Flag = MTPDinputMediaUploadedPhoto::Flag; + const auto spoiler = item->media() + && item->media()->hasSpoiler(); + const auto flags = (spoiler ? Flag::f_spoiler : Flag()) + | (info.attachedStickers.empty() ? Flag() : Flag::f_stickers); return MTP_inputMediaUploadedPhoto( MTP_flags(flags), info.file, @@ -93,12 +97,13 @@ MTPInputMedia PrepareUploadedDocument( if (!item || !item->media() || !item->media()->document()) { return MTP_inputMediaEmpty(); } - const auto emptyFlag = MTPDinputMediaUploadedDocument::Flags(0); - using DocFlags = MTPDinputMediaUploadedDocument::Flag; - const auto flags = emptyFlag - | (info.thumb ? DocFlags::f_thumb : emptyFlag) - | (item->groupId() ? DocFlags::f_nosound_video : emptyFlag) - | (info.attachedStickers.empty() ? DocFlags::f_stickers : emptyFlag); + using Flag = MTPDinputMediaUploadedDocument::Flag; + const auto spoiler = item->media() + && item->media()->hasSpoiler(); + const auto flags = (spoiler ? Flag::f_spoiler : Flag()) + | (info.thumb ? Flag::f_thumb : Flag()) + | (item->groupId() ? Flag::f_nosound_video : Flag()) + | (info.attachedStickers.empty() ? Flag::f_stickers : Flag()); const auto document = item->media()->document(); return MTP_inputMediaUploadedDocument( MTP_flags(flags), diff --git a/Telegram/SourceFiles/api/api_media.h b/Telegram/SourceFiles/api/api_media.h index b9f744856..87912e9b7 100644 --- a/Telegram/SourceFiles/api/api_media.h +++ b/Telegram/SourceFiles/api/api_media.h @@ -13,7 +13,9 @@ namespace Api { struct RemoteFileInfo; -MTPInputMedia PrepareUploadedPhoto(RemoteFileInfo info); +MTPInputMedia PrepareUploadedPhoto( + not_null item, + RemoteFileInfo info); MTPInputMedia PrepareUploadedDocument( not_null item, diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index b2004f70b..f00431f64 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -441,13 +441,17 @@ void SendConfirmedFile( const auto media = MTPMessageMedia([&] { if (file->type == SendMediaType::Photo) { + using Flag = MTPDmessageMediaPhoto::Flag; return MTP_messageMediaPhoto( - MTP_flags(MTPDmessageMediaPhoto::Flag::f_photo), + MTP_flags(Flag::f_photo + | (file->spoiler ? Flag::f_spoiler : Flag())), file->photo, MTPint()); } else if (file->type == SendMediaType::File) { + using Flag = MTPDmessageMediaDocument::Flag; return MTP_messageMediaDocument( - MTP_flags(MTPDmessageMediaDocument::Flag::f_document), + MTP_flags(Flag::f_document + | (file->spoiler ? Flag::f_spoiler : Flag())), file->document, MTPint()); } else if (file->type == SendMediaType::Audio) { diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 8ac060deb..d406e5330 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -3365,7 +3365,8 @@ void ApiWrap::editMedia( std::move(file.information), type, to, - caption)); + caption, + file.spoiler)); } void ApiWrap::sendFiles( @@ -3406,6 +3407,7 @@ void ApiWrap::sendFiles( uploadWithType, to, caption, + file.spoiler, album)); caption = TextWithTags(); } @@ -3425,14 +3427,17 @@ void ApiWrap::sendFile( const SendAction &action) { const auto to = fileLoadTaskOptions(action); auto caption = TextWithTags(); + const auto spoiler = false; + const auto information = nullptr; _fileLoader->addTask(std::make_unique( &session(), QString(), fileContent, - nullptr, + information, type, to, - caption)); + caption, + spoiler)); } void ApiWrap::sendUploadedPhoto( @@ -3440,7 +3445,7 @@ void ApiWrap::sendUploadedPhoto( Api::RemoteFileInfo info, Api::SendOptions options) { if (const auto item = _session->data().message(localId)) { - const auto media = Api::PrepareUploadedPhoto(std::move(info)); + const auto media = Api::PrepareUploadedPhoto(item, std::move(info)); if (const auto groupId = item->groupId()) { uploadAlbumMedia(item, groupId, media); } else { diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 3c0da6955..c11928fa3 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -215,19 +215,35 @@ rpl::producer SendFilesBox::Block::itemModifyRequest() const { void SendFilesBox::Block::setSendWay(Ui::SendFilesWay way) { if (!_isAlbum) { + if (_isSingleMedia) { + const auto media = static_cast( + _preview.get()); + media->setSendWay(way); + } return; } - applyAlbumOrder(); + applyChanges(); const auto album = static_cast(_preview.get()); album->setSendWay(way); } -void SendFilesBox::Block::applyAlbumOrder() { +void SendFilesBox::Block::applyChanges() { if (!_isAlbum) { + if (_isSingleMedia) { + const auto media = static_cast( + _preview.get()); + (*_items)[_from].spoiler = media->hasSpoiler(); + } return; } const auto album = static_cast(_preview.get()); const auto order = album->takeOrder(); + const auto spoilered = album->collectSpoileredIndices(); + const auto guard = gsl::finally([&] { + for (auto i = 0, count = int(order.size()); i != count; ++i) { + (*_items)[_from + i].spoiler = spoilered.contains(i); + } + }); const auto isIdentity = [&] { for (auto i = 0, count = int(order.size()); i != count; ++i) { if (order[i] != i) { @@ -385,19 +401,25 @@ void SendFilesBox::setupDragArea() { areas.photo->setDroppedCallback(droppedCallback(true)); } -void SendFilesBox::refreshAllAfterChanges(int fromItem) { +void SendFilesBox::refreshAllAfterChanges(int fromItem, Fn perform) { auto fromBlock = 0; for (auto count = int(_blocks.size()); fromBlock != count; ++fromBlock) { if (_blocks[fromBlock].tillIndex() >= fromItem) { break; } } + for (auto index = fromBlock; index < _blocks.size(); ++index) { + _blocks[index].applyChanges(); + } + if (perform) { + perform(); + } + generatePreviewFrom(fromBlock); { auto sendWay = _sendWay.current(); sendWay.setHasCompressedStickers(_list.hasSticker()); _sendWay = sendWay; } - generatePreviewFrom(fromBlock); _inner->resizeToWidth(st::boxWideWidth); refreshControls(); captionResized(); @@ -489,11 +511,7 @@ void SendFilesBox::generatePreviewFrom(int fromBlock) { using Type = Ui::PreparedFile::Type; - const auto eraseFrom = _blocks.begin() + fromBlock; - for (auto i = eraseFrom; i != _blocks.end(); ++i) { - i->applyAlbumOrder(); - } - _blocks.erase(eraseFrom, _blocks.end()); + _blocks.erase(_blocks.begin() + fromBlock, _blocks.end()); const auto fromItem = _blocks.empty() ? 0 : _blocks.back().tillIndex(); Assert(fromItem <= _list.files.size()); @@ -559,8 +577,9 @@ void SendFilesBox::pushBlock(int from, int till) { closeBox(); return; } - _list.files.erase(_list.files.begin() + index); - refreshAllAfterChanges(from); + refreshAllAfterChanges(index, [&] { + _list.files.erase(_list.files.begin() + index); + }); }); }, widget->lifetime()); @@ -571,8 +590,9 @@ void SendFilesBox::pushBlock(int from, int till) { if (list.files.empty()) { return; } - _list.files[index] = std::move(list.files.front()); - refreshAllAfterChanges(from); + refreshAllAfterChanges(from, [&] { + _list.files[index] = std::move(list.files.front()); + }); }; const auto checkResult = [=](const Ui::PreparedList &list) { if (_sendLimit != SendLimit::One) { @@ -1076,7 +1096,7 @@ void SendFilesBox::send( } for (auto &block : _blocks) { - block.applyAlbumOrder(); + block.applyChanges(); } Storage::ApplyModifications(_list); diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index 0d336832e..480b946a3 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -106,7 +106,7 @@ private: [[nodiscard]] rpl::producer itemModifyRequest() const; void setSendWay(Ui::SendFilesWay way); - void applyAlbumOrder(); + void applyChanges(); private: base::unique_qptr _preview; @@ -152,7 +152,7 @@ private: void pushBlock(int from, int till); void openDialogToAddFileToAlbum(); - void refreshAllAfterChanges(int fromItem); + void refreshAllAfterChanges(int fromItem, Fn perform = nullptr); void enqueueNextPrepare(); void addPreparedAsyncFile(Ui::PreparedFile &&file); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp b/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp index 3b5c66fd7..fed572b75 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp @@ -129,7 +129,8 @@ void DicePack::generateLocal(int index, const QString &name) { nullptr, SendMediaType::File, FileLoadTo(0, {}, 0, 0, 0), - {}); + {}, + false); task.process({ .generateGoodThumbnail = false }); const auto result = task.peekResult(); Assert(result != nullptr); diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index cc878a6c7..eb0488cb4 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -446,6 +446,10 @@ QString Media::errorTextForForward(not_null peer) const { return QString(); } +bool Media::hasSpoiler() const { + return false; +} + bool Media::consumeMessageText(const TextWithEntities &text) { return false; } @@ -663,6 +667,10 @@ QString MediaPhoto::errorTextForForward(not_null peer) const { ).value_or(QString()); } +bool MediaPhoto::hasSpoiler() const { + return _spoiler; +} + bool MediaPhoto::updateInlineResultMedia(const MTPMessageMedia &media) { if (media.type() != mtpc_messageMediaPhoto) { return false; @@ -1037,6 +1045,10 @@ QString MediaFile::errorTextForForward(not_null peer) const { return QString(); } +bool MediaFile::hasSpoiler() const { + return _spoiler; +} + bool MediaFile::updateInlineResultMedia(const MTPMessageMedia &media) { if (media.type() != mtpc_messageMediaDocument) { return false; diff --git a/Telegram/SourceFiles/data/data_media_types.h b/Telegram/SourceFiles/data/data_media_types.h index 0b612a799..1b69d28f7 100644 --- a/Telegram/SourceFiles/data/data_media_types.h +++ b/Telegram/SourceFiles/data/data_media_types.h @@ -129,6 +129,7 @@ public: virtual bool dropForwardedInfo() const; virtual bool forceForwardedInfo() const; virtual QString errorTextForForward(not_null peer) const; + [[nodiscard]] virtual bool hasSpoiler() const; [[nodiscard]] virtual bool consumeMessageText( const TextWithEntities &text); @@ -190,6 +191,7 @@ public: bool allowsEditCaption() const override; bool allowsEditMedia() const override; QString errorTextForForward(not_null peer) const override; + bool hasSpoiler() const override; bool updateInlineResultMedia(const MTPMessageMedia &media) override; bool updateSentMedia(const MTPMessageMedia &media) override; @@ -233,6 +235,7 @@ public: bool forwardedBecomesUnread() const override; bool dropForwardedInfo() const override; QString errorTextForForward(not_null peer) const override; + bool hasSpoiler() const override; bool updateInlineResultMedia(const MTPMessageMedia &media) override; bool updateSentMedia(const MTPMessageMedia &media) override; diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 7db685895..e1a267e4c 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -834,12 +834,27 @@ void Gif::validateSpoilerImageCache( && _spoiler->backgroundRounding == rounding) { return; } + const auto normal = _dataMedia->thumbnail(); + auto container = std::optional(); + const auto downscale = [&](Image *image) { + if (!image || (image->width() <= 40 && image->height() <= 40)) { + return image; + } + container.emplace(image->original().scaled( + { 40, 40 }, + Qt::KeepAspectRatio, + Qt::SmoothTransformation)); + return &*container; + }; + const auto videothumb = _videoThumbnailFrame.get(); + const auto embedded = _dataMedia->thumbnailInline(); + const auto blurred = embedded ? embedded : downscale(normal); _spoiler->background = Images::Round( PrepareWithBlurredBackground( outer, ::Media::Streaming::ExpandDecision(), nullptr, - _dataMedia->thumbnailInline()), + blurred), MediaRoundingMask(rounding)); _spoiler->backgroundRounding = rounding; } diff --git a/Telegram/SourceFiles/passport/passport_form_controller.cpp b/Telegram/SourceFiles/passport/passport_form_controller.cpp index 3b3e871a8..47df675c7 100644 --- a/Telegram/SourceFiles/passport/passport_form_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_form_controller.cpp @@ -1588,6 +1588,7 @@ void FormController::uploadEncryptedFile( file.uploadData->fileId, FileLoadTo(PeerId(), Api::SendOptions(), MsgId(), MsgId(), MsgId()), TextWithTags(), + false, std::shared_ptr(nullptr)); prepared->type = SendMediaType::Secure; prepared->content = QByteArray::fromRawData( diff --git a/Telegram/SourceFiles/storage/localimageloader.cpp b/Telegram/SourceFiles/storage/localimageloader.cpp index 5ccaec59a..de870d7f4 100644 --- a/Telegram/SourceFiles/storage/localimageloader.cpp +++ b/Telegram/SourceFiles/storage/localimageloader.cpp @@ -488,12 +488,14 @@ FileLoadResult::FileLoadResult( uint64 id, const FileLoadTo &to, const TextWithTags &caption, + bool spoiler, std::shared_ptr album) : taskId(taskId) , id(id) , to(to) , album(std::move(album)) -, caption(caption) { +, caption(caption) +, spoiler(spoiler) { } void FileLoadResult::setFileData(const QByteArray &filedata) { @@ -530,6 +532,7 @@ FileLoadTask::FileLoadTask( SendMediaType type, const FileLoadTo &to, const TextWithTags &caption, + bool spoiler, std::shared_ptr album) : _id(base::RandomValue()) , _session(session) @@ -540,7 +543,8 @@ FileLoadTask::FileLoadTask( , _content(content) , _information(std::move(information)) , _type(type) -, _caption(caption) { +, _caption(caption) +, _spoiler(spoiler) { Expects(to.options.scheduled || !to.replaceMediaOf || IsServerMsgId(to.replaceMediaOf)); @@ -736,6 +740,7 @@ void FileLoadTask::process(Args &&args) { _id, _to, _caption, + _spoiler, _album); QString filename, filemime; diff --git a/Telegram/SourceFiles/storage/localimageloader.h b/Telegram/SourceFiles/storage/localimageloader.h index d68ee45f9..365ea8112 100644 --- a/Telegram/SourceFiles/storage/localimageloader.h +++ b/Telegram/SourceFiles/storage/localimageloader.h @@ -224,6 +224,7 @@ struct FileLoadResult { uint64 id, const FileLoadTo &to, const TextWithTags &caption, + bool spoiler, std::shared_ptr album); TaskId taskId; @@ -256,6 +257,7 @@ struct FileLoadResult { PreparedPhotoThumbs photoThumbs; TextWithTags caption; + bool spoiler = false; std::vector attachedStickers; @@ -285,6 +287,7 @@ public: SendMediaType type, const FileLoadTo &to, const TextWithTags &caption, + bool spoiler, std::shared_ptr album = nullptr); FileLoadTask( not_null session, @@ -343,6 +346,7 @@ private: VoiceWaveform _waveform; SendMediaType _type; TextWithTags _caption; + bool _spoiler = false; std::shared_ptr _result; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_media_preview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_media_preview.cpp index dccd8874d..5898a5bf2 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_media_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_media_preview.cpp @@ -9,12 +9,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "editor/photo_editor_common.h" #include "ui/chat/attach/attach_controls.h" +#include "ui/chat/attach/attach_prepare.h" #include "ui/image/image_prepare.h" -#include "ui/widgets/buttons.h" +#include "ui/effects/spoiler_mess.h" +#include "ui/widgets/popup_menu.h" #include "ui/painter.h" +#include "lang/lang_keys.h" #include "styles/style_boxes.h" #include "styles/style_chat.h" #include "styles/style_layers.h" +#include "styles/style_menu_icons.h" namespace Ui { namespace { @@ -29,7 +33,6 @@ AbstractSingleMediaPreview::AbstractSingleMediaPreview( : AbstractSinglePreview(parent) , _minThumbH(st::sendBoxAlbumGroupSize.height() + st::sendBoxAlbumGroupSkipTop * 2) -, _photoEditorButton(base::make_unique_q(this)) , _controls(base::make_unique_q(this, type)) { } @@ -44,7 +47,25 @@ rpl::producer<> AbstractSingleMediaPreview::editRequests() const { } rpl::producer<> AbstractSingleMediaPreview::modifyRequests() const { - return _photoEditorButton->clicks() | rpl::to_empty; + return _photoEditorRequests.events(); +} + +void AbstractSingleMediaPreview::setSendWay(SendFilesWay way) { + if (_sendWay != way) { + _sendWay = way; + } + update(); +} + +void AbstractSingleMediaPreview::setSpoiler(bool spoiler) { + _spoiler = spoiler + ? std::make_unique([=] { update(); }) + : nullptr; + update(); +} + +bool AbstractSingleMediaPreview::hasSpoiler() const { + return _spoiler != nullptr; } void AbstractSingleMediaPreview::preparePreview(QImage preview) { @@ -105,16 +126,17 @@ void AbstractSingleMediaPreview::preparePreview(QImage preview) { preview = Images::Opaque(std::move(preview)); _preview = PixmapFromImage(std::move(preview)); _preview.setDevicePixelRatio(style::DevicePixelRatio()); - - updatePhotoEditorButton(); + _previewBlurred = QPixmap(); resize(width(), std::max(_previewHeight, _minThumbH)); } -void AbstractSingleMediaPreview::updatePhotoEditorButton() { - _photoEditorButton->resize(_previewWidth, _previewHeight); - _photoEditorButton->moveToLeft(_previewLeft, _previewTop); - _photoEditorButton->setVisible(isPhoto()); +bool AbstractSingleMediaPreview::isOverPreview(QPoint position) const { + return QRect( + _previewLeft, + _previewTop, + _previewWidth, + _previewHeight).contains(position); } void AbstractSingleMediaPreview::resizeEvent(QResizeEvent *e) { @@ -127,6 +149,15 @@ void AbstractSingleMediaPreview::resizeEvent(QResizeEvent *e) { void AbstractSingleMediaPreview::paintEvent(QPaintEvent *e) { auto p = QPainter(this); + auto takenSpoiler = (drawBackground() || _sendWay.sendImagesAsPhotos()) + ? nullptr + : base::take(_spoiler); + const auto guard = gsl::finally([&] { + if (takenSpoiler) { + _spoiler = base::take(takenSpoiler); + } + }); + if (drawBackground()) { const auto &padding = st::boxPhotoPadding; if (_previewLeft > padding.left()) { @@ -154,10 +185,23 @@ void AbstractSingleMediaPreview::paintEvent(QPaintEvent *e) { st::confirmBg); } } - if (!tryPaintAnimation(p)) { - p.drawPixmap(_previewLeft, _previewTop, _preview); + + if (_spoiler && _previewBlurred.isNull()) { + _previewBlurred = BlurredPreviewFromPixmap(_preview, RectPart::None); } - if (_animated && !isAnimatedPreviewReady()) { + if (_spoiler || !tryPaintAnimation(p)) { + const auto &pixmap = _spoiler ? _previewBlurred : _preview; + const auto position = QPoint(_previewLeft, _previewTop); + p.drawPixmap(position, pixmap); + if (_spoiler) { + FillSpoilerRect( + p, + QRect(position, pixmap.size() / pixmap.devicePixelRatio()), + DefaultImageSpoiler().frame( + _spoiler->index(crl::now(), false))); + } + } + if (_animated && !isAnimatedPreviewReady() && !_spoiler) { const auto innerSize = st::msgFileLayout.thumbSize; auto inner = QRect( _previewLeft + (_previewWidth - innerSize) / 2, @@ -177,6 +221,56 @@ void AbstractSingleMediaPreview::paintEvent(QPaintEvent *e) { } } +void AbstractSingleMediaPreview::mousePressEvent(QMouseEvent *e) { + if (isOverPreview(e->pos())) { + _pressed = true; + } +} + +void AbstractSingleMediaPreview::mouseMoveEvent(QMouseEvent *e) { + applyCursor((isPhoto() && isOverPreview(e->pos())) + ? style::cur_pointer + : style::cur_default); +} + +void AbstractSingleMediaPreview::mouseReleaseEvent(QMouseEvent *e) { + if (base::take(_pressed) && isOverPreview(e->pos())) { + if (e->button() == Qt::RightButton) { + showContextMenu(e->globalPos()); + } else if (isPhoto()) { + _photoEditorRequests.fire({}); + } + } +} + +void AbstractSingleMediaPreview::applyCursor(style::cursor cursor) { + if (_cursor != cursor) { + _cursor = cursor; + setCursor(_cursor); + } +} + +void AbstractSingleMediaPreview::showContextMenu(QPoint position) { + if (!_sendWay.sendImagesAsPhotos()) { + return; + } + _menu = base::make_unique_q( + this, + st::popupMenuWithIcons); + + _menu->addAction(hasSpoiler() + ? tr::lng_context_disable_spoiler(tr::now) + : tr::lng_context_spoiler_effect(tr::now), [=] { + setSpoiler(!hasSpoiler()); + }, &st::menuIconCopy); + + if (_menu->empty()) { + _menu = nullptr; + } else { + _menu->popup(position); + } +} + int AbstractSingleMediaPreview::previewLeft() const { return _previewLeft; } diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_media_preview.h b/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_media_preview.h index 011eabe82..ffdd83d5b 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_media_preview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_abstract_single_media_preview.h @@ -9,27 +9,34 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/chat/attach/attach_abstract_single_preview.h" #include "ui/chat/attach/attach_controls.h" +#include "ui/chat/attach/attach_send_files_way.h" #include "ui/abstract_button.h" namespace Ui { +class PopupMenu; + class AbstractSingleMediaPreview : public AbstractSinglePreview { public: AbstractSingleMediaPreview(QWidget *parent, AttachControls::Type type); ~AbstractSingleMediaPreview(); + void setSendWay(SendFilesWay way); + [[nodiscard]] rpl::producer<> deleteRequests() const override; [[nodiscard]] rpl::producer<> editRequests() const override; [[nodiscard]] rpl::producer<> modifyRequests() const override; [[nodiscard]] bool isPhoto() const; + void setSpoiler(bool spoiler); + [[nodiscard]] bool hasSpoiler() const; + protected: virtual bool drawBackground() const = 0; virtual bool tryPaintAnimation(QPainter &p) = 0; virtual bool isAnimatedPreviewReady() const = 0; - void updatePhotoEditorButton(); void preparePreview(QImage preview); int previewLeft() const; @@ -42,17 +49,33 @@ protected: private: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + [[nodiscard]] bool isOverPreview(QPoint position) const; + void applyCursor(style::cursor cursor); + void showContextMenu(QPoint position); + + SendFilesWay _sendWay; bool _animated = false; QPixmap _preview; + QPixmap _previewBlurred; int _previewLeft = 0; int _previewTop = 0; int _previewWidth = 0; int _previewHeight = 0; + std::unique_ptr _spoiler; + const int _minThumbH; - const base::unique_qptr _photoEditorButton; const base::unique_qptr _controls; + rpl::event_stream<> _photoEditorRequests; + + style::cursor _cursor = style::cur_default; + bool _pressed = false; + + base::unique_qptr _menu; rpl::event_stream<> _modifyRequests; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp index 87f8e700b..00dcc182a 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp @@ -9,10 +9,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/chat/attach/attach_album_thumbnail.h" #include "ui/chat/attach/attach_prepare.h" +#include "ui/widgets/popup_menu.h" #include "ui/painter.h" +#include "lang/lang_keys.h" #include "styles/style_chat.h" #include "styles/style_boxes.h" #include "styles/style_layers.h" +#include "styles/style_menu_icons.h" #include @@ -61,6 +64,19 @@ void AlbumPreview::updateFileRows() { } } +base::flat_set AlbumPreview::collectSpoileredIndices() { + auto result = base::flat_set(); + result.reserve(_thumbs.size()); + auto i = 0; + for (const auto &thumb : _thumbs) { + if (thumb->hasSpoiler()) { + result.emplace(i); + } + ++i; + } + return result; +} + std::vector AlbumPreview::takeOrder() { //Expects(_thumbs.size() == _order.size()); //Expects(_itemsShownDimensions.size() == _order.size()); @@ -112,6 +128,7 @@ void AlbumPreview::prepareThumbs(gsl::span items) { items[i], layout[i], this, + [=] { update(); }, [=] { changeThumbByIndex(thumbIndex(thumbUnderCursor())); }, [=] { deleteThumbByIndex(thumbIndex(thumbUnderCursor())); })); if (_thumbs.back()->isCompressedSticker()) { @@ -365,11 +382,7 @@ void AlbumPreview::paintFiles(Painter &p, QRect clip) const { } else if (bottom <= clip.y()) { continue; } - if (thumb->isCompressedSticker()) { - thumb->paintPhoto(p, left, top, outerWidth); - } else { - thumb->paintFile(p, left, top, outerWidth); - } + thumb->paintFile(p, left, top, outerWidth); } } } @@ -393,15 +406,6 @@ void AlbumPreview::deleteThumbByIndex(int index) { if (index < 0) { return; } - const auto orderIt = ranges::find(_order, index); - Expects(orderIt != _order.end()); - - _order.erase(orderIt); - ranges::for_each(_order, [=](auto &i) { - if (i > index) { - i--; - } - }); _thumbDeleted.fire(std::move(index)); } @@ -448,7 +452,8 @@ void AlbumPreview::mousePressEvent(QMouseEvent *e) { const auto isAlbum = _sendWay.sendImagesAsPhotos() && _sendWay.groupFiles(); - if (!isAlbum) { + if (!isAlbum || e->button() != Qt::LeftButton) { + _dragTimer.cancel(); return; } @@ -554,13 +559,38 @@ void AlbumPreview::mouseReleaseEvent(QMouseEvent *e) { } else if (const auto thumb = base::take(_pressedThumb)) { const auto was = _pressedButtonType; const auto now = thumb->buttonTypeFromPoint(e->pos()); - if (was == now) { + if (e->button() == Qt::RightButton) { + showContextMenu(thumb, e->globalPos()); + } else if (was == now) { thumbButtonsCallback(thumb, now); } } _pressedButtonType = AttachButtonType::None; } +void AlbumPreview::showContextMenu( + not_null thumb, + QPoint position) { + if (!_sendWay.sendImagesAsPhotos()) { + return; + } + _menu = base::make_unique_q( + this, + st::popupMenuWithIcons); + + _menu->addAction(thumb->hasSpoiler() + ? tr::lng_context_disable_spoiler(tr::now) + : tr::lng_context_spoiler_effect(tr::now), [=] { + thumb->setSpoiler(!thumb->hasSpoiler()); + }, &st::menuIconCopy); + + if (_menu->empty()) { + _menu = nullptr; + } else { + _menu->popup(position); + } +} + void AlbumPreview::switchToDrag() { _paintedAbove = _suggestedThumb diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h index 2f9bf586e..50c239d8e 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h @@ -16,6 +16,7 @@ namespace Ui { struct PreparedFile; struct GroupMediaLayout; class AlbumThumbnail; +class PopupMenu; class AlbumPreview final : public RpWidget { public: @@ -26,7 +27,9 @@ public: ~AlbumPreview(); void setSendWay(SendFilesWay way); - std::vector takeOrder(); + + [[nodiscard]] base::flat_set collectSpoileredIndices(); + [[nodiscard]] std::vector takeOrder(); [[nodiscard]] rpl::producer thumbDeleted() const { return _thumbDeleted.events(); @@ -79,6 +82,8 @@ private: void cancelDrag(); void finishDrag(); + void showContextMenu(not_null thumb, QPoint position); + SendFilesWay _sendWay; style::cursor _cursor = style::cur_default; std::vector _order; @@ -103,6 +108,8 @@ private: rpl::event_stream _thumbChanged; rpl::event_stream _thumbModified; + base::unique_qptr _menu; + mutable Animations::Simple _thumbsHeightAnimation; mutable Animations::Simple _shrinkAnimation; mutable Animations::Simple _finishDragAnimation; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.cpp index bf57d5cf7..05fdf503f 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image_prepare.h" #include "ui/text/format_values.h" #include "ui/widgets/buttons.h" +#include "ui/effects/spoiler_mess.h" #include "ui/ui_utility.h" #include "ui/painter.h" #include "base/call_delayed.h" @@ -26,6 +27,7 @@ AlbumThumbnail::AlbumThumbnail( const PreparedFile &file, const GroupMediaLayout &layout, QWidget *parent, + Fn repaint, Fn editCallback, Fn deleteCallback) : _layout(layout) @@ -33,7 +35,8 @@ AlbumThumbnail::AlbumThumbnail( , _shrinkSize(int(std::ceil(st::roundRadiusLarge / 1.4))) , _isPhoto(file.type == PreparedFile::Type::Photo) , _isVideo(file.type == PreparedFile::Type::Video) -, _isCompressedSticker(Core::IsMimeSticker(file.information->filemime)) { +, _isCompressedSticker(Core::IsMimeSticker(file.information->filemime)) +, _repaint(std::move(repaint)) { Expects(!_fullPreview.isNull()); moveToLayout(layout); @@ -107,9 +110,23 @@ AlbumThumbnail::AlbumThumbnail( _editMedia->setIconOverride(&st::sendBoxAlbumGroupEditButtonIconFile); _deleteMedia->setIconOverride(&st::sendBoxAlbumGroupDeleteButtonIconFile); + setSpoiler(file.spoiler); setButtonVisible(false); } +void AlbumThumbnail::setSpoiler(bool spoiler) { + Expects(_repaint != nullptr); + + _spoiler = spoiler + ? std::make_unique(_repaint) + : nullptr; + _repaint(); +} + +bool AlbumThumbnail::hasSpoiler() const { + return _spoiler != nullptr; +} + void AlbumThumbnail::setButtonVisible(bool value) { _editMedia->setVisible(value); _deleteMedia->setVisible(value); @@ -135,7 +152,7 @@ void AlbumThumbnail::animateLayoutToInitial() { } void AlbumThumbnail::moveToLayout(const GroupMediaLayout &layout) { - using Option = Images::Option; + using namespace Images; animateLayoutToInitial(); _layout = layout; @@ -143,27 +160,20 @@ void AlbumThumbnail::moveToLayout(const GroupMediaLayout &layout) { const auto width = _layout.geometry.width(); const auto height = _layout.geometry.height(); _albumCorners = GetCornersFromSides(_layout.sides); - const auto corner = [&](RectPart part, Option skip) { - return !(_albumCorners & part) ? skip : Option(); - }; - const auto options = Option::RoundLarge - | corner(RectPart::TopLeft, Option::RoundSkipTopLeft) - | corner(RectPart::TopRight, Option::RoundSkipTopRight) - | corner(RectPart::BottomLeft, Option::RoundSkipBottomLeft) - | corner(RectPart::BottomRight, Option::RoundSkipBottomRight); const auto pixSize = GetImageScaleSizeForGeometry( { _fullPreview.width(), _fullPreview.height() }, { width, height }); const auto pixWidth = pixSize.width() * style::DevicePixelRatio(); const auto pixHeight = pixSize.height() * style::DevicePixelRatio(); - _albumImage = PixmapFromImage(Images::Prepare( + _albumImage = PixmapFromImage(Prepare( _fullPreview, QSize(pixWidth, pixHeight), { - .options = options, + .options = RoundOptions(ImageRoundRadius::Large, _albumCorners), .outer = { width, height }, })); + _albumImageBlurred = QPixmap(); } int AlbumThumbnail::photoHeight() const { @@ -188,46 +198,83 @@ void AlbumThumbnail::paintInAlbum( float64 moveProgress) { const auto shrink = anim::interpolate(0, _shrinkSize, shrinkProgress); _lastShrinkValue = shrink; - const auto geometry = countCurrentGeometry(moveProgress); - const auto x = left + geometry.x(); - const auto y = top + geometry.y(); - if (shrink > 0 || moveProgress < 1.) { - const auto size = geometry.size(); - if (shrinkProgress < 1 && _albumCorners != RectPart::None) { - prepareCache(size, shrink); - p.drawImage(x, y, _albumCache); - } else { - const auto to = QRect({ x, y }, size).marginsRemoved( + const auto geometry = countCurrentGeometry( + moveProgress + ).translated(left, top); + auto paintedTo = geometry; + const auto revealed = _spoiler ? shrinkProgress : 1.; + if (revealed > 0.) { + if (shrink > 0 || moveProgress < 1.) { + const auto size = geometry.size(); + paintedTo = geometry.marginsRemoved( { shrink, shrink, shrink, shrink } ); - drawSimpleFrame(p, to, size); + if (shrinkProgress < 1 && _albumCorners != RectPart::None) { + prepareCache(size, shrink); + p.drawImage(geometry.topLeft(), _albumCache); + } else { + drawSimpleFrame(p, paintedTo, size); + } + } else { + p.drawPixmap(geometry.topLeft(), _albumImage); + } + if (_isVideo) { + paintPlayVideo(p, geometry); } - } else { - p.drawPixmap(x, y, _albumImage); } - if (_isVideo) { - const auto innerSize = st::msgFileLayout.thumbSize; - const auto inner = QRect( - x + (geometry.width() - innerSize) / 2, - y + (geometry.height() - innerSize) / 2, - innerSize, - innerSize); - { - PainterHighQualityEnabler hq(p); - p.setPen(Qt::NoPen); - p.setBrush(st::msgDateImgBg); - p.drawEllipse(inner); + if (revealed < 1.) { + auto corners = Images::CornersMaskRef( + Images::CornersMask(ImageRoundRadius::Large)); + if (!(_albumCorners & RectPart::TopLeft)) { + corners.p[0] = nullptr; } - st::historyFileThumbPlay.paintInCenter(p, inner); + if (!(_albumCorners & RectPart::TopRight)) { + corners.p[1] = nullptr; + } + if (!(_albumCorners & RectPart::BottomLeft)) { + corners.p[2] = nullptr; + } + if (!(_albumCorners & RectPart::BottomRight)) { + corners.p[3] = nullptr; + } + p.setOpacity(1. - revealed); + if (_albumImageBlurred.isNull()) { + _albumImageBlurred = BlurredPreviewFromPixmap( + _albumImage, + _albumCorners); + } + p.drawPixmap(paintedTo, _albumImageBlurred); + FillSpoilerRect( + p, + paintedTo, + corners, + DefaultImageSpoiler().frame(_spoiler->index(crl::now(), false)), + _cornerCache); + p.setOpacity(1.); } _lastRectOfButtons = paintButtons( p, - { x, y }, + geometry.topLeft(), geometry.width(), shrinkProgress); + _lastRectOfModify = geometry; +} - _lastRectOfModify = QRect(QPoint(x, y), geometry.size()); +void AlbumThumbnail::paintPlayVideo(QPainter &p, QRect geometry) { + const auto innerSize = st::msgFileLayout.thumbSize; + const auto inner = QRect( + geometry.x() + (geometry.width() - innerSize) / 2, + geometry.y() + (geometry.height() - innerSize) / 2, + innerSize, + innerSize); + { + PainterHighQualityEnabler hq(p); + p.setPen(Qt::NoPen); + p.setBrush(st::msgDateImgBg); + p.drawEllipse(inner); + } + st::historyFileThumbPlay.paintInCenter(p, inner); } void AlbumThumbnail::prepareCache(QSize size, int shrink) { @@ -376,11 +423,33 @@ void AlbumThumbnail::drawSimpleFrame(QPainter &p, QRect to, QSize size) const { void AlbumThumbnail::paintPhoto(Painter &p, int left, int top, int outerWidth) { const auto size = _photo.size() / style::DevicePixelRatio(); + if (_spoiler && _photoBlurred.isNull()) { + _photoBlurred = BlurredPreviewFromPixmap( + _photo, + RectPart::AllCorners); + } + const auto &pixmap = _spoiler ? _photoBlurred : _photo; + const auto rect = QRect( + left + (st::sendMediaPreviewSize - size.width()) / 2, + top, + pixmap.width() / pixmap.devicePixelRatio(), + pixmap.height() / pixmap.devicePixelRatio()); p.drawPixmapLeft( left + (st::sendMediaPreviewSize - size.width()) / 2, top, outerWidth, - _photo); + pixmap); + if (_spoiler) { + FillSpoilerRect( + p, + rect, + Images::CornersMaskRef( + Images::CornersMask(ImageRoundRadius::Large)), + DefaultImageSpoiler().frame(_spoiler->index(crl::now(), false)), + _cornerCache); + } else if (_isVideo) { + paintPlayVideo(p, rect); + } const auto topLeft = QPoint{ left, top }; @@ -398,6 +467,13 @@ void AlbumThumbnail::paintFile( int left, int top, int outerWidth) { + + if (isCompressedSticker()) { + auto spoiler = base::take(_spoiler); + paintPhoto(p, left, top, outerWidth); + _spoiler = base::take(spoiler); + return; + } const auto &st = st::attachPreviewThumbLayout; const auto textLeft = left + st.thumbSize + st.thumbSkip; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.h b/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.h index eaad8d61b..d85bd9c32 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_thumbnail.h @@ -18,6 +18,7 @@ namespace Ui { struct PreparedFile; class IconButton; +class SpoilerAnimation; class AlbumThumbnail final { public: @@ -25,6 +26,7 @@ public: const PreparedFile &file, const GroupMediaLayout &layout, QWidget *parent, + Fn repaint, Fn editCallback, Fn deleteCallback); @@ -32,6 +34,9 @@ public: void animateLayoutToInitial(); void resetLayoutAnimation(); + void setSpoiler(bool spoiler); + [[nodiscard]] bool hasSpoiler() const; + int photoHeight() const; int fileHeight() const; @@ -71,6 +76,7 @@ private: QPoint point, int outerWidth, float64 shrinkProgress); + void paintPlayVideo(QPainter &p, QRect geometry); GroupMediaLayout _layout; std::optional _animateFromGeometry; @@ -79,10 +85,12 @@ private: const bool _isPhoto; const bool _isVideo; QPixmap _albumImage; + QPixmap _albumImageBlurred; QImage _albumCache; QPoint _albumPosition; RectParts _albumCorners = RectPart::None; QPixmap _photo; + QPixmap _photoBlurred; QPixmap _fileThumb; QString _name; QString _status; @@ -94,6 +102,9 @@ private: AttachControls _buttons; bool _isCompressedSticker = false; + std::unique_ptr _spoiler; + QImage _cornerCache; + Fn _repaint; QRect _lastRectOfModify; QRect _lastRectOfButtons; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp index b57b6fb00..74c417049 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp @@ -295,4 +295,28 @@ QPixmap PrepareSongCoverForThumbnail(QImage image, int size) { })); } +QPixmap BlurredPreviewFromPixmap(QPixmap pixmap, RectParts corners) { + const auto image = pixmap.toImage(); + const auto skip = st::roundRadiusLarge * image.devicePixelRatio(); + auto small = image.copy( + skip, + skip, + image.width() - 2 * skip, + image.height() - 2 * skip + ).scaled( + 40, + 40, + Qt::KeepAspectRatioByExpanding, + Qt::SmoothTransformation); + + using namespace Images; + return PixmapFromImage(Prepare( + Blur(std::move(small), true), + image.size() / style::DevicePixelRatio(), + { + .options = RoundOptions(ImageRoundRadius::Large, corners), + .outer = image.size() / style::DevicePixelRatio(), + })); +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h index c3e0797b5..8d4ee6929 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "editor/photo_editor_common.h" +#include "ui/rect_part.h" #include #include @@ -80,6 +81,7 @@ struct PreparedFile { QImage preview; QSize shownDimensions; Type type = Type::File; + bool spoiler = false; }; [[nodiscard]] bool CanBeInAlbumType(PreparedFile::Type type, AlbumType album); @@ -143,4 +145,8 @@ struct PreparedGroup { [[nodiscard]] QPixmap PrepareSongCoverForThumbnail(QImage image, int size); +[[nodiscard]] QPixmap BlurredPreviewFromPixmap( + QPixmap pixmap, + RectParts corners); + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.cpp index 224a110e7..600b3066a 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.cpp @@ -47,6 +47,7 @@ SingleMediaPreview *SingleMediaPreview::Create( preview, animated, Core::IsMimeSticker(file.information->filemime), + file.spoiler, animationPreview ? file.path : QString(), type); } @@ -57,6 +58,7 @@ SingleMediaPreview::SingleMediaPreview( QImage preview, bool animated, bool sticker, + bool spoiler, const QString &animatedPreviewPath, AttachControls::Type type) : AbstractSingleMediaPreview(parent, type) @@ -67,7 +69,7 @@ SingleMediaPreview::SingleMediaPreview( preparePreview(preview); prepareAnimatedPreview(animatedPreviewPath, animated); - updatePhotoEditorButton(); + setSpoiler(spoiler); } bool SingleMediaPreview::drawBackground() const { diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.h b/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.h index f1bf834d5..e5d03d245 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.h @@ -32,6 +32,7 @@ public: QImage preview, bool animated, bool sticker, + bool spoiler, const QString &animatedPreviewPath, AttachControls::Type type);