From 5589f5136959a689d990fa60f0a96418dcaa1622 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 17 Oct 2020 20:09:06 +0300 Subject: [PATCH] Allow delete / replace items in SendFilesBox. --- Telegram/SourceFiles/boxes/send_files_box.cpp | 147 +++++++++++------- Telegram/SourceFiles/boxes/send_files_box.h | 7 +- .../ui/chat/attach/attach_album_preview.cpp | 6 +- 3 files changed, 94 insertions(+), 66 deletions(-) diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index b0d0701273..1541aca0ca 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -153,6 +153,22 @@ object_ptr SendFilesBox::Block::takeWidget() { return object_ptr::fromRaw(_preview.get()); } +rpl::producer SendFilesBox::Block::itemDeleteRequest() const { + if (!_isAlbum) { + return rpl::never(); + } + const auto album = static_cast(_preview.get()); + return album->thumbDeleted(); +} + +rpl::producer SendFilesBox::Block::itemReplaceRequest() const { + if (!_isAlbum) { + return rpl::never(); + } + const auto album = static_cast(_preview.get()); + return album->thumbChanged(); +} + void SendFilesBox::Block::setSendWay(Ui::SendFilesWay way) { if (!_isAlbum) { return; @@ -238,52 +254,6 @@ void SendFilesBox::initPreview() { }, _dimensionsLifetime); } -void SendFilesBox::addThumbButtonHandlers(not_null wrap) { - // #TODO files - //_albumPreview->thumbDeleted( - //) | rpl::start_with_next([=](auto index) { - // _lastScrollTop = wrap->scrollTop(); - - // _list.files.erase(_list.files.begin() + index); - // applyAlbumOrder(); - - // if (_preview) { - // _preview->deleteLater(); - // } - // _albumPreview = nullptr; - - // refreshAllAfterAlbumChanges(); - //}, _albumPreview->lifetime()); - - //_albumPreview->thumbChanged( - //) | rpl::start_with_next([=](auto index) { - // _lastScrollTop = wrap->scrollTop(); - - // const auto callback = [=](FileDialog::OpenResult &&result) { - // FileDialogCallback( - // std::move(result), - // [=] (auto list) { - // _list.files[index] = std::move(list.files.front()); - // applyAlbumOrder(); - - // if (_preview) { - // _preview->deleteLater(); - // } - // _albumPreview = nullptr; - - // refreshAllAfterAlbumChanges(); - // }); - // }; - - // FileDialog::GetOpenPath( - // this, - // tr::lng_choose_file(tr::now), - // FileDialog::AllOrImagesFilter(), - // crl::guard(this, callback)); - - //}, _albumPreview->lifetime()); -} - void SendFilesBox::enqueueNextPrepare() { if (_preparing) { return; @@ -497,20 +467,6 @@ void SendFilesBox::generatePreviewFrom(int fromBlock) { Assert(fromItem <= _list.files.size()); auto albumStart = -1; - const auto gifPaused = [controller = _controller] { - return controller->isGifPausedAtLeastFor( - Window::GifPauseReason::Layer); - }; - const auto pushBlock = [&](int from, int till) { - _blocks.emplace_back( - _inner.data(), - &_list.files, - from, - till, - gifPaused, - _sendWay.current()); - _inner->add(_blocks.back().takeWidget()); - }; for (auto i = fromItem, till = int(_list.files.size()); i != till; ++i) { const auto type = _list.files[i].type; if (albumStart >= 0) { @@ -536,6 +492,77 @@ void SendFilesBox::generatePreviewFrom(int fromBlock) { } } +void SendFilesBox::pushBlock(int from, int till) { + const auto gifPaused = [controller = _controller] { + return controller->isGifPausedAtLeastFor( + Window::GifPauseReason::Layer); + }; + const auto index = int(_blocks.size()); + _blocks.emplace_back( + _inner.data(), + &_list.files, + from, + till, + gifPaused, + _sendWay.current()); + auto &block = _blocks.back(); + const auto widget = _inner->add(block.takeWidget()); + + block.itemDeleteRequest( + ) | rpl::filter([=] { + return !_removingIndex; + }) | rpl::start_with_next([=](int index) { + _removingIndex = from + index; + crl::on_main(this, [=] { + const auto index = base::take(_removingIndex).value_or(-1); + if (index < 0 || index >= _list.files.size()) { + return; + } + _list.files.erase(_list.files.begin() + index); + refreshAllAfterChanges(from); + }); + }, widget->lifetime()); + + block.itemReplaceRequest( + ) | rpl::start_with_next([=](int index) { + const auto replace = [=](Ui::PreparedList list) { + if (list.files.empty()) { + return; + } + _list.files[from + index] = std::move(list.files.front()); + refreshAllAfterChanges(from); + }; + const auto checkResult = [=](const Ui::PreparedList &list) { + if (_sendLimit != SendLimit::One) { + return true; + } + auto removing = std::move(_list.files[from + index]); + std::swap(_list.files[from + index], _list.files.back()); + _list.files.pop_back(); + const auto result = _list.canBeSentInSlowmodeWith(list); + _list.files.push_back(std::move(removing)); + std::swap(_list.files[from + index], _list.files.back()); + if (!result) { + Ui::Toast::Show(tr::lng_slowmode_no_many(tr::now)); + return false; + } + return true; + }; + const auto callback = [=](FileDialog::OpenResult &&result) { + FileDialogCallback( + std::move(result), + checkResult, + replace); + }; + + FileDialog::GetOpenPath( + this, + tr::lng_choose_file(tr::now), + FileDialog::AllOrImagesFilter(), + crl::guard(this, callback)); + }, widget->lifetime()); +} + void SendFilesBox::refreshControls() { refreshTitleText(); updateSendWayControlsVisibility(); diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index 2384852795..bde7ee2441 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -100,6 +100,9 @@ private: [[nodiscard]] int tillIndex() const; [[nodiscard]] object_ptr takeWidget(); + [[nodiscard]] rpl::producer itemDeleteRequest() const; + [[nodiscard]] rpl::producer itemReplaceRequest() const; + void setSendWay(Ui::SendFilesWay way); void applyAlbumOrder(); @@ -138,12 +141,11 @@ private: void updateControlsGeometry(); void updateCaptionPlaceholder(); - void addThumbButtonHandlers(not_null wrap); - bool canAddFiles(not_null data) const; bool addFiles(not_null data); bool addFiles(Ui::PreparedList list); void addFile(Ui::PreparedFile &&file); + void pushBlock(int from, int till); void openDialogToAddFileToAlbum(); void refreshAllAfterChanges(int fromItem); @@ -158,6 +160,7 @@ private: int _titleHeight = 0; Ui::PreparedList _list; + std::optional _removingIndex; SendLimit _sendLimit = SendLimit::Many; SendMenu::Type _sendMenuType = SendMenu::Type(); diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp index b90cd2609e..98b93813da 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_album_preview.cpp @@ -54,8 +54,8 @@ void AlbumPreview::updateFileRows() { } std::vector AlbumPreview::takeOrder() { - Expects(_thumbs.size() == _order.size()); - Expects(_itemsShownDimensions.size() == _order.size()); + //Expects(_thumbs.size() == _order.size()); + //Expects(_itemsShownDimensions.size() == _order.size()); auto reordered = std::vector>(); auto reorderedShownDimensions = std::vector(); @@ -82,8 +82,6 @@ auto AlbumPreview::generateOrderedLayout() const } std::vector AlbumPreview::defaultOrder(int count) const { - Expects(count > 0 || !_order.empty()); - if (count < 0) { count = _order.size(); }