localimageloader.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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/variant.h"
  9. #include "api/api_common.h"
  10. namespace Ui {
  11. struct PreparedFileInformation;
  12. } // namespace Ui
  13. namespace Main {
  14. class Session;
  15. } // namespace Main
  16. // Load files up to 2'000 MB.
  17. constexpr auto kFileSizeLimit = 2'000 * int64(1024 * 1024);
  18. // Load files up to 4'000 MB.
  19. constexpr auto kFileSizePremiumLimit = 4'000 * int64(1024 * 1024);
  20. extern const char kOptionSendLargePhotos[];
  21. [[nodiscard]] int PhotoSideLimit();
  22. enum class SendMediaType {
  23. Photo,
  24. Audio,
  25. Round,
  26. File,
  27. ThemeFile,
  28. Secure,
  29. };
  30. using TaskId = void*; // no interface, just id
  31. inline constexpr auto kEmptyTaskId = TaskId();
  32. class Task {
  33. public:
  34. virtual void process() = 0; // is executed in a separate thread
  35. virtual void finish() = 0; // is executed in the same as TaskQueue thread
  36. virtual ~Task() = default;
  37. TaskId id() const {
  38. return static_cast<TaskId>(const_cast<Task*>(this));
  39. }
  40. };
  41. class TaskQueueWorker;
  42. class TaskQueue : public QObject {
  43. Q_OBJECT
  44. public:
  45. explicit TaskQueue(crl::time stopTimeoutMs = 0); // <= 0 - never stop worker
  46. TaskId addTask(std::unique_ptr<Task> &&task);
  47. void addTasks(std::vector<std::unique_ptr<Task>> &&tasks);
  48. void cancelTask(TaskId id); // this task finish() won't be called
  49. ~TaskQueue();
  50. Q_SIGNALS:
  51. void taskAdded();
  52. public Q_SLOTS:
  53. void onTaskProcessed();
  54. void stop();
  55. private:
  56. friend class TaskQueueWorker;
  57. void wakeThread();
  58. std::deque<std::unique_ptr<Task>> _tasksToProcess;
  59. std::deque<std::unique_ptr<Task>> _tasksToFinish;
  60. TaskId _taskInProcessId = TaskId();
  61. QMutex _tasksToProcessMutex, _tasksToFinishMutex;
  62. QThread *_thread = nullptr;
  63. TaskQueueWorker *_worker = nullptr;
  64. QTimer *_stopTimer = nullptr;
  65. };
  66. class TaskQueueWorker : public QObject {
  67. Q_OBJECT
  68. public:
  69. TaskQueueWorker(TaskQueue *queue) : _queue(queue) {
  70. }
  71. Q_SIGNALS:
  72. void taskProcessed();
  73. public Q_SLOTS:
  74. void onTaskAdded();
  75. private:
  76. TaskQueue *_queue;
  77. bool _inTaskAdded = false;
  78. };
  79. struct SendingAlbum {
  80. struct Item {
  81. explicit Item(TaskId taskId);
  82. TaskId taskId = kEmptyTaskId;
  83. uint64 randomId = 0;
  84. FullMsgId msgId;
  85. std::optional<MTPInputSingleMedia> media;
  86. };
  87. SendingAlbum();
  88. void fillMedia(
  89. not_null<HistoryItem*> item,
  90. const MTPInputMedia &media,
  91. uint64 randomId);
  92. void refreshMediaCaption(not_null<HistoryItem*> item);
  93. void removeItem(not_null<HistoryItem*> item);
  94. uint64 groupId = 0;
  95. std::vector<Item> items;
  96. Api::SendOptions options;
  97. bool sent = false;
  98. };
  99. struct FileLoadTo {
  100. FileLoadTo(
  101. PeerId peer,
  102. Api::SendOptions options,
  103. FullReplyTo replyTo,
  104. MsgId replaceMediaOf)
  105. : peer(peer)
  106. , options(options)
  107. , replyTo(replyTo)
  108. , replaceMediaOf(replaceMediaOf) {
  109. }
  110. PeerId peer;
  111. Api::SendOptions options;
  112. FullReplyTo replyTo;
  113. MsgId replaceMediaOf;
  114. };
  115. using UploadFileParts = std::vector<QByteArray>;
  116. struct FilePrepareDescriptor {
  117. TaskId taskId = kEmptyTaskId;
  118. base::required<uint64> id;
  119. SendMediaType type = SendMediaType::File;
  120. FileLoadTo to = { PeerId(), Api::SendOptions(), FullReplyTo(), MsgId() };
  121. TextWithTags caption;
  122. bool spoiler = false;
  123. std::shared_ptr<SendingAlbum> album;
  124. };
  125. struct FilePrepareResult {
  126. explicit FilePrepareResult(FilePrepareDescriptor &&descriptor);
  127. TaskId taskId = kEmptyTaskId;
  128. uint64 id = 0;
  129. FileLoadTo to;
  130. std::shared_ptr<SendingAlbum> album;
  131. SendMediaType type = SendMediaType::File;
  132. QString filepath;
  133. QByteArray content;
  134. QString filename;
  135. QString filemime;
  136. int64 filesize = 0;
  137. UploadFileParts fileparts;
  138. QByteArray filemd5;
  139. int64 partssize = 0;
  140. uint64 thumbId = 0; // id is always file-id of media, thumbId is file-id of thumb ( == id for photos)
  141. QString thumbname;
  142. UploadFileParts thumbparts;
  143. QByteArray thumbbytes;
  144. QByteArray thumbmd5;
  145. QImage thumb;
  146. QImage goodThumbnail;
  147. QByteArray goodThumbnailBytes;
  148. MTPPhoto photo = MTP_photoEmpty(MTP_long(0));
  149. MTPDocument document = MTP_documentEmpty(MTP_long(0));
  150. PreparedPhotoThumbs photoThumbs;
  151. TextWithTags caption;
  152. bool spoiler = false;
  153. std::vector<MTPInputDocument> attachedStickers;
  154. std::shared_ptr<FilePrepareResult> videoCover;
  155. void setFileData(const QByteArray &filedata);
  156. void setThumbData(const QByteArray &thumbdata);
  157. };
  158. [[nodiscard]] std::shared_ptr<FilePrepareResult> MakePreparedFile(
  159. FilePrepareDescriptor &&descriptor);
  160. class FileLoadTask final : public Task {
  161. public:
  162. static std::unique_ptr<Ui::PreparedFileInformation> ReadMediaInformation(
  163. const QString &filepath,
  164. const QByteArray &content,
  165. const QString &filemime);
  166. static bool FillImageInformation(
  167. QImage &&image,
  168. bool animated,
  169. std::unique_ptr<Ui::PreparedFileInformation> &result,
  170. QByteArray content = {},
  171. QByteArray format = {});
  172. FileLoadTask(
  173. not_null<Main::Session*> session,
  174. const QString &filepath,
  175. const QByteArray &content,
  176. std::unique_ptr<Ui::PreparedFileInformation> information,
  177. std::unique_ptr<FileLoadTask> videoCover,
  178. SendMediaType type,
  179. const FileLoadTo &to,
  180. const TextWithTags &caption,
  181. bool spoiler,
  182. std::shared_ptr<SendingAlbum> album = nullptr,
  183. uint64 idOverride = 0);
  184. FileLoadTask(
  185. not_null<Main::Session*> session,
  186. const QByteArray &voice,
  187. crl::time duration,
  188. const VoiceWaveform &waveform,
  189. bool video,
  190. const FileLoadTo &to,
  191. const TextWithTags &caption);
  192. ~FileLoadTask();
  193. uint64 fileid() const {
  194. return _id;
  195. }
  196. struct Args {
  197. bool generateGoodThumbnail = true;
  198. };
  199. void process(Args &&args);
  200. void process() override {
  201. process({});
  202. }
  203. void finish() override;
  204. [[nodiscard]] auto peekResult() const
  205. -> const std::shared_ptr<FilePrepareResult> &;
  206. private:
  207. static bool CheckForSong(
  208. const QString &filepath,
  209. const QByteArray &content,
  210. std::unique_ptr<Ui::PreparedFileInformation> &result);
  211. static bool CheckForVideo(
  212. const QString &filepath,
  213. const QByteArray &content,
  214. std::unique_ptr<Ui::PreparedFileInformation> &result);
  215. static bool CheckForImage(
  216. const QString &filepath,
  217. const QByteArray &content,
  218. std::unique_ptr<Ui::PreparedFileInformation> &result);
  219. template <typename Mimes, typename Extensions>
  220. static bool CheckMimeOrExtensions(const QString &filepath, const QString &filemime, Mimes &mimes, Extensions &extensions);
  221. std::unique_ptr<Ui::PreparedFileInformation> readMediaInformation(const QString &filemime) const;
  222. void removeFromAlbum();
  223. uint64 _id = 0;
  224. base::weak_ptr<Main::Session> _session;
  225. MTP::DcId _dcId = 0;
  226. FileLoadTo _to;
  227. const std::shared_ptr<SendingAlbum> _album;
  228. QString _filepath;
  229. QByteArray _content;
  230. std::unique_ptr<FileLoadTask> _videoCover;
  231. std::unique_ptr<Ui::PreparedFileInformation> _information;
  232. crl::time _duration = 0;
  233. VoiceWaveform _waveform;
  234. SendMediaType _type;
  235. TextWithTags _caption;
  236. bool _spoiler = false;
  237. std::shared_ptr<FilePrepareResult> _result;
  238. };