data_reply_preview.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. #include "data/data_reply_preview.h"
  8. #include "data/data_file_origin.h"
  9. #include "data/data_document.h"
  10. #include "data/data_document_media.h"
  11. #include "data/data_photo.h"
  12. #include "data/data_photo_media.h"
  13. #include "ui/image/image.h"
  14. #include "styles/style_chat.h"
  15. namespace Data {
  16. ReplyPreview::ReplyPreview(not_null<DocumentData*> document)
  17. : _document(document) {
  18. }
  19. ReplyPreview::ReplyPreview(not_null<PhotoData*> photo)
  20. : _photo(photo) {
  21. }
  22. ReplyPreview::~ReplyPreview() = default;
  23. void ReplyPreview::prepare(
  24. not_null<Image*> image,
  25. Images::Options options,
  26. bool spoiler) {
  27. using namespace Images;
  28. if (image->isNull()) {
  29. return;
  30. }
  31. int w = image->width(), h = image->height();
  32. if (w <= 0) w = 1;
  33. if (h <= 0) h = 1;
  34. auto thumbSize = (w > h)
  35. ? QSize(
  36. w * st::historyReplyPreview / h,
  37. st::historyReplyPreview)
  38. : QSize(
  39. st::historyReplyPreview,
  40. h * st::historyReplyPreview / w);
  41. thumbSize *= style::DevicePixelRatio();
  42. options |= Option::TransparentBackground;
  43. auto outerSize = st::historyReplyPreview;
  44. auto original = spoiler
  45. ? image->original().scaled(
  46. { 40, 40 },
  47. Qt::KeepAspectRatio,
  48. Qt::SmoothTransformation)
  49. : image->original();
  50. auto prepared = Prepare(std::move(original), thumbSize, {
  51. .options = options | (spoiler ? Option::Blur : Option()),
  52. .outer = { outerSize, outerSize },
  53. });
  54. (spoiler ? _spoilered : _regular) = std::make_unique<Image>(
  55. std::move(prepared));
  56. _good = spoiler || ((options & Option::Blur) == 0);
  57. }
  58. Image *ReplyPreview::image(
  59. Data::FileOrigin origin,
  60. not_null<PeerData*> context,
  61. bool spoiler) {
  62. auto &image = spoiler ? _spoilered : _regular;
  63. auto &checked = spoiler ? _checkedSpoilered : _checkedRegular;
  64. if (checked) {
  65. return image.get();
  66. } else if (_document) {
  67. if (!image || (!_good && _document->hasThumbnail())) {
  68. if (!_documentMedia) {
  69. _documentMedia = _document->createMediaView();
  70. _documentMedia->thumbnailWanted(origin);
  71. }
  72. const auto thumbnail = _documentMedia->thumbnail();
  73. const auto option = _document->isVideoMessage()
  74. ? Images::Option::RoundCircle
  75. : Images::Option::None;
  76. if (spoiler) {
  77. if (const auto image = _documentMedia->thumbnailInline()) {
  78. prepare(image, option, true);
  79. } else if (thumbnail) {
  80. prepare(thumbnail, option, true);
  81. }
  82. } else if (thumbnail) {
  83. prepare(thumbnail, option);
  84. } else if (!image) {
  85. if (const auto image = _documentMedia->thumbnailInline()) {
  86. prepare(image, option | Images::Option::Blur);
  87. }
  88. }
  89. if (_good || !_document->hasThumbnail()) {
  90. checked = true;
  91. _documentMedia = nullptr;
  92. }
  93. }
  94. } else {
  95. Assert(_photo != nullptr);
  96. if (!image || !_good) {
  97. const auto inlineThumbnailBytes = _photo->inlineThumbnailBytes();
  98. if (!_photoMedia) {
  99. _photoMedia = _photo->createMediaView();
  100. }
  101. using Size = PhotoSize;
  102. const auto loadThumbnail = inlineThumbnailBytes.isEmpty()
  103. || (!spoiler
  104. && _photoMedia->autoLoadThumbnailAllowed(context));
  105. if (loadThumbnail) {
  106. _photoMedia->wanted(Size::Small, origin);
  107. }
  108. if (spoiler) {
  109. if (const auto blurred = _photoMedia->thumbnailInline()) {
  110. prepare(blurred, {}, true);
  111. } else if (const auto small = _photoMedia->image(Size::Small)) {
  112. prepare(small, {}, true);
  113. } else if (const auto large = _photoMedia->image(Size::Large)) {
  114. prepare(large, {}, true);
  115. }
  116. } else if (const auto small = _photoMedia->image(Size::Small)) {
  117. prepare(small, {});
  118. } else if (const auto large = _photoMedia->image(Size::Large)) {
  119. prepare(large, {});
  120. } else if (!image) {
  121. if (const auto blurred = _photoMedia->thumbnailInline()) {
  122. prepare(blurred, Images::Option::Blur);
  123. }
  124. }
  125. if (_good) {
  126. checked = true;
  127. _photoMedia = nullptr;
  128. }
  129. }
  130. }
  131. return image.get();
  132. }
  133. bool ReplyPreview::loaded(bool spoiler) const {
  134. return spoiler ? _checkedSpoilered : _checkedRegular;
  135. }
  136. } // namespace Data