/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "base/timer.h" namespace Ui { struct DownloadBarProgress; struct DownloadBarContent; } // namespace Ui namespace Main { class Session; } // namespace Main namespace Data { // Used in serialization! enum class DownloadType { Document, Photo, }; // unixtime * 1000. using DownloadDate = int64; [[nodiscard]] inline TimeId DateFromDownloadDate(DownloadDate date) { return date / 1000; } struct DownloadId { uint64 objectId = 0; DownloadType type = DownloadType::Document; }; struct DownloadProgress { int64 ready = 0; int64 total = 0; }; inline constexpr bool operator==( const DownloadProgress &a, const DownloadProgress &b) { return (a.ready == b.ready) && (a.total == b.total); } struct DownloadObject { not_null item; DocumentData *document = nullptr; PhotoData *photo = nullptr; }; struct DownloadedId { DownloadId download; DownloadDate started = 0; QString path; int64 size = 0; FullMsgId itemId; uint64 peerAccessHash = 0; std::unique_ptr object; }; struct DownloadingId { DownloadObject object; DownloadDate started = 0; QString path; int64 ready = 0; int64 total = 0; bool hiddenByView = false; bool done = false; }; class DownloadManager final { public: DownloadManager(); ~DownloadManager(); void trackSession(not_null session); void itemVisibilitiesUpdated(not_null session); [[nodiscard]] DownloadDate computeNextStartDate(); void addLoading(DownloadObject object); void addLoaded( DownloadObject object, const QString &path, DownloadDate started); void clearIfFinished(); void deleteFiles(const std::vector &ids); void deleteAll(); [[nodiscard]] bool loadedHasNonCloudFile() const; [[nodiscard]] auto loadingList() const -> ranges::any_view; [[nodiscard]] DownloadProgress loadingProgress() const; [[nodiscard]] rpl::producer<> loadingListChanges() const; [[nodiscard]] auto loadingProgressValue() const -> rpl::producer; [[nodiscard]] bool loadingInProgress( Main::Session *onlyInSession = nullptr) const; void loadingStopWithConfirmation( Fn callback, Main::Session *onlyInSession = nullptr); [[nodiscard]] auto loadedList() -> ranges::any_view; [[nodiscard]] auto loadedAdded() const -> rpl::producer>; [[nodiscard]] auto loadedRemoved() const -> rpl::producer>; [[nodiscard]] rpl::producer<> loadedResolveDone() const; private: struct DeleteFilesDescriptor; struct SessionData { std::vector downloaded; std::vector downloading; int resolveNeeded = 0; int resolveSentRequests = 0; int resolveSentTotal = 0; rpl::lifetime lifetime; }; void check(not_null item); void check(not_null document); void check( SessionData &data, std::vector::iterator i); void changed(not_null item); void removed(not_null item); void detach(DownloadedId &id); void untrack(not_null session); void remove( SessionData &data, std::vector::iterator i); void cancel( SessionData &data, std::vector::iterator i); void clearLoading(); [[nodiscard]] SessionData &sessionData(not_null session); [[nodiscard]] const SessionData &sessionData( not_null session) const; [[nodiscard]] SessionData &sessionData( not_null item); [[nodiscard]] SessionData &sessionData(not_null document); void resolve(not_null session, SessionData &data); void resolveRequestsFinished( not_null session, SessionData &data); void checkFullResolveDone(); [[nodiscard]] not_null regenerateItem( const DownloadObject &previous); [[nodiscard]] not_null generateFakeItem( not_null document); [[nodiscard]] not_null generateItem( HistoryItem *previousItem, DocumentData *document, PhotoData *photo); void generateEntry(not_null session, DownloadedId &id); [[nodiscard]] HistoryItem *lookupLoadingItem( Main::Session *onlyInSession) const; void loadingStop(Main::Session *onlyInSession); void finishFilesDelete(DeleteFilesDescriptor &&descriptor); void writePostponed(not_null session); [[nodiscard]] Fn()> serializator( not_null session) const; [[nodiscard]] std::vector deserialize( not_null session) const; base::flat_map, SessionData> _sessions; base::flat_set> _loading; base::flat_set> _loadingDocuments; base::flat_set> _loadingDone; base::flat_set> _loaded; base::flat_set> _generated; base::flat_set> _generatedDocuments; TimeId _lastStartedBase = 0; int _lastStartedAdded = 0; rpl::event_stream<> _loadingListChanges; rpl::variable _loadingProgress; rpl::event_stream> _loadedAdded; rpl::event_stream> _loadedRemoved; rpl::variable _loadedResolveDone; base::Timer _clearLoadingTimer; }; [[nodiscard]] auto MakeDownloadBarProgress() -> rpl::producer; [[nodiscard]] rpl::producer MakeDownloadBarContent(); } // namespace Data