From 202534575b6855c6d5a033d8d577cb3ecb9c8851 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 16 Oct 2020 10:52:55 +0300 Subject: [PATCH] Allow many previews in SendFilesBox. --- .../SourceFiles/boxes/edit_caption_box.cpp | 2 +- Telegram/SourceFiles/boxes/send_files_box.cpp | 313 ++++++++++-------- Telegram/SourceFiles/boxes/send_files_box.h | 17 +- .../SourceFiles/history/history_widget.cpp | 4 +- .../view/history_view_replies_section.cpp | 7 +- .../SourceFiles/storage/localimageloader.cpp | 9 +- .../SourceFiles/storage/localimageloader.h | 2 +- .../storage/storage_media_prepare.cpp | 40 +-- .../ui/chat/attach/attach_album_preview.cpp | 10 +- .../ui/chat/attach/attach_album_preview.h | 10 +- .../ui/chat/attach/attach_prepare.cpp | 57 +++- .../ui/chat/attach/attach_prepare.h | 19 +- .../attach/attach_single_file_preview.cpp | 12 +- .../chat/attach/attach_single_file_preview.h | 2 - .../attach/attach_single_media_preview.cpp | 6 +- .../chat/attach/attach_single_media_preview.h | 2 - 16 files changed, 286 insertions(+), 226 deletions(-) diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index 1a216e3bd5..659151e98d 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -689,7 +689,7 @@ bool EditCaptionBox::fileFromClipboard(not_null data) { } const auto file = &list.files.front(); - if (_isAlbum && (file->type == AlbumType::None)) { + if (_isAlbum && (file->type == AlbumType::File)) { const auto imageAsDoc = [&] { using Info = Ui::PreparedFileInformation; const auto fileMedia = &file->information->media; diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 01d323c818..f0accfe2e2 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/input_fields.h" #include "ui/widgets/scroll_area.h" #include "ui/wrap/fade_wrap.h" +#include "ui/wrap/vertical_layout.h" #include "ui/chat/attach/attach_prepare.h" #include "ui/chat/attach/attach_send_files_way.h" #include "ui/chat/attach/attach_album_preview.h" @@ -64,12 +65,6 @@ inline bool CanAddUrls(const QList &urls) { return !urls.isEmpty() && ranges::all_of(urls, &QUrl::isLocalFile); } -inline bool IsFirstAlbumItem(const Ui::PreparedList &list) { - using AlbumType = Ui::PreparedFile::AlbumType; - return (list.files.size() > 0) - && (list.files.front().type != AlbumType::None); -} - inline bool IsSingleItem(const Ui::PreparedList &list) { return list.files.size() == 1; } @@ -98,9 +93,7 @@ void FileDialogCallback( rpl::producer FieldPlaceholder( const Ui::PreparedList &list, SendFilesWay way) { - const auto isAlbum = list.singleAlbumIsPossible - && way.groupMediaInAlbums(); - return list.canAddCaption(isAlbum) + return list.canAddCaption(way.groupMediaInAlbums()) ? tr::lng_photo_caption() : tr::lng_photos_comment(); } @@ -125,10 +118,14 @@ SendFilesBox::SendFilesBox( st::confirmCaptionArea, Ui::InputField::Mode::MultiLine, nullptr, - caption) { + caption) +, _scroll(this, st::boxScroll) +, _inner( + _scroll->setOwnedWidget( + object_ptr(_scroll.data()))) { } -void SendFilesBox::initPreview(rpl::producer desiredPreviewHeight) { +void SendFilesBox::initPreview() { using namespace rpl::mappers; setupControls(); @@ -136,8 +133,10 @@ void SendFilesBox::initPreview(rpl::producer desiredPreviewHeight) { updateBoxSize(); _dimensionsLifetime.destroy(); + _inner->resizeToWidth(st::boxWideWidth); + rpl::combine( - std::move(desiredPreviewHeight), + _inner->heightValue(), _footerHeight.value(), _titleHeight + _1 + _2 ) | rpl::start_with_next([=](int height) { @@ -146,102 +145,83 @@ void SendFilesBox::initPreview(rpl::producer desiredPreviewHeight) { std::min(st::sendMediaPreviewHeightMax, height), true); }, _dimensionsLifetime); - - if (_preview) { - _preview->show(); - } } -void SendFilesBox::prepareSingleFilePreview() { - Expects(IsSingleItem(_list)); +//void SendFilesBox::prepareSingleFilePreview() { +// const auto &file = _list.files[0]; +// const auto controller = _controller; +// const auto media = Ui::SingleMediaPreview::Create(this, [=] { +// return controller->isGifPausedAtLeastFor( +// Window::GifPauseReason::Layer); +// }, file); +// if (media) { +// _preview = media; +// initPreview(media->desiredHeightValue()); +// } else { +// const auto preview = Ui::CreateChild(this, file); +// _preview = preview; +// initPreview(preview->desiredHeightValue()); +// } +//} - const auto &file = _list.files[0]; - const auto controller = _controller; - const auto media = Ui::SingleMediaPreview::Create(this, [=] { - return controller->isGifPausedAtLeastFor( - Window::GifPauseReason::Layer); - }, file); - if (media) { - _preview = media; - initPreview(media->desiredHeightValue()); - } else { - const auto preview = Ui::CreateChild(this, file); - _preview = preview; - initPreview(preview->desiredHeightValue()); - } -} - -void SendFilesBox::prepareAlbumPreview() { - const auto wrap = Ui::CreateChild( - this, - st::boxScroll); - _albumPreview = wrap->setOwnedWidget(object_ptr( - this, - _list, - _sendWay.current())); - - addThumbButtonHandlers(wrap); - - _preview = wrap; - _albumPreview->show(); - setupShadows(wrap, _albumPreview); - - initPreview(_albumPreview->desiredHeightValue()); - - crl::on_main([=] { - wrap->scrollToY(_lastScrollTop); - _lastScrollTop = 0; - }); -} +//void SendFilesBox::prepareAlbumPreview() { +// addThumbButtonHandlers(wrap); // #TODO files +// +// setupShadows(wrap, _albumPreview); +// +// initPreview(_albumPreview->desiredHeightValue()); +// +// crl::on_main([=] { +// wrap->scrollToY(_lastScrollTop); +// _lastScrollTop = 0; +// }); +//} void SendFilesBox::addThumbButtonHandlers(not_null wrap) { - _albumPreview->thumbDeleted( - ) | rpl::start_with_next([=](auto index) { - _lastScrollTop = wrap->scrollTop(); + // #TODO files + //_albumPreview->thumbDeleted( + //) | rpl::start_with_next([=](auto index) { + // _lastScrollTop = wrap->scrollTop(); - _list.files.erase(_list.files.begin() + index); - applyAlbumOrder(); + // _list.files.erase(_list.files.begin() + index); + // applyAlbumOrder(); - if (_preview) { - _preview->deleteLater(); - } - _albumPreview = nullptr; + // if (_preview) { + // _preview->deleteLater(); + // } + // _albumPreview = nullptr; - if (IsSingleItem(_list)) { - _list.singleAlbumIsPossible = false; - } + // refreshAllAfterAlbumChanges(); + //}, _albumPreview->lifetime()); - refreshAllAfterAlbumChanges(); - }, _albumPreview->lifetime()); + //_albumPreview->thumbChanged( + //) | rpl::start_with_next([=](auto index) { + // _lastScrollTop = wrap->scrollTop(); - _albumPreview->thumbChanged( - ) | rpl::start_with_next([=](auto index) { - _lastScrollTop = wrap->scrollTop(); + // const auto callback = [=](FileDialog::OpenResult &&result) { + // FileDialogCallback( + // std::move(result), + // true, + // [=] (auto list) { + // _list.files[index] = std::move(list.files.front()); + // applyAlbumOrder(); - const auto callback = [=](FileDialog::OpenResult &&result) { - FileDialogCallback( - std::move(result), - true, - [=] (auto list) { - _list.files[index] = std::move(list.files.front()); - applyAlbumOrder(); + // if (_preview) { + // _preview->deleteLater(); + // } + // _albumPreview = nullptr; - if (_preview) { - _preview->deleteLater(); - } - _albumPreview = nullptr; + // refreshAllAfterAlbumChanges(); + // }); + // }; - refreshAllAfterAlbumChanges(); - }); - }; + // FileDialog::GetOpenPath( + // this, + // tr::lng_choose_file(tr::now), + // FileDialog::AlbumFilesFilter(), + // crl::guard(this, callback)); - FileDialog::GetOpenPath( - this, - tr::lng_choose_file(tr::now), - FileDialog::AlbumFilesFilter(), - crl::guard(this, callback)); - - }, _albumPreview->lifetime()); + //}, _albumPreview->lifetime()); } void SendFilesBox::setupShadows( @@ -288,6 +268,10 @@ void SendFilesBox::prepare() { setupCaption(); setupSendWayControls(); preparePreview(); + initPreview(); + + _scroll->show(); + _inner->show(); boxClosing() | rpl::start_with_next([=] { if (!_confirmed && _cancelledCallback) { @@ -379,10 +363,6 @@ void SendFilesBox::initSendWay() { _sendWay.changes( ) | rpl::start_with_next([=](SendFilesWay value) { updateCaptionPlaceholder(); - applyAlbumOrder(); - if (_albumPreview) { - _albumPreview->setSendWay(value); - } updateEmojiPanelGeometry(); setInnerFocus(); }, lifetime()); @@ -393,9 +373,8 @@ void SendFilesBox::updateCaptionPlaceholder() { return; } const auto sendWay = _sendWay.current(); - const auto isAlbum = _list.singleAlbumIsPossible - && sendWay.groupMediaInAlbums(); - if (!_list.canAddCaption(isAlbum) && _sendLimit == SendLimit::One) { + if (!_list.canAddCaption(sendWay.groupMediaInAlbums()) + && _sendLimit == SendLimit::One) { _caption->hide(); if (_emojiToggle) { _emojiToggle->hide(); @@ -410,11 +389,73 @@ void SendFilesBox::updateCaptionPlaceholder() { } void SendFilesBox::preparePreview() { - if (IsSingleItem(_list)) { - prepareSingleFilePreview(); - } else { - prepareAlbumPreview(); // #TODO files many albums + using Type = Ui::PreparedFile::AlbumType; + + _blocks.clear(); + auto albumStart = -1; + const auto finishAlbum = [&](int till) { + if (albumStart < 0) { + return; + } + const auto count = (till - albumStart); + const auto preview = _inner->add(object_ptr( + this, + gsl::make_span(_list.files).subspan(albumStart, count), + _sendWay.current())); + + auto &block = _blocks.emplace_back(); + block.fromIndex = albumStart; + block.tillIndex = albumStart + count; + block.preview.reset(preview); + block.preview->show(); + + _sendWay.changes( + ) | rpl::start_with_next([=](SendFilesWay value) { + applyAlbumOrder(preview, albumStart); + preview->setSendWay(value); + }, preview->lifetime()); + + albumStart = -1; + }; + const auto finishSingle = [&](int index) { + const auto &file = _list.files[index]; + const auto controller = _controller; + auto &block = _blocks.emplace_back(); + block.fromIndex = index; + block.tillIndex = index + 1; + const auto media = Ui::SingleMediaPreview::Create(this, [=] { + return controller->isGifPausedAtLeastFor( + Window::GifPauseReason::Layer); + }, file); + if (media) { + block.preview.reset( + _inner->add(object_ptr::fromRaw( + media))); + } else { + block.preview.reset( + _inner->add(object_ptr(this, file))); + } + block.preview->show(); + }; + for (auto i = 0, count = int(_list.files.size()); i != count; ++i) { + const auto type = _list.files[i].type; + if (albumStart >= 0) { + const auto albumCount = (i - albumStart); + if (type == Type::File || (albumCount == Ui::MaxAlbumItems())) { + finishAlbum(i); + } else { + continue; + } + } + if (type != Type::File) { + if (albumStart < 0) { + albumStart = i; + } + continue; + } + finishSingle(i); } + finishAlbum(_list.files.size()); } void SendFilesBox::setupControls() { @@ -479,12 +520,10 @@ void SendFilesBox::updateSendWayControlsVisibility() { _groupFiles->setVisible(!onlyOne); } -void SendFilesBox::applyAlbumOrder() { - if (!_albumPreview) { - return; - } - - const auto order = _albumPreview->takeOrder(); +void SendFilesBox::applyAlbumOrder( + not_null preview, + int from) { + const auto order = preview->takeOrder(); const auto isDefault = [&] { for (auto i = 0, count = int(order.size()); i != count; ++i) { if (order[i] != i) { @@ -497,7 +536,14 @@ void SendFilesBox::applyAlbumOrder() { return; } - _list = Ui::PreparedList::Reordered(std::move(_list), order); + auto elements = std::vector(); + elements.reserve(order.size()); + for (const auto index : order) { + elements.push_back(std::move(_list.files[from + index])); + } + for (auto i = 0, count = int(order.size()); i != count; ++i) { + _list.files[from + i] = std::move(elements[i]); + } } void SendFilesBox::setupCaption() { @@ -604,20 +650,21 @@ void SendFilesBox::captionResized() { } bool SendFilesBox::canAddFiles(not_null data) const { - const auto urls = data->hasUrls() ? data->urls() : QList(); - auto filesCount = CanAddUrls(urls) ? urls.size() : 0; - if (!filesCount && data->hasImage()) { - ++filesCount; - } + return (data->hasUrls() && CanAddUrls(data->urls())) || data->hasImage(); + //const auto urls = data->hasUrls() ? data->urls() : QList(); + //auto filesCount = CanAddUrls(urls) ? urls.size() : 0; + //if (!filesCount && data->hasImage()) { + // ++filesCount; + //} - if (_list.files.size() + filesCount > Ui::MaxAlbumItems()) { - return false; - } else if (_list.files.size() > 1 && !_albumPreview) { - return false; - } else if (!IsFirstAlbumItem(_list)) { - return false; - } - return true; + //if (_list.files.size() + filesCount > Ui::MaxAlbumItems()) { // #TODO files + // return false; + //} else if (_list.files.size() > 1 && !_albumPreview) { + // return false; + //} else if (!IsFirstAlbumItem(_list)) { + // return false; + //} + //return true; } bool SendFilesBox::addFiles(not_null data) { @@ -661,10 +708,10 @@ bool SendFilesBox::addFiles(Ui::PreparedList list) { //} else if (!IsFirstAlbumItem(_list)) { // return false; } - applyAlbumOrder(); - delete base::take(_preview); - _albumPreview = nullptr; - + //applyAlbumOrder(); + //delete base::take(_preview); + //_albumPreview = nullptr; + return false; _list.mergeToEnd(std::move(list), cutToAlbumSize); refreshAllAfterAlbumChanges(); @@ -769,10 +816,8 @@ void SendFilesBox::updateControlsGeometry() { bottom -= st::boxPhotoCompressedSkip + pointer->heightNoMargins(); } } - if (_preview) { - _preview->resize(width(), bottom - _titleHeight); - _preview->move(0, _titleHeight); - } + _scroll->resize(width(), bottom - _titleHeight); + _scroll->move(0, _titleHeight); } void SendFilesBox::setInnerFocus() { @@ -809,7 +854,7 @@ void SendFilesBox::send( Core::App().saveSettingsDelayed(); } - applyAlbumOrder(); + //applyAlbumOrder(); // #TODO files _confirmed = true; if (_confirmedCallback) { auto caption = (_caption && !_caption->isHidden()) diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index 46ffe34b53..00f0626e8a 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -34,6 +34,7 @@ class InputField; struct GroupMediaLayout; class EmojiButton; class AlbumPreview; +class VerticalLayout; } // namespace Ui namespace Window { @@ -83,8 +84,13 @@ protected: void resizeEvent(QResizeEvent *e) override; private: + struct Block { + base::unique_qptr preview; + int fromIndex = 0; + int tillIndex = 0; + }; void initSendWay(); - void initPreview(rpl::producer desiredPreviewHeight); + void initPreview(); void setupControls(); void setupSendWayControls(); @@ -99,9 +105,7 @@ private: void emojiFilterForGeometry(not_null event); void preparePreview(); - void prepareSingleFilePreview(); - void prepareAlbumPreview(); - void applyAlbumOrder(); + void applyAlbumOrder(not_null preview, int from); void send(Api::SendOptions options, bool ctrlShiftEnter = false); void sendSilent(); @@ -157,8 +161,9 @@ private: rpl::event_stream<> _albumChanged; rpl::lifetime _dimensionsLifetime; - QWidget *_preview = nullptr; - Ui::AlbumPreview *_albumPreview = nullptr; + object_ptr _scroll; + QPointer _inner; + std::vector _blocks; int _lastScrollTop = 0; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 4a50804bdd..f731557956 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -4097,9 +4097,7 @@ bool HistoryWidget::showSendingFilesError( } else if (!canWriteMessage()) { return tr::lng_forward_send_files_cant(tr::now); } - if (list.files.size() > 1 - && _peer->slowmodeApplied() - && !list.singleAlbumIsPossible) { + if (_peer->slowmodeApplied() && !list.canBeSentInSlowmode()) { return tr::lng_slowmode_no_many(tr::now); } else if (const auto left = _peer->slowmodeSecondsLeft()) { return tr::lng_slowmode_enabled( diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 6415cd87aa..46a0ed4f6b 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -800,15 +800,14 @@ void RepliesWidget::uploadFile( bool RepliesWidget::showSendingFilesError( const Ui::PreparedList &list) const { const auto text = [&] { + const auto peer = _history->peer; const auto error = Data::RestrictionError( - _history->peer, + peer, ChatRestriction::f_send_media); if (error) { return *error; } - if (list.files.size() > 1 - && _history->peer->slowmodeApplied() - && !list.singleAlbumIsPossible) { + if (peer->slowmodeApplied() && !list.canBeSentInSlowmode()) { return tr::lng_slowmode_no_many(tr::now); } else if (const auto left = _history->peer->slowmodeSecondsLeft()) { return tr::lng_slowmode_enabled( diff --git a/Telegram/SourceFiles/storage/localimageloader.cpp b/Telegram/SourceFiles/storage/localimageloader.cpp index e1e67bf845..6865d52002 100644 --- a/Telegram/SourceFiles/storage/localimageloader.cpp +++ b/Telegram/SourceFiles/storage/localimageloader.cpp @@ -530,10 +530,11 @@ FileLoadTask::FileLoadTask( FileLoadTask::~FileLoadTask() = default; -std::unique_ptr FileLoadTask::ReadMediaInformation( - const QString &filepath, - const QByteArray &content, - const QString &filemime) { +auto FileLoadTask::ReadMediaInformation( + const QString &filepath, + const QByteArray &content, + const QString &filemime) +-> std::unique_ptr { auto result = std::make_unique(); result->filemime = filemime; diff --git a/Telegram/SourceFiles/storage/localimageloader.h b/Telegram/SourceFiles/storage/localimageloader.h index b550bb0821..02a403d9b5 100644 --- a/Telegram/SourceFiles/storage/localimageloader.h +++ b/Telegram/SourceFiles/storage/localimageloader.h @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_common.h" #include "ui/chat/attach/attach_prepare.h" -constexpr auto kFileSizeLimit = 2000 * 1024 * 1024; // Load files up to 1500mb +constexpr auto kFileSizeLimit = 2000 * 1024 * 1024; // Load files up to 2000MB enum class SendMediaType { Photo, diff --git a/Telegram/SourceFiles/storage/storage_media_prepare.cpp b/Telegram/SourceFiles/storage/storage_media_prepare.cpp index a7c79875e3..aa9535964f 100644 --- a/Telegram/SourceFiles/storage/storage_media_prepare.cpp +++ b/Telegram/SourceFiles/storage/storage_media_prepare.cpp @@ -62,11 +62,10 @@ QSize PrepareShownDimensions(const QImage &preview) { : result; } -bool PrepareAlbumMediaIsWaiting( +bool PrepareDetailsIsWaiting( QSemaphore &semaphore, PreparedFile &file, int previewWidth) { - // TODO: Use some special thread queue, like a separate QThreadPool. crl::async([=, &semaphore, &file] { const auto guard = gsl::finally([&] { semaphore.release(); }); if (!file.path.isEmpty()) { @@ -116,29 +115,21 @@ bool PrepareAlbumMediaIsWaiting( return true; } -void PrepareAlbum(PreparedList &result, int previewWidth) { - const auto count = int(result.files.size()); - if (count > Ui::MaxAlbumItems()) { - return; - } +void PrepareDetailsInParallel(PreparedList &result, int previewWidth) { + Expects(result.files.size() <= Ui::MaxAlbumItems()); - //result.albumIsPossible = (count > 1); auto waiting = 0; QSemaphore semaphore; for (auto &file : result.files) { - if (PrepareAlbumMediaIsWaiting(semaphore, file, previewWidth)) { + if (PrepareDetailsIsWaiting( + semaphore, + file, + previewWidth)) { ++waiting; } } if (waiting > 0) { semaphore.acquire(waiting); - //if (result.albumIsPossible) { - // const auto badIt = ranges::find( - // result.files, - // PreparedFile::AlbumType::None, - // [](const PreparedFile &file) { return file.type; }); - // result.albumIsPossible = (badIt == result.files.end()); - //} } } @@ -250,13 +241,15 @@ PreparedList PrepareMediaList(const QStringList &files, int previewWidth) { file }; } - const auto toCompress = HasExtensionFrom(file, extensionsToCompress); - if (filesize > App::kImageSizeLimit || !toCompress) { -// result.allFilesForCompress = false; + if (result.files.size() < Ui::MaxAlbumItems()) { + result.files.emplace_back(file); + result.files.back().size = filesize; + } else { + result.filesToProcess.emplace_back(file); + result.files.back().size = filesize; } - result.files.emplace_back(file); } - PrepareAlbum(result, previewWidth); + PrepareDetailsInParallel(result, previewWidth); return result; } @@ -276,7 +269,7 @@ PreparedList PrepareMediaFromImage( file.information); } result.files.push_back(std::move(file)); - PrepareAlbum(result, previewWidth); + PrepareDetailsInParallel(result, previewWidth); return result; } @@ -304,7 +297,7 @@ std::optional PreparedFileFromFilesDialog( if (isAlbum) { const auto file = &list.files.front(); if (!Core::IsMimeAcceptedForAlbum(mimeFile) - || file->type == Storage::PreparedFile::AlbumType::None) { + || file->type == Storage::PreparedFile::AlbumType::File) { errorCallback(tr::lng_edit_media_album_error); return std::nullopt; } @@ -361,7 +354,6 @@ std::optional PreparedFileFromFilesDialog( } auto list = PreparedList(temp.error, temp.errorData); - //list.albumIsPossible = isAlbum; list.files = std::move(filteredFiles); return list; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp index e57e5ab480..af6b665266 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp @@ -22,7 +22,7 @@ constexpr auto kDragDuration = crl::time(200); AlbumPreview::AlbumPreview( QWidget *parent, - const PreparedList &list, + gsl::span list, SendFilesWay way) : RpWidget(parent) , _list(list) @@ -69,7 +69,7 @@ auto AlbumPreview::generateOrderedLayout() const auto sizes = ranges::view::all( _order ) | ranges::view::transform([&](int index) { - return _list.files[index].shownDimensions; + return _list[index].shownDimensions; }) | ranges::to_vector; auto layout = LayoutMediaGroup( @@ -82,19 +82,19 @@ auto AlbumPreview::generateOrderedLayout() const } std::vector AlbumPreview::defaultOrder() const { - const auto count = int(_list.files.size()); + const auto count = int(_list.size()); return ranges::view::ints(0, count) | ranges::to_vector; } void AlbumPreview::prepareThumbs() { _order = defaultOrder(); - const auto count = int(_list.files.size()); + const auto count = int(_list.size()); const auto layout = generateOrderedLayout(); _thumbs.reserve(count); for (auto i = 0; i != count; ++i) { _thumbs.push_back(std::make_unique( - _list.files[i], + _list[i], layout[i], this, [=] { changeThumbByIndex(thumbIndex(thumbUnderCursor())); }, diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h index fe9a2d1603..fad5a80db7 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.h @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Ui { -struct PreparedList; +struct PreparedFile; struct GroupMediaLayout; class AlbumThumbnail; @@ -20,18 +20,18 @@ class AlbumPreview final : public RpWidget { public: AlbumPreview( QWidget *parent, - const PreparedList &list, + gsl::span list, SendFilesWay way); ~AlbumPreview(); void setSendWay(SendFilesWay way); std::vector takeOrder(); - auto thumbDeleted() { + [[nodiscard]] rpl::producer thumbDeleted() const { return _thumbDeleted.events(); } - auto thumbChanged() { + [[nodiscard]] rpl::producer thumbChanged() const { return _thumbChanged.events(); } @@ -73,7 +73,7 @@ private: void cancelDrag(); void finishDrag(); - const PreparedList &_list; + gsl::span _list; SendFilesWay _sendWay; style::cursor _cursor = style::cur_default; std::vector _order; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp index 1698eb5bbb..07d23def10 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp @@ -32,7 +32,6 @@ PreparedList PreparedList::Reordered( Expects(list.files.size() == order.size()); auto result = PreparedList(list.error, list.errorData); - result.singleAlbumIsPossible = list.singleAlbumIsPossible; result.files.reserve(list.files.size()); for (auto index : order) { result.files.push_back(std::move(list.files[index])); @@ -58,28 +57,50 @@ void PreparedList::mergeToEnd(PreparedList &&other, bool cutToAlbumSize) { } files.push_back(std::move(file)); } - if (files.size() > 1 && files.size() <= kMaxAlbumCount) { - const auto badIt = ranges::find( - files, - PreparedFile::AlbumType::None, - [](const PreparedFile &file) { return file.type; }); - singleAlbumIsPossible = (badIt == files.end()); - } else { - singleAlbumIsPossible = false; - } } -bool PreparedList::canAddCaption(bool isAlbum) const { - const auto isSticker = [&] { - if (files.empty()) { - return false; - } - return Core::IsMimeSticker(files.front().mime) +bool PreparedList::canBeSentInSlowmode() const { + if (!filesToProcess.empty()) { + return false; + } else if (files.size() < 2) { + return true; + } else if (files.size() > kMaxAlbumCount) { + return false; + } + + const auto hasFiles = ranges::contains( + files, + PreparedFile::AlbumType::File, + &PreparedFile::type); + const auto hasVideos = ranges::contains( + files, + PreparedFile::AlbumType::Video, + &PreparedFile::type); + + // File-s and Video-s never can be grouped. + return !hasFiles || !hasVideos; +} + +bool PreparedList::canAddCaption(bool groupMediaInAlbums) const { + if (!filesToProcess.empty() + || files.empty() + || files.size() > kMaxAlbumCount) { + return false; + } + if (files.size() == 1) { + const auto isSticker = Core::IsMimeSticker(files.front().mime) || files.front().path.endsWith( qstr(".tgs"), Qt::CaseInsensitive); - }; - return isAlbum || (files.size() == 1 && !isSticker()); + return !isSticker; + } else if (!groupMediaInAlbums) { + return false; + } + const auto hasFiles = ranges::contains( + files, + PreparedFile::AlbumType::File, + &PreparedFile::type); + return !hasFiles; } int MaxAlbumItems() { diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h index 56e9781ecd..a7a64dd51a 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include #include namespace Ui { @@ -34,8 +35,15 @@ struct PreparedFileInformation { }; struct PreparedFile { + // File-s can be grouped if 'groupFiles'. + // File-s + Photo-s can be grouped if 'groupFiles && !sendImagesAsPhotos'. + // Photo-s can be grouped if '(groupFiles && !sendImagesAsPhotos) + // || (groupMediaInAlbums && sendImagesAsPhotos)'. + // Photo-s + Video-s can be grouped if 'groupMediaInAlbums + // && sendImagesAsPhotos'. + // Video-s can be grouped if 'groupMediaInAlbums'. enum class AlbumType { - None, + File, Photo, Video, }; @@ -48,10 +56,11 @@ struct PreparedFile { QString path; QByteArray content; QString mime; + int size = 0; std::unique_ptr information; QImage preview; QSize shownDimensions; - AlbumType type = AlbumType::None; + AlbumType type = AlbumType::File; }; struct PreparedList { @@ -73,16 +82,14 @@ struct PreparedList { std::vector order); void mergeToEnd(PreparedList &&other, bool cutToAlbumSize = false); - [[nodiscard]] bool canAddCaption(bool isAlbum) const; + [[nodiscard]] bool canAddCaption(bool groupMediaInAlbums) const; + [[nodiscard]] bool canBeSentInSlowmode() const; Error error = Error::None; QString errorData; std::vector files; std::deque filesToProcess; std::optional overrideSendImagesAsPhotos; - //bool someFilesForCompress = false; - //bool someAlbumIsPossible = false; - bool singleAlbumIsPossible = false; }; [[nodiscard]] int MaxAlbumItems(); 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 43f0e0911a..1e837150e6 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.cpp @@ -25,6 +25,11 @@ SingleFilePreview::SingleFilePreview( const PreparedFile &file) : RpWidget(parent) { preparePreview(file); + + auto h = _fileThumb.isNull() + ? (st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom()) + : (st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom()); + resize(width(), st::boxPhotoPadding.top() + h + st::msgShadow); } void SingleFilePreview::prepareThumb(const QImage &preview) { @@ -163,11 +168,4 @@ void SingleFilePreview::paintEvent(QPaintEvent *e) { p.drawTextLeft(x + nameleft, y + statustop, width(), _statusText); } -rpl::producer SingleFilePreview::desiredHeightValue() const { - auto h = _fileThumb.isNull() - ? (st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom()) - : (st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom()); - return rpl::single(st::boxPhotoPadding.top() + h + st::msgShadow); -} - } // 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 442106148a..bb06249dd2 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_single_file_preview.h @@ -19,8 +19,6 @@ public: QWidget *parent, const PreparedFile &file); - rpl::producer desiredHeightValue() const override; - protected: void paintEvent(QPaintEvent *e) override; 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 18b41cbb9e..3d88cbb350 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.cpp @@ -135,6 +135,8 @@ void SingleMediaPreview::preparePreview( _preview.setDevicePixelRatio(style::DevicePixelRatio()); prepareAnimatedPreview(animatedPreviewPath); + + resize(width(), st::boxPhotoPadding.top() + _previewHeight); } void SingleMediaPreview::prepareAnimatedPreview( @@ -228,8 +230,4 @@ void SingleMediaPreview::paintEvent(QPaintEvent *e) { } } -rpl::producer SingleMediaPreview::desiredHeightValue() const { - return rpl::single(st::boxPhotoPadding.top() + _previewHeight); -} - } // namespace Ui 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 17e035e8e8..8f61787d63 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.h @@ -38,8 +38,6 @@ public: return _canSendAsPhoto; } - rpl::producer desiredHeightValue() const override; - protected: void paintEvent(QPaintEvent *e) override;