data_download_manager.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "base/timer.h"
  9. namespace Ui {
  10. struct DownloadBarProgress;
  11. struct DownloadBarContent;
  12. } // namespace Ui
  13. namespace Main {
  14. class Session;
  15. } // namespace Main
  16. namespace Data {
  17. // Used in serialization!
  18. enum class DownloadType {
  19. Document,
  20. Photo,
  21. };
  22. // unixtime * 1000.
  23. using DownloadDate = int64;
  24. [[nodiscard]] inline TimeId DateFromDownloadDate(DownloadDate date) {
  25. return date / 1000;
  26. }
  27. struct DownloadId {
  28. uint64 objectId = 0;
  29. DownloadType type = DownloadType::Document;
  30. };
  31. struct DownloadProgress {
  32. int64 ready = 0;
  33. int64 total = 0;
  34. };
  35. inline constexpr bool operator==(
  36. const DownloadProgress &a,
  37. const DownloadProgress &b) {
  38. return (a.ready == b.ready) && (a.total == b.total);
  39. }
  40. struct DownloadObject {
  41. not_null<HistoryItem*> item;
  42. DocumentData *document = nullptr;
  43. PhotoData *photo = nullptr;
  44. };
  45. struct DownloadedId {
  46. DownloadId download;
  47. DownloadDate started = 0;
  48. QString path;
  49. int64 size = 0;
  50. FullMsgId itemId;
  51. uint64 peerAccessHash = 0;
  52. std::unique_ptr<DownloadObject> object;
  53. };
  54. struct DownloadingId {
  55. DownloadObject object;
  56. DownloadDate started = 0;
  57. QString path;
  58. int64 ready = 0;
  59. int64 total = 0;
  60. bool hiddenByView = false;
  61. bool done = false;
  62. };
  63. class DownloadManager final {
  64. public:
  65. DownloadManager();
  66. ~DownloadManager();
  67. [[nodiscard]] bool empty() const;
  68. void trackSession(not_null<Main::Session*> session);
  69. void itemVisibilitiesUpdated(not_null<Main::Session*> session);
  70. [[nodiscard]] DownloadDate computeNextStartDate();
  71. void addLoading(DownloadObject object);
  72. void addLoaded(
  73. DownloadObject object,
  74. const QString &path,
  75. DownloadDate started);
  76. void clearIfFinished();
  77. void deleteFiles(const std::vector<GlobalMsgId> &ids);
  78. void deleteAll();
  79. [[nodiscard]] bool loadedHasNonCloudFile() const;
  80. [[nodiscard]] auto loadingList() const
  81. -> ranges::any_view<const DownloadingId*, ranges::category::input>;
  82. [[nodiscard]] DownloadProgress loadingProgress() const;
  83. [[nodiscard]] rpl::producer<> loadingListChanges() const;
  84. [[nodiscard]] auto loadingProgressValue() const
  85. -> rpl::producer<DownloadProgress>;
  86. [[nodiscard]] bool loadingInProgress(
  87. Main::Session *onlyInSession = nullptr) const;
  88. void loadingStopWithConfirmation(
  89. Fn<void()> callback,
  90. Main::Session *onlyInSession = nullptr);
  91. [[nodiscard]] auto loadedList()
  92. -> ranges::any_view<const DownloadedId*, ranges::category::input>;
  93. [[nodiscard]] auto loadedAdded() const
  94. -> rpl::producer<not_null<const DownloadedId*>>;
  95. [[nodiscard]] auto loadedRemoved() const
  96. -> rpl::producer<not_null<const HistoryItem*>>;
  97. [[nodiscard]] rpl::producer<> loadedResolveDone() const;
  98. private:
  99. struct DeleteFilesDescriptor;
  100. struct SessionData {
  101. std::vector<DownloadedId> downloaded;
  102. std::vector<DownloadingId> downloading;
  103. int resolveNeeded = 0;
  104. int resolveSentRequests = 0;
  105. int resolveSentTotal = 0;
  106. rpl::lifetime lifetime;
  107. };
  108. void check(not_null<const HistoryItem*> item);
  109. void check(not_null<DocumentData*> document);
  110. void check(
  111. SessionData &data,
  112. std::vector<DownloadingId>::iterator i);
  113. void changed(not_null<const HistoryItem*> item);
  114. void removed(not_null<const HistoryItem*> item);
  115. void detach(DownloadedId &id);
  116. void untrack(not_null<Main::Session*> session);
  117. void remove(
  118. SessionData &data,
  119. std::vector<DownloadingId>::iterator i);
  120. void cancel(
  121. SessionData &data,
  122. std::vector<DownloadingId>::iterator i);
  123. void clearLoading();
  124. [[nodiscard]] SessionData &sessionData(not_null<Main::Session*> session);
  125. [[nodiscard]] const SessionData &sessionData(
  126. not_null<Main::Session*> session) const;
  127. [[nodiscard]] SessionData &sessionData(
  128. not_null<const HistoryItem*> item);
  129. [[nodiscard]] SessionData &sessionData(not_null<DocumentData*> document);
  130. void resolve(not_null<Main::Session*> session, SessionData &data);
  131. void resolveRequestsFinished(
  132. not_null<Main::Session*> session,
  133. SessionData &data);
  134. void checkFullResolveDone();
  135. [[nodiscard]] not_null<HistoryItem*> regenerateItem(
  136. const DownloadObject &previous);
  137. [[nodiscard]] not_null<HistoryItem*> generateFakeItem(
  138. not_null<DocumentData*> document);
  139. [[nodiscard]] not_null<HistoryItem*> generateItem(
  140. HistoryItem *previousItem,
  141. DocumentData *document,
  142. PhotoData *photo);
  143. void generateEntry(not_null<Main::Session*> session, DownloadedId &id);
  144. [[nodiscard]] HistoryItem *lookupLoadingItem(
  145. Main::Session *onlyInSession) const;
  146. void loadingStop(Main::Session *onlyInSession);
  147. void finishFilesDelete(DeleteFilesDescriptor &&descriptor);
  148. void writePostponed(not_null<Main::Session*> session);
  149. [[nodiscard]] Fn<std::optional<QByteArray>()> serializator(
  150. not_null<Main::Session*> session) const;
  151. [[nodiscard]] std::vector<DownloadedId> deserialize(
  152. not_null<Main::Session*> session) const;
  153. base::flat_map<not_null<Main::Session*>, SessionData> _sessions;
  154. base::flat_set<not_null<const HistoryItem*>> _loading;
  155. base::flat_set<not_null<DocumentData*>> _loadingDocuments;
  156. base::flat_set<not_null<const HistoryItem*>> _loadingDone;
  157. base::flat_set<not_null<const HistoryItem*>> _loaded;
  158. base::flat_set<not_null<HistoryItem*>> _generated;
  159. base::flat_set<not_null<DocumentData*>> _generatedDocuments;
  160. TimeId _lastStartedBase = 0;
  161. int _lastStartedAdded = 0;
  162. rpl::event_stream<> _loadingListChanges;
  163. rpl::variable<DownloadProgress> _loadingProgress;
  164. rpl::event_stream<not_null<const DownloadedId*>> _loadedAdded;
  165. rpl::event_stream<not_null<const HistoryItem*>> _loadedRemoved;
  166. rpl::variable<bool> _loadedResolveDone;
  167. base::Timer _clearLoadingTimer;
  168. };
  169. [[nodiscard]] auto MakeDownloadBarProgress()
  170. -> rpl::producer<Ui::DownloadBarProgress>;
  171. [[nodiscard]] rpl::producer<Ui::DownloadBarContent> MakeDownloadBarContent();
  172. } // namespace Data