From 93c6038992d1b4127be3e637f9f4495672f23311 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 24 Feb 2022 20:39:23 +0300 Subject: [PATCH] Start showing downloading items in Downloads. --- .../downloads/info_downloads_provider.cpp | 152 +++++++++++++++--- .../info/downloads/info_downloads_provider.h | 17 +- .../info/media/info_media_provider.cpp | 6 +- 3 files changed, 150 insertions(+), 25 deletions(-) diff --git a/Telegram/SourceFiles/info/downloads/info_downloads_provider.cpp b/Telegram/SourceFiles/info/downloads/info_downloads_provider.cpp index 1cd2b9e10..b379ef729 100644 --- a/Telegram/SourceFiles/info/downloads/info_downloads_provider.cpp +++ b/Telegram/SourceFiles/info/downloads/info_downloads_provider.cpp @@ -10,6 +10,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/media/info_media_widget.h" #include "info/media/info_media_list_section.h" #include "info/info_controller.h" +#include "data/data_download_manager.h" +#include "data/data_document.h" +#include "data/data_media_types.h" +#include "history/history_item.h" +#include "core/application.h" #include "storage/storage_shared_media.h" #include "layout/layout_selection.h" @@ -22,11 +27,6 @@ using namespace Media; Provider::Provider(not_null controller) : _controller(controller) { - //_controller->session().data().itemRemoved( - //) | rpl::start_with_next([this](auto item) { - // itemRemoved(item); - //}, _lifetime); - style::PaletteChanged( ) | rpl::start_with_next([=] { for (auto &layout : _layouts) { @@ -52,11 +52,10 @@ bool Provider::isPossiblyMyItem(not_null item) { } std::optional Provider::fullCount() { - return 0; + return _fullCount; } void Provider::restart() { - } void Provider::checkPreload( @@ -65,11 +64,44 @@ void Provider::checkPreload( not_null bottomLayout, bool preloadTop, bool preloadBottom) { - } void Provider::refreshViewer() { - + if (_fullCount) { + return; + } + auto &manager = Core::App().downloadManager(); + rpl::single( + rpl::empty_value() + ) | rpl::then( + manager.loadingListChanges() | rpl::to_empty + ) | rpl::start_with_next([=, &manager] { + auto copy = _downloading; + auto added = false; + for (const auto &id : manager.loadingList()) { + if (!id.done) { + const auto item = id.object.item; + if (!copy.remove(item)) { + added = true; + _downloading.emplace(item); + _elements.push_back(Element{ item, id.started }); + } + } + } + for (const auto &item : copy) { + _downloading.remove(item); + // #TODO downloads check if downloaded + _elements.erase( + ranges::remove(_elements, item, &Element::item), + end(_elements)); + } + if (added) { + ranges::sort(_elements, ranges::less(), &Element::started); + _refreshed.fire({}); + } else if (!copy.empty()) { + _refreshed.fire({}); + } + }, _lifetime); } rpl::producer<> Provider::refreshed() { @@ -77,8 +109,40 @@ rpl::producer<> Provider::refreshed() { } std::vector Provider::fillSections( - not_null delegate) { - return {}; + not_null delegate) { + markLayoutsStale(); + const auto guard = gsl::finally([&] { clearStaleLayouts(); }); + + if (_elements.empty()) { + return {}; + } + + auto result = std::vector(1, ListSection(Type::File)); + auto §ion = result.back(); + for (const auto &element : _elements) { + if (auto layout = getLayout(element, delegate)) { + section.addItem(layout); + } + } + section.finishSection(); + return result; +} + +void Provider::markLayoutsStale() { + for (auto &layout : _layouts) { + layout.second.stale = true; + } +} + +void Provider::clearStaleLayouts() { + for (auto i = _layouts.begin(); i != _layouts.end();) { + if (i->second.stale) { + _layoutRemoved.fire(i->second.item.get()); + i = _layouts.erase(i); + } else { + ++i; + } + } } rpl::producer> Provider::layoutRemoved() { @@ -90,22 +154,68 @@ BaseLayout *Provider::lookupLayout(const HistoryItem *item) { } bool Provider::isMyItem(not_null item) { - return false; + return _downloading.contains(item) || _downloaded.contains(item); } bool Provider::isAfter( - not_null a, - not_null b) { - return a < b; + not_null a, + not_null b) { + if (a != b) { + for (const auto &element : _elements) { + if (element.item == a) { + return false; + } else if (element.item == b) { + return true; + } + } + } + return false; +} + +BaseLayout *Provider::getLayout( + Element element, + not_null delegate) { + auto it = _layouts.find(element.item); + if (it == _layouts.end()) { + if (auto layout = createLayout(element, delegate)) { + layout->initDimensions(); + it = _layouts.emplace(element.item, std::move(layout)).first; + } else { + return nullptr; + } + } + it->second.stale = false; + return it->second.item.get(); +} + +std::unique_ptr Provider::createLayout( + Element element, + not_null delegate) { + const auto getFile = [&]() -> DocumentData* { + if (auto media = element.item->media()) { + return media->document(); + } + return nullptr; + }; + + auto &songSt = st::overviewFileLayout; + if (const auto file = getFile()) { + return std::make_unique( + delegate, + element.item, + file, + songSt); + } + return nullptr; } void Provider::applyDragSelection( - ListSelectedMap &selected, - not_null fromItem, - bool skipFrom, - not_null tillItem, - bool skipTill) { - + ListSelectedMap &selected, + not_null fromItem, + bool skipFrom, + not_null tillItem, + bool skipTill) { + // #TODO downloads } void Provider::saveState( diff --git a/Telegram/SourceFiles/info/downloads/info_downloads_provider.h b/Telegram/SourceFiles/info/downloads/info_downloads_provider.h index d30ae486b..f402a9f4a 100644 --- a/Telegram/SourceFiles/info/downloads/info_downloads_provider.h +++ b/Telegram/SourceFiles/info/downloads/info_downloads_provider.h @@ -62,11 +62,26 @@ public: private: struct Element { not_null item; - uint64 started = 0; + int64 started = 0; // unixtime * 1000 }; + + void itemRemoved(not_null item); + void markLayoutsStale(); + void clearStaleLayouts(); + + [[nodiscard]] Media::BaseLayout *getLayout( + Element element, + not_null delegate); + [[nodiscard]] std::unique_ptr createLayout( + Element element, + not_null delegate); + const not_null _controller; std::vector _elements; + std::optional _fullCount; + base::flat_set> _downloading; + base::flat_set> _downloaded; std::unordered_map, Media::CachedItem> _layouts; rpl::event_stream> _layoutRemoved; diff --git a/Telegram/SourceFiles/info/media/info_media_provider.cpp b/Telegram/SourceFiles/info/media/info_media_provider.cpp index 6dd2d8025..f4ff2bfc3 100644 --- a/Telegram/SourceFiles/info/media/info_media_provider.cpp +++ b/Telegram/SourceFiles/info/media/info_media_provider.cpp @@ -338,20 +338,20 @@ std::unique_ptr Provider::createLayout( if (!item) { return nullptr; } - auto getPhoto = [&]() -> PhotoData* { + const auto getPhoto = [&]() -> PhotoData* { if (const auto media = item->media()) { return media->photo(); } return nullptr; }; - auto getFile = [&]() -> DocumentData* { + const auto getFile = [&]() -> DocumentData* { if (auto media = item->media()) { return media->document(); } return nullptr; }; - auto &songSt = st::overviewFileLayout; + const auto &songSt = st::overviewFileLayout; using namespace Overview::Layout; switch (type) { case Type::Photo: