mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-31 06:26:18 +00:00
Update API scheme to layer 183. Paid media.
This commit is contained in:
@@ -7,12 +7,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "data/data_media_types.h"
|
||||
|
||||
#include "base/random.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h" // CreateMedia.
|
||||
#include "history/history_location_manager.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
#include "history/view/history_view_item_preview.h"
|
||||
#include "history/view/media/history_view_extended_preview.h"
|
||||
#include "history/view/media/history_view_photo.h"
|
||||
#include "history/view/media/history_view_sticker.h"
|
||||
#include "history/view/media/history_view_gif.h"
|
||||
@@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "history/view/media/history_view_giveaway.h"
|
||||
#include "history/view/media/history_view_invoice.h"
|
||||
#include "history/view/media/history_view_media_generic.h"
|
||||
#include "history/view/media/history_view_media_grouped.h"
|
||||
#include "history/view/media/history_view_call.h"
|
||||
#include "history/view/media/history_view_web_page.h"
|
||||
#include "history/view/media/history_view_poll.h"
|
||||
@@ -261,48 +262,80 @@ template <typename MediaType>
|
||||
}
|
||||
|
||||
bool UpdateExtendedMedia(
|
||||
Invoice &invoice,
|
||||
std::unique_ptr<Media> &media,
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPMessageExtendedMedia &media) {
|
||||
return media.match([&](const MTPDmessageExtendedMediaPreview &data) {
|
||||
if (invoice.extendedMedia) {
|
||||
return false;
|
||||
const MTPMessageExtendedMedia &extended) {
|
||||
return extended.match([&](const MTPDmessageExtendedMediaPreview &data) {
|
||||
auto photo = (PhotoData*)nullptr;
|
||||
if (!media) {
|
||||
const auto id = base::RandomValue<PhotoId>();
|
||||
photo = item->history()->owner().photo(id);
|
||||
} else {
|
||||
photo = media->photo();
|
||||
if (!photo || !photo->extendedMediaPreview()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto changed = false;
|
||||
auto &preview = invoice.extendedPreview;
|
||||
auto size = QSize();
|
||||
auto thumbnail = QByteArray();
|
||||
auto videoDuration = TimeId();
|
||||
if (const auto &w = data.vw()) {
|
||||
const auto &h = data.vh();
|
||||
Assert(h.has_value());
|
||||
const auto dimensions = QSize(w->v, h->v);
|
||||
if (preview.dimensions != dimensions) {
|
||||
preview.dimensions = dimensions;
|
||||
size = QSize(w->v, h->v);
|
||||
if (!changed && photo->size(PhotoSize::Large) != size) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (const auto &thumb = data.vthumb()) {
|
||||
if (thumb->type() == mtpc_photoStrippedSize) {
|
||||
const auto bytes = thumb->c_photoStrippedSize().vbytes().v;
|
||||
if (preview.inlineThumbnailBytes != bytes) {
|
||||
preview.inlineThumbnailBytes = bytes;
|
||||
thumbnail = thumb->c_photoStrippedSize().vbytes().v;
|
||||
if (!changed && photo->inlineThumbnailBytes() != thumbnail) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (const auto &duration = data.vvideo_duration()) {
|
||||
if (preview.videoDuration != duration->v) {
|
||||
preview.videoDuration = duration->v;
|
||||
videoDuration = duration->v;
|
||||
if (photo->extendedMediaVideoDuration() != videoDuration) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
photo->setExtendedMediaPreview(size, thumbnail, videoDuration);
|
||||
}
|
||||
if (!media) {
|
||||
media = std::make_unique<MediaPhoto>(item, photo, true);
|
||||
}
|
||||
return changed;
|
||||
}, [&](const MTPDmessageExtendedMedia &data) {
|
||||
invoice.extendedMedia = HistoryItem::CreateMedia(
|
||||
item,
|
||||
data.vmedia());
|
||||
media = HistoryItem::CreateMedia(item, data.vmedia());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool UpdateExtendedMedia(
|
||||
Invoice &invoice,
|
||||
not_null<HistoryItem*> item,
|
||||
const QVector<MTPMessageExtendedMedia> &media) {
|
||||
auto changed = false;
|
||||
const auto count = int(media.size());
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
if (i < invoice.extendedMedia.size()) {
|
||||
invoice.extendedMedia.emplace_back();
|
||||
changed = true;
|
||||
}
|
||||
UpdateExtendedMedia(invoice.extendedMedia[i], item, media[i]);
|
||||
}
|
||||
if (count < invoice.extendedMedia.size()) {
|
||||
invoice.extendedMedia.resize(count);
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
TextForMimeData WithCaptionClipboardText(
|
||||
const QString &attachType,
|
||||
TextForMimeData &&caption) {
|
||||
@@ -344,11 +377,22 @@ Invoice ComputeInvoiceData(
|
||||
.isTest = data.is_test(),
|
||||
};
|
||||
if (const auto &media = data.vextended_media()) {
|
||||
UpdateExtendedMedia(result, item, *media);
|
||||
UpdateExtendedMedia(result, item, { *media });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Invoice ComputeInvoiceData(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPDmessageMediaPaidMedia &data) {
|
||||
auto result = Invoice{
|
||||
.amount = data.vstars_amount().v,
|
||||
.currency = Ui::kCreditsCurrency,
|
||||
};
|
||||
UpdateExtendedMedia(result, item, data.vextended_media().v);
|
||||
return result;
|
||||
}
|
||||
|
||||
Call ComputeCallData(const MTPDmessageActionPhoneCall &call) {
|
||||
auto result = Call();
|
||||
result.finishReason = [&] {
|
||||
@@ -424,6 +468,18 @@ GiveawayResults ComputeGiveawayResultsData(
|
||||
return result;
|
||||
}
|
||||
|
||||
bool HasExtendedMedia(const Invoice &invoice) {
|
||||
return !invoice.extendedMedia.empty();
|
||||
}
|
||||
|
||||
bool HasUnpaidMedia(const Invoice &invoice) {
|
||||
for (const auto &media : invoice.extendedMedia) {
|
||||
const auto photo = media->photo();
|
||||
return photo && photo->extendedMediaPreview();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Media::Media(not_null<HistoryItem*> parent) : _parent(parent) {
|
||||
}
|
||||
|
||||
@@ -1851,14 +1907,14 @@ MediaInvoice::MediaInvoice(
|
||||
.currency = data.currency,
|
||||
.title = data.title,
|
||||
.description = data.description,
|
||||
.extendedPreview = data.extendedPreview,
|
||||
.extendedMedia = (data.extendedMedia
|
||||
? data.extendedMedia->clone(parent)
|
||||
: nullptr),
|
||||
.photo = data.photo,
|
||||
.isTest = data.isTest,
|
||||
} {
|
||||
if (_invoice.extendedPreview && !_invoice.extendedMedia) {
|
||||
_invoice.extendedMedia.reserve(data.extendedMedia.size());
|
||||
for (auto &item : data.extendedMedia) {
|
||||
_invoice.extendedMedia.push_back(item->clone(parent));
|
||||
}
|
||||
if (HasUnpaidMedia(_invoice)) {
|
||||
Ui::PreloadImageSpoiler();
|
||||
}
|
||||
}
|
||||
@@ -1917,7 +1973,7 @@ bool MediaInvoice::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
bool MediaInvoice::updateExtendedMedia(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPMessageExtendedMedia &media) {
|
||||
const QVector<MTPMessageExtendedMedia> &media) {
|
||||
Expects(item == parent());
|
||||
|
||||
return UpdateExtendedMedia(_invoice, item, media);
|
||||
@@ -1927,15 +1983,15 @@ std::unique_ptr<HistoryView::Media> MediaInvoice::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
if (_invoice.extendedMedia) {
|
||||
return _invoice.extendedMedia->createView(
|
||||
if (_invoice.extendedMedia.size() == 1) {
|
||||
return _invoice.extendedMedia.front()->createView(
|
||||
message,
|
||||
realParent,
|
||||
replacing);
|
||||
} else if (_invoice.extendedPreview) {
|
||||
return std::make_unique<HistoryView::ExtendedPreview>(
|
||||
} else if (!_invoice.extendedMedia.empty()) {
|
||||
return std::make_unique<HistoryView::GroupedMedia>(
|
||||
message,
|
||||
&_invoice);
|
||||
_invoice.extendedMedia);
|
||||
}
|
||||
return std::make_unique<HistoryView::Invoice>(message, &_invoice);
|
||||
}
|
||||
|
@@ -84,19 +84,6 @@ struct Call {
|
||||
|
||||
};
|
||||
|
||||
struct ExtendedPreview {
|
||||
QByteArray inlineThumbnailBytes;
|
||||
QSize dimensions;
|
||||
TimeId videoDuration = -1;
|
||||
|
||||
[[nodiscard]] bool empty() const {
|
||||
return dimensions.isEmpty();
|
||||
}
|
||||
explicit operator bool() const {
|
||||
return !empty();
|
||||
}
|
||||
};
|
||||
|
||||
class Media;
|
||||
|
||||
struct Invoice {
|
||||
@@ -105,11 +92,12 @@ struct Invoice {
|
||||
QString currency;
|
||||
QString title;
|
||||
TextWithEntities description;
|
||||
ExtendedPreview extendedPreview;
|
||||
std::unique_ptr<Media> extendedMedia;
|
||||
std::vector<std::unique_ptr<Media>> extendedMedia;
|
||||
PhotoData *photo = nullptr;
|
||||
bool isTest = false;
|
||||
};
|
||||
[[nodiscard]] bool HasExtendedMedia(const Invoice &invoice);
|
||||
[[nodiscard]] bool HasUnpaidMedia(const Invoice &invoice);
|
||||
|
||||
struct GiveawayStart {
|
||||
std::vector<not_null<ChannelData*>> channels;
|
||||
@@ -207,7 +195,7 @@ public:
|
||||
virtual bool updateSentMedia(const MTPMessageMedia &media) = 0;
|
||||
virtual bool updateExtendedMedia(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPMessageExtendedMedia &media) {
|
||||
const QVector<MTPMessageExtendedMedia> &media) {
|
||||
return false;
|
||||
}
|
||||
virtual std::unique_ptr<HistoryView::Media> createView(
|
||||
@@ -524,7 +512,7 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
bool updateExtendedMedia(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPMessageExtendedMedia &media) override;
|
||||
const QVector<MTPMessageExtendedMedia> &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent,
|
||||
@@ -750,6 +738,9 @@ private:
|
||||
[[nodiscard]] Invoice ComputeInvoiceData(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPDmessageMediaInvoice &data);
|
||||
[[nodiscard]] Invoice ComputeInvoiceData(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPDmessageMediaPaidMedia &data);
|
||||
|
||||
[[nodiscard]] Call ComputeCallData(const MTPDmessageActionPhoneCall &call);
|
||||
|
||||
|
@@ -50,6 +50,38 @@ PhotoData::~PhotoData() {
|
||||
base::take(_videoSizes);
|
||||
}
|
||||
|
||||
void PhotoData::setFields(TimeId date, bool hasAttachedStickers) {
|
||||
_dateOrExtendedVideoDuration = date;
|
||||
_hasStickers = hasAttachedStickers;
|
||||
_extendedMediaPreview = false;
|
||||
}
|
||||
|
||||
void PhotoData::setExtendedMediaPreview(
|
||||
QSize dimensions,
|
||||
const QByteArray &inlineThumbnailBytes,
|
||||
TimeId videoDuration) {
|
||||
_extendedMediaPreview = true;
|
||||
updateImages(
|
||||
inlineThumbnailBytes,
|
||||
{},
|
||||
{},
|
||||
{ .location = { {}, dimensions.width(), dimensions.height() } },
|
||||
{},
|
||||
{},
|
||||
{});
|
||||
_dateOrExtendedVideoDuration = videoDuration + 1;
|
||||
}
|
||||
|
||||
bool PhotoData::extendedMediaPreview() const {
|
||||
return _extendedMediaPreview;
|
||||
}
|
||||
|
||||
std::optional<TimeId> PhotoData::extendedMediaVideoDuration() const {
|
||||
return (_extendedMediaPreview && _dateOrExtendedVideoDuration)
|
||||
? TimeId(_dateOrExtendedVideoDuration - 1)
|
||||
: std::optional<TimeId>();
|
||||
}
|
||||
|
||||
Data::Session &PhotoData::owner() const {
|
||||
return *_owner;
|
||||
}
|
||||
@@ -74,6 +106,10 @@ void PhotoData::load(
|
||||
load(PhotoSize::Large, origin, fromCloud, autoLoading);
|
||||
}
|
||||
|
||||
TimeId PhotoData::date() const {
|
||||
return _extendedMediaPreview ? 0 : _dateOrExtendedVideoDuration;
|
||||
}
|
||||
|
||||
bool PhotoData::loading() const {
|
||||
return loading(PhotoSize::Large);
|
||||
}
|
||||
|
@@ -53,6 +53,7 @@ public:
|
||||
|
||||
void automaticLoadSettingsChanged();
|
||||
|
||||
[[nodiscard]] TimeId date() const;
|
||||
[[nodiscard]] bool loading() const;
|
||||
[[nodiscard]] bool displayLoading() const;
|
||||
void cancel();
|
||||
@@ -89,6 +90,14 @@ public:
|
||||
[[nodiscard]] auto activeMediaView() const
|
||||
-> std::shared_ptr<Data::PhotoMedia>;
|
||||
|
||||
void setFields(TimeId date, bool hasAttachedStickers);
|
||||
void setExtendedMediaPreview(
|
||||
QSize dimensions,
|
||||
const QByteArray &inlineThumbnailBytes,
|
||||
TimeId videoDuration);
|
||||
[[nodiscard]] bool extendedMediaPreview() const;
|
||||
[[nodiscard]] std::optional<TimeId> extendedMediaVideoDuration() const;
|
||||
|
||||
void updateImages(
|
||||
const QByteArray &inlineThumbnailBytes,
|
||||
const ImageWithLocation &small,
|
||||
@@ -148,11 +157,10 @@ public:
|
||||
void setHasAttachedStickers(bool value);
|
||||
|
||||
// For now they return size of the 'large' image.
|
||||
int width() const;
|
||||
int height() const;
|
||||
[[nodiscard]] int width() const;
|
||||
[[nodiscard]] int height() const;
|
||||
|
||||
PhotoId id = 0;
|
||||
TimeId date = 0;
|
||||
|
||||
PeerData *peer = nullptr; // for chat and channel photos connection
|
||||
// geo, caption
|
||||
@@ -164,6 +172,8 @@ private:
|
||||
[[nodiscard]] const Data::CloudFile &videoFile(
|
||||
Data::PhotoSize size) const;
|
||||
|
||||
TimeId _dateOrExtendedVideoDuration = 0;
|
||||
|
||||
struct VideoSizes {
|
||||
Data::CloudFile small;
|
||||
Data::CloudFile large;
|
||||
@@ -177,6 +187,8 @@ private:
|
||||
int32 _dc = 0;
|
||||
uint64 _access = 0;
|
||||
bool _hasStickers = false;
|
||||
bool _extendedMediaPreview = false;
|
||||
|
||||
QByteArray _fileReference;
|
||||
std::unique_ptr<Data::ReplyPreview> _replyPreview;
|
||||
std::weak_ptr<Data::PhotoMedia> _media;
|
||||
|
@@ -3077,8 +3077,7 @@ void Session::photoApplyFields(
|
||||
return;
|
||||
}
|
||||
photo->setRemoteLocation(dc, access, fileReference);
|
||||
photo->date = date;
|
||||
photo->setHasAttachedStickers(hasStickers);
|
||||
photo->setFields(date, hasStickers);
|
||||
photo->updateImages(
|
||||
inlineThumbnailBytes,
|
||||
small,
|
||||
|
Reference in New Issue
Block a user