mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Update API scheme on layer 166.
This commit is contained in:
parent
744c1b925e
commit
926aae6847
18 changed files with 801 additions and 75 deletions
|
@ -677,6 +677,8 @@ PRIVATE
|
|||
history/view/media/history_view_game.h
|
||||
history/view/media/history_view_gif.cpp
|
||||
history/view/media/history_view_gif.h
|
||||
history/view/media/history_view_giveaway.cpp
|
||||
history/view/media/history_view_giveaway.h
|
||||
history/view/media/history_view_invoice.cpp
|
||||
history/view/media/history_view_invoice.h
|
||||
history/view/media/history_view_large_emoji.cpp
|
||||
|
|
|
@ -2076,13 +2076,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
"lng_prize_title" = "Congratulations!";
|
||||
"lng_prize_about" = "You won a prize in a giveaway organized by {channel}.";
|
||||
"lng_prize_duration" = "Your prize is **Telegram Premium** subscription for {duration}.";
|
||||
"lng_prize_duration" = "Your prize is a **Telegram Premium** subscription for {duration}.";
|
||||
"lng_prize_gift_about" = "You've received a gift from {channel}.";
|
||||
"lng_prize_gift_duration" = "Your gift is a **Telegram Premium** subscription for {duration}.";
|
||||
"lng_prize_open" = "Open Gift Link";
|
||||
|
||||
"lng_prizes_title#one" = "Giveaway Prize";
|
||||
"lng_prizes_title#other" = "Giveaway Prizes";
|
||||
"lng_prizes_about#one" = "{count} Telegram Premium Subscription for {duration}.";
|
||||
"lng_prizes_about#other" = "{count} Telegram Premium Subscriptions for {duration}.";
|
||||
"lng_prizes_about#one" = "**{count}** Telegram Premium Subscription for {duration}.";
|
||||
"lng_prizes_about#other" = "**{count}** Telegram Premium Subscriptions for {duration}.";
|
||||
"lng_prizes_participants" = "Participants";
|
||||
"lng_prizes_participants_all#one" = "All subscribers of the channel:";
|
||||
"lng_prizes_participants_all#other" = "All subscribers of the channels:";
|
||||
|
|
|
@ -2134,15 +2134,16 @@ void ApiWrap::saveDraftsToCloud() {
|
|||
}
|
||||
|
||||
auto flags = MTPmessages_SaveDraft::Flags(0);
|
||||
auto replyFlags = MTPDinputReplyToMessage::Flags(0);
|
||||
auto &textWithTags = cloudDraft->textWithTags;
|
||||
if (cloudDraft->previewState != Data::PreviewState::Allowed) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_no_webpage;
|
||||
}
|
||||
if (cloudDraft->msgId) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_reply_to_msg_id;
|
||||
}
|
||||
if (cloudDraft->topicRootId) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_top_msg_id;
|
||||
if (cloudDraft->msgId || cloudDraft->topicRootId) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_reply_to;
|
||||
if (cloudDraft->topicRootId) {
|
||||
replyFlags |= MTPDinputReplyToMessage::Flag::f_top_msg_id;
|
||||
}
|
||||
}
|
||||
if (!textWithTags.tags.isEmpty()) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_entities;
|
||||
|
@ -2155,8 +2156,15 @@ void ApiWrap::saveDraftsToCloud() {
|
|||
history->startSavingCloudDraft(topicRootId);
|
||||
cloudDraft->saveRequestId = request(MTPmessages_SaveDraft(
|
||||
MTP_flags(flags),
|
||||
MTP_int(cloudDraft->msgId),
|
||||
MTP_int(cloudDraft->topicRootId),
|
||||
MTP_inputReplyToMessage(
|
||||
MTP_flags(replyFlags),
|
||||
MTP_int(cloudDraft->msgId
|
||||
? cloudDraft->msgId
|
||||
: cloudDraft->topicRootId),
|
||||
MTP_int(cloudDraft->topicRootId),
|
||||
MTPInputPeer(), // reply_to_peer_id
|
||||
MTPstring(), // quote_text
|
||||
MTPVector<MTPMessageEntity>()), // quote_entities
|
||||
history->peer->input,
|
||||
MTP_string(textWithTags.text),
|
||||
entities
|
||||
|
|
|
@ -64,7 +64,18 @@ void ApplyPeerCloudDraft(
|
|||
session,
|
||||
draft.ventities().value_or_empty()))
|
||||
};
|
||||
const auto replyTo = draft.vreply_to_msg_id().value_or_empty();
|
||||
auto replyTo = MsgId();
|
||||
if (const auto reply = draft.vreply_to()) {
|
||||
reply->match([&](const MTPDmessageReplyHeader &data) {
|
||||
if (!data.vreply_to_peer_id()
|
||||
|| (peerFromMTP(*data.vreply_to_peer_id()) == peerId)) {
|
||||
replyTo = data.vreply_to_msg_id().value_or_empty();
|
||||
} else {
|
||||
// #TODO replies
|
||||
}
|
||||
}, [&](const MTPDmessageReplyStoryHeader &data) {
|
||||
});
|
||||
}
|
||||
auto cloudDraft = std::make_unique<Draft>(
|
||||
textWithTags,
|
||||
replyTo,
|
||||
|
|
|
@ -45,12 +45,15 @@ MTPInputReplyTo ReplyToForMTP(
|
|||
}
|
||||
} else if (replyTo.msgId || replyTo.topicRootId) {
|
||||
using Flag = MTPDinputReplyToMessage::Flag;
|
||||
return MTP_inputReplyToMessage(
|
||||
return MTP_inputReplyToMessage( // #TODO replies
|
||||
(replyTo.topicRootId
|
||||
? MTP_flags(Flag::f_top_msg_id)
|
||||
: MTP_flags(0)),
|
||||
MTP_int(replyTo.msgId ? replyTo.msgId : replyTo.topicRootId),
|
||||
MTP_int(replyTo.topicRootId));
|
||||
MTP_int(replyTo.topicRootId),
|
||||
MTPInputPeer(), // reply_to_peer_id
|
||||
MTPstring(), // quote_text
|
||||
MTPVector<MTPMessageEntity>()); // quote_entities
|
||||
}
|
||||
return MTPInputReplyTo();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/view/media/history_view_contact.h"
|
||||
#include "history/view/media/history_view_location.h"
|
||||
#include "history/view/media/history_view_game.h"
|
||||
#include "history/view/media/history_view_giveaway.h"
|
||||
#include "history/view/media/history_view_invoice.h"
|
||||
#include "history/view/media/history_view_call.h"
|
||||
#include "history/view/media/history_view_web_page.h"
|
||||
|
@ -361,6 +362,22 @@ Call ComputeCallData(const MTPDmessageActionPhoneCall &call) {
|
|||
return result;
|
||||
}
|
||||
|
||||
Giveaway ComputeGiveawayData(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPDmessageMediaGiveaway &data) {
|
||||
auto result = Giveaway{
|
||||
.untilDate = data.vuntil_date().v,
|
||||
.quantity = data.vquantity().v,
|
||||
.months = data.vmonths().v,
|
||||
};
|
||||
result.channels.reserve(data.vchannels().v.size());
|
||||
const auto owner = &item->history()->owner();
|
||||
for (const auto &id : data.vchannels().v) {
|
||||
result.channels.push_back(owner->channel(ChannelId(id)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Media::Media(not_null<HistoryItem*> parent) : _parent(parent) {
|
||||
}
|
||||
|
||||
|
@ -420,6 +437,10 @@ bool Media::storyMention() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
const Giveaway *Media::giveaway() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Media::uploading() const {
|
||||
return false;
|
||||
}
|
||||
|
@ -2144,4 +2165,50 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
|
|||
}
|
||||
}
|
||||
|
||||
MediaGiveaway::MediaGiveaway(
|
||||
not_null<HistoryItem*> parent,
|
||||
const Giveaway &data)
|
||||
: Media(parent)
|
||||
, _giveaway(data) {
|
||||
}
|
||||
|
||||
std::unique_ptr<Media> MediaGiveaway::clone(not_null<HistoryItem*> parent) {
|
||||
return std::make_unique<MediaGiveaway>(parent, _giveaway);
|
||||
}
|
||||
|
||||
const Giveaway *MediaGiveaway::giveaway() const {
|
||||
return &_giveaway;
|
||||
}
|
||||
|
||||
TextWithEntities MediaGiveaway::notificationText() const {
|
||||
return {
|
||||
.text = tr::lng_prizes_title(tr::now, lt_count, _giveaway.quantity),
|
||||
};
|
||||
}
|
||||
|
||||
QString MediaGiveaway::pinnedTextSubstring() const {
|
||||
return QString::fromUtf8("\xC2\xAB")
|
||||
+ notificationText().text
|
||||
+ QString::fromUtf8("\xC2\xBB");
|
||||
}
|
||||
|
||||
TextForMimeData MediaGiveaway::clipboardText() const {
|
||||
return TextForMimeData();
|
||||
}
|
||||
|
||||
bool MediaGiveaway::updateInlineResultMedia(const MTPMessageMedia &media) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MediaGiveaway::updateSentMedia(const MTPMessageMedia &media) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaGiveaway::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
return std::make_unique<HistoryView::Giveaway>(message, &_giveaway);
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -90,6 +90,14 @@ struct Invoice {
|
|||
bool isTest = false;
|
||||
};
|
||||
|
||||
struct Giveaway {
|
||||
std::vector<not_null<ChannelData*>> channels;
|
||||
TimeId untilDate = 0;
|
||||
int quantity = 0;
|
||||
int months = 0;
|
||||
bool all = false;
|
||||
};
|
||||
|
||||
class Media {
|
||||
public:
|
||||
Media(not_null<HistoryItem*> parent);
|
||||
|
@ -116,6 +124,7 @@ public:
|
|||
virtual FullStoryId storyId() const;
|
||||
virtual bool storyExpired(bool revalidate = false);
|
||||
virtual bool storyMention() const;
|
||||
virtual const Giveaway *giveaway() const;
|
||||
|
||||
virtual bool uploading() const;
|
||||
virtual Storage::SharedMediaTypesMask sharedMediaTypes() const;
|
||||
|
@ -605,6 +614,32 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class MediaGiveaway final : public Media {
|
||||
public:
|
||||
MediaGiveaway(
|
||||
not_null<HistoryItem*> parent,
|
||||
const Giveaway &data);
|
||||
|
||||
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
|
||||
|
||||
const Giveaway *giveaway() const override;
|
||||
|
||||
TextWithEntities notificationText() const override;
|
||||
QString pinnedTextSubstring() const override;
|
||||
TextForMimeData clipboardText() const override;
|
||||
|
||||
bool updateInlineResultMedia(const MTPMessageMedia &media) override;
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
private:
|
||||
Giveaway _giveaway;
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] TextForMimeData WithCaptionClipboardText(
|
||||
const QString &attachType,
|
||||
TextForMimeData &&caption);
|
||||
|
@ -615,4 +650,8 @@ private:
|
|||
|
||||
[[nodiscard]] Call ComputeCallData(const MTPDmessageActionPhoneCall &call);
|
||||
|
||||
[[nodiscard]] Giveaway ComputeGiveawayData(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPDmessageMediaGiveaway &data);
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -576,6 +576,18 @@ Poll ParsePoll(const MTPDmessageMediaPoll &data) {
|
|||
return result;
|
||||
}
|
||||
|
||||
Giveaway ParseGiveaway(const MTPDmessageMediaGiveaway &data) {
|
||||
auto result = Giveaway{
|
||||
.untilDate = data.vuntil_date().v,
|
||||
.quantity = data.vquantity().v,
|
||||
.months = data.vmonths().v,
|
||||
};
|
||||
for (const auto &id : data.vchannels().v) {
|
||||
result.channels.push_back(ChannelId(id));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UserpicsSlice ParseUserpicsSlice(
|
||||
const MTPVector<MTPPhoto> &data,
|
||||
int baseIndex) {
|
||||
|
@ -1057,7 +1069,9 @@ Media ParseMedia(
|
|||
}, [](const MTPDmessageMediaDice &data) {
|
||||
// #TODO dice
|
||||
}, [](const MTPDmessageMediaStory &data) {
|
||||
// #TODO stories export
|
||||
// #TODO export stories
|
||||
}, [&](const MTPDmessageMediaGiveaway &data) {
|
||||
result.content = ParseGiveaway(data);
|
||||
}, [](const MTPDmessageMediaEmpty &data) {});
|
||||
return result;
|
||||
}
|
||||
|
@ -1298,6 +1312,14 @@ ServiceAction ParseServiceAction(
|
|||
content.peerId = ParsePeerId(data.vpeer());
|
||||
content.buttonId = data.vbutton_id().v;
|
||||
result.content = content;
|
||||
}, [&](const MTPDmessageActionGiftCode &data) {
|
||||
auto content = ActionGiftCode();
|
||||
content.boostPeerId = data.vboost_peer()
|
||||
? peerFromMTP(*data.vboost_peer())
|
||||
: PeerId();
|
||||
content.viaGiveaway = data.is_via_giveaway();
|
||||
content.months = data.vmonths().v;
|
||||
content.code = data.vslug().v;
|
||||
}, [](const MTPDmessageActionEmpty &data) {});
|
||||
return result;
|
||||
}
|
||||
|
@ -1358,15 +1380,19 @@ Message ParseMessage(
|
|||
}
|
||||
if (const auto replyTo = data.vreply_to()) {
|
||||
replyTo->match([&](const MTPDmessageReplyHeader &data) {
|
||||
result.replyToMsgId = data.vreply_to_msg_id().v;
|
||||
result.replyToPeerId = data.vreply_to_peer_id()
|
||||
? ParsePeerId(*data.vreply_to_peer_id())
|
||||
: 0;
|
||||
if (result.replyToPeerId == result.peerId) {
|
||||
result.replyToPeerId = 0;
|
||||
if (const auto replyToMsg = data.vreply_to_msg_id()) {
|
||||
result.replyToMsgId = replyToMsg->v;
|
||||
result.replyToPeerId = data.vreply_to_peer_id()
|
||||
? ParsePeerId(*data.vreply_to_peer_id())
|
||||
: 0;
|
||||
if (result.replyToPeerId == result.peerId) {
|
||||
result.replyToPeerId = 0;
|
||||
}
|
||||
} else {
|
||||
// #TODO export replies
|
||||
}
|
||||
}, [&](const MTPDmessageReplyStoryHeader &data) {
|
||||
// #TODO stories export
|
||||
// #TODO export stories
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1410,12 +1436,16 @@ Message ParseMessage(
|
|||
}
|
||||
if (const auto replyTo = data.vreply_to()) {
|
||||
replyTo->match([&](const MTPDmessageReplyHeader &data) {
|
||||
result.replyToMsgId = data.vreply_to_msg_id().v;
|
||||
result.replyToPeerId = data.vreply_to_peer_id()
|
||||
? ParsePeerId(*data.vreply_to_peer_id())
|
||||
: PeerId(0);
|
||||
if (const auto replyToMsg = data.vreply_to_msg_id()) {
|
||||
result.replyToMsgId = replyToMsg->v;
|
||||
result.replyToPeerId = data.vreply_to_peer_id()
|
||||
? ParsePeerId(*data.vreply_to_peer_id())
|
||||
: PeerId(0);
|
||||
} else {
|
||||
// #TODO export replies
|
||||
}
|
||||
}, [&](const MTPDmessageReplyStoryHeader &data) {
|
||||
// #TODO stories export
|
||||
// #TODO export stories
|
||||
});
|
||||
}
|
||||
if (const auto viaBotId = data.vvia_bot_id()) {
|
||||
|
|
|
@ -196,6 +196,13 @@ struct Poll {
|
|||
bool closed = false;
|
||||
};
|
||||
|
||||
struct Giveaway {
|
||||
std::vector<ChannelId> channels;
|
||||
TimeId untilDate = 0;
|
||||
int quantity = 0;
|
||||
int months = 0;
|
||||
};
|
||||
|
||||
struct UserpicsSlice {
|
||||
std::vector<Photo> list;
|
||||
};
|
||||
|
@ -325,6 +332,7 @@ struct Media {
|
|||
Game,
|
||||
Invoice,
|
||||
Poll,
|
||||
Giveaway,
|
||||
UnsupportedMedia> content;
|
||||
TimeId ttl = 0;
|
||||
|
||||
|
@ -527,6 +535,13 @@ struct ActionSetChatWallPaper {
|
|||
struct ActionSetSameChatWallPaper {
|
||||
};
|
||||
|
||||
struct ActionGiftCode {
|
||||
QByteArray code;
|
||||
PeerId boostPeerId = 0;
|
||||
int months = 0;
|
||||
bool viaGiveaway = false;
|
||||
};
|
||||
|
||||
struct ActionRequestedPeer {
|
||||
PeerId peerId = 0;
|
||||
int buttonId = 0;
|
||||
|
@ -570,7 +585,8 @@ struct ServiceAction {
|
|||
ActionSuggestProfilePhoto,
|
||||
ActionRequestedPeer,
|
||||
ActionSetChatWallPaper,
|
||||
ActionSetSameChatWallPaper> content;
|
||||
ActionSetSameChatWallPaper,
|
||||
ActionGiftCode> content;
|
||||
};
|
||||
|
||||
ServiceAction ParseServiceAction(
|
||||
|
|
|
@ -611,6 +611,9 @@ private:
|
|||
const Data::Photo &data,
|
||||
const QString &basePath);
|
||||
[[nodiscard]] QByteArray pushPoll(const Data::Poll &data);
|
||||
[[nodiscard]] QByteArray pushGiveaway(
|
||||
const PeersMap &peers,
|
||||
const Data::Giveaway &data);
|
||||
|
||||
File _file;
|
||||
QByteArray _composedStart;
|
||||
|
@ -1276,6 +1279,16 @@ auto HtmlWriter::Wrap::pushMessage(
|
|||
+ " set "
|
||||
+ wrapReplyToLink("the same background")
|
||||
+ " for this chat";
|
||||
}, [&](const ActionGiftCode &data) {
|
||||
return data.viaGiveaway
|
||||
? ("You won a Telegram Premium for "
|
||||
+ NumberToString(data.months)
|
||||
+ (data.months > 1 ? " months" : "month")
|
||||
+ " prize in a giveaway organized by a channel.")
|
||||
: ("You've received a Telegram Premium for "
|
||||
+ NumberToString(data.months)
|
||||
+ (data.months > 1 ? " months" : "month")
|
||||
+ " gift from a channel.");
|
||||
}, [](v::null_t) { return QByteArray(); });
|
||||
|
||||
if (!serviceText.isEmpty()) {
|
||||
|
@ -1459,8 +1472,9 @@ QByteArray HtmlWriter::Wrap::pushMedia(
|
|||
if (!data.classes.isEmpty()) {
|
||||
return pushGenericMedia(data);
|
||||
}
|
||||
using namespace Data;
|
||||
const auto &content = message.media.content;
|
||||
if (const auto document = std::get_if<Data::Document>(&content)) {
|
||||
if (const auto document = std::get_if<Document>(&content)) {
|
||||
Assert(!message.media.ttl);
|
||||
if (document->isSticker) {
|
||||
return pushStickerMedia(*document, basePath);
|
||||
|
@ -1470,11 +1484,13 @@ QByteArray HtmlWriter::Wrap::pushMedia(
|
|||
return pushVideoFileMedia(*document, basePath);
|
||||
}
|
||||
Unexpected("Non generic document in HtmlWriter::Wrap::pushMedia.");
|
||||
} else if (const auto photo = std::get_if<Data::Photo>(&content)) {
|
||||
} else if (const auto photo = std::get_if<Photo>(&content)) {
|
||||
Assert(!message.media.ttl);
|
||||
return pushPhotoMedia(*photo, basePath);
|
||||
} else if (const auto poll = std::get_if<Data::Poll>(&content)) {
|
||||
} else if (const auto poll = std::get_if<Poll>(&content)) {
|
||||
return pushPoll(*poll);
|
||||
} else if (const auto giveaway = std::get_if<Giveaway>(&content)) {
|
||||
return pushGiveaway(peers, *giveaway);
|
||||
}
|
||||
Assert(v::is_null(content));
|
||||
return QByteArray();
|
||||
|
@ -1796,6 +1812,52 @@ QByteArray HtmlWriter::Wrap::pushPoll(const Data::Poll &data) {
|
|||
return result;
|
||||
}
|
||||
|
||||
QByteArray HtmlWriter::Wrap::pushGiveaway(
|
||||
const PeersMap &peers,
|
||||
const Data::Giveaway &data) {
|
||||
auto result = pushDiv("media_wrap clearfix");
|
||||
result.append(pushDiv("media_giveaway"));
|
||||
|
||||
result.append(pushDiv("section_title bold"));
|
||||
result.append(SerializeString("Giveaway Prizes"));
|
||||
result.append(popTag());
|
||||
result.append(pushDiv("section_body"));
|
||||
result.append("<b>"
|
||||
+ Data::NumberToString(data.quantity)
|
||||
+ "</b> "
|
||||
+ SerializeString((data.quantity > 1)
|
||||
? "Telegram Premium Subscriptions"
|
||||
: "Telegram Premium Subscription")
|
||||
+ " for <b>" + Data::NumberToString(data.months) + "</b> "
|
||||
+ (data.months > 1 ? "months." : "month."));
|
||||
result.append(popTag());
|
||||
|
||||
result.append(pushDiv("section_title bold"));
|
||||
result.append(SerializeString("Participants"));
|
||||
result.append(popTag());
|
||||
result.append(pushDiv("section_body"));
|
||||
auto channels = QByteArrayList();
|
||||
for (const auto &channel : data.channels) {
|
||||
channels.append("<b>" + peers.wrapPeerName(channel) + "</b>");
|
||||
}
|
||||
result.append(SerializeString((channels.size() > 1)
|
||||
? "All subscribers of those channels: "
|
||||
: "All subscribers of the channel: ")
|
||||
+ channels.join(", "));
|
||||
result.append(popTag());
|
||||
|
||||
result.append(pushDiv("section_title bold"));
|
||||
result.append(SerializeString("Winners Selection Date"));
|
||||
result.append(popTag());
|
||||
result.append(pushDiv("section_body"));
|
||||
result.append(Data::FormatDateTime(data.untilDate));
|
||||
result.append(popTag());
|
||||
|
||||
result.append(popTag());
|
||||
result.append(popTag());
|
||||
return result;
|
||||
}
|
||||
|
||||
MediaData HtmlWriter::Wrap::prepareMediaData(
|
||||
const Data::Message &message,
|
||||
const QString &basePath,
|
||||
|
@ -1954,6 +2016,7 @@ MediaData HtmlWriter::Wrap::prepareMediaData(
|
|||
result.description = data.description;
|
||||
result.status = Data::FormatMoneyAmount(data.amount, data.currency);
|
||||
}, [](const Poll &data) {
|
||||
}, [](const Giveaway &data) {
|
||||
}, [](const UnsupportedMedia &data) {
|
||||
Unexpected("Unsupported message.");
|
||||
}, [](v::null_t) {});
|
||||
|
|
|
@ -287,11 +287,12 @@ QByteArray SerializeMessage(
|
|||
}
|
||||
|
||||
const auto push = [&](const QByteArray &key, const auto &value) {
|
||||
if constexpr (std::is_arithmetic_v<std::decay_t<decltype(value)>>) {
|
||||
using V = std::decay_t<decltype(value)>;
|
||||
if constexpr (std::is_same_v<V, bool>) {
|
||||
pushBare(key, value ? "true" : "false");
|
||||
} else if constexpr (std::is_arithmetic_v<V>) {
|
||||
pushBare(key, Data::NumberToString(value));
|
||||
} else if constexpr (std::is_same_v<
|
||||
std::decay_t<decltype(value)>,
|
||||
PeerId>) {
|
||||
} else if constexpr (std::is_same_v<V, PeerId>) {
|
||||
if (const auto chat = peerToChat(value)) {
|
||||
pushBare(
|
||||
key,
|
||||
|
@ -592,6 +593,14 @@ QByteArray SerializeMessage(
|
|||
pushAction("requested_peer");
|
||||
push("button_id", data.buttonId);
|
||||
push("peer_id", data.peerId.value);
|
||||
}, [&](const ActionGiftCode &data) {
|
||||
pushAction("gift_code_prize");
|
||||
push("gift_code", data.code);
|
||||
if (data.boostPeerId) {
|
||||
push("boost_peer_id", data.boostPeerId);
|
||||
}
|
||||
push("months", data.months);
|
||||
push("via_giveaway", data.viaGiveaway);
|
||||
}, [&](const ActionSetChatWallPaper &data) {
|
||||
pushActor();
|
||||
pushAction("set_chat_wallpaper");
|
||||
|
@ -738,6 +747,22 @@ QByteArray SerializeMessage(
|
|||
{ "total_voters", NumberToString(data.totalVotes) },
|
||||
{ "answers", serialized }
|
||||
}));
|
||||
}, [&](const Giveaway &data) {
|
||||
context.nesting.push_back(Context::kObject);
|
||||
const auto channels = ranges::views::all(
|
||||
data.channels
|
||||
) | ranges::views::transform([&](ChannelId id) {
|
||||
return NumberToString(id.bare);
|
||||
}) | ranges::to_vector;
|
||||
const auto serialized = SerializeArray(context, channels);
|
||||
context.nesting.pop_back();
|
||||
|
||||
push("giveaway_information", SerializeObject(context, {
|
||||
{ "quantity", NumberToString(data.quantity) },
|
||||
{ "months", NumberToString(data.months) },
|
||||
{ "until_date", SerializeDate(data.untilDate) },
|
||||
{ "channels", serialized },
|
||||
}));
|
||||
}, [](const UnsupportedMedia &data) {
|
||||
Unexpected("Unsupported message.");
|
||||
}, [](v::null_t) {});
|
||||
|
|
|
@ -1127,8 +1127,8 @@ void History::applyServiceChanges(
|
|||
}, [&](const MTPDmessageActionPinMessage &data) {
|
||||
if (replyTo) {
|
||||
replyTo->match([&](const MTPDmessageReplyHeader &data) {
|
||||
const auto id = data.vreply_to_msg_id().v;
|
||||
if (item) {
|
||||
const auto id = data.vreply_to_msg_id().value_or_empty();
|
||||
if (id && item) {
|
||||
session().storage().add(Storage::SharedMediaAddSlice(
|
||||
peer->id,
|
||||
MsgId(0),
|
||||
|
|
|
@ -291,6 +291,10 @@ std::unique_ptr<Data::Media> HistoryItem::CreateMedia(
|
|||
peerFromMTP(media.vpeer()),
|
||||
media.vid().v,
|
||||
}, media.is_via_mention());
|
||||
}, [&](const MTPDmessageMediaGiveaway &media) -> Result {
|
||||
return std::make_unique<Data::MediaGiveaway>(
|
||||
item,
|
||||
Data::ComputeGiveawayData(item, media));
|
||||
}, [](const MTPDmessageMediaEmpty &) -> Result {
|
||||
return nullptr;
|
||||
}, [](const MTPDmessageMediaUnsupported &) -> Result {
|
||||
|
@ -1621,11 +1625,18 @@ void HistoryItem::applySentMessage(const MTPDmessage &data) {
|
|||
setForwardsCount(data.vforwards().value_or(-1));
|
||||
if (const auto reply = data.vreply_to()) {
|
||||
reply->match([&](const MTPDmessageReplyHeader &data) {
|
||||
setReplyFields(
|
||||
data.vreply_to_msg_id().v,
|
||||
data.vreply_to_top_id().value_or(
|
||||
data.vreply_to_msg_id().v),
|
||||
data.is_forum_topic());
|
||||
// #TODO replies
|
||||
const auto replyToPeer = data.vreply_to_peer_id()
|
||||
? peerFromMTP(*data.vreply_to_peer_id())
|
||||
: PeerId();
|
||||
if (!replyToPeer || replyToPeer == history()->peer->id) {
|
||||
if (const auto replyToId = data.vreply_to_msg_id()) {
|
||||
setReplyFields(
|
||||
replyToId->v,
|
||||
data.vreply_to_top_id().value_or(replyToId->v),
|
||||
data.is_forum_topic());
|
||||
}
|
||||
}
|
||||
}, [](const MTPDmessageReplyStoryHeader &data) {
|
||||
});
|
||||
}
|
||||
|
@ -3382,18 +3393,21 @@ void HistoryItem::createComponents(const MTPDmessage &data) {
|
|||
}
|
||||
if (const auto reply = data.vreply_to()) {
|
||||
reply->match([&](const MTPDmessageReplyHeader &data) {
|
||||
if (const auto peer = data.vreply_to_peer_id()) {
|
||||
config.replyToPeer = peerFromMTP(*peer);
|
||||
if (config.replyToPeer == _history->peer->id) {
|
||||
config.replyToPeer = 0;
|
||||
// #TODO replies
|
||||
if (const auto id = data.vreply_to_msg_id().value_or_empty()) {
|
||||
if (const auto peer = data.vreply_to_peer_id()) {
|
||||
config.replyToPeer = peerFromMTP(*peer);
|
||||
if (config.replyToPeer == _history->peer->id) {
|
||||
config.replyToPeer = 0;
|
||||
}
|
||||
}
|
||||
const auto owner = &_history->owner();
|
||||
config.replyTo = data.is_reply_to_scheduled()
|
||||
? owner->scheduledMessages().localMessageId(id)
|
||||
: id;
|
||||
config.replyToTop = data.vreply_to_top_id().value_or(id);
|
||||
config.replyIsTopicPost = data.is_forum_topic();
|
||||
}
|
||||
const auto id = data.vreply_to_msg_id().v;
|
||||
config.replyTo = data.is_reply_to_scheduled()
|
||||
? _history->owner().scheduledMessages().localMessageId(id)
|
||||
: id;
|
||||
config.replyToTop = data.vreply_to_top_id().value_or(id);
|
||||
config.replyIsTopicPost = data.is_forum_topic();
|
||||
}, [&](const MTPDmessageReplyStoryHeader &data) {
|
||||
config.replyToPeer = peerFromUser(data.vuser_id());
|
||||
config.replyToStory = data.vstory_id().v;
|
||||
|
@ -3631,21 +3645,23 @@ void HistoryItem::createServiceFromMtp(const MTPDmessageService &message) {
|
|||
? peerFromMTP(*data.vreply_to_peer_id())
|
||||
: _history->peer->id;
|
||||
if (const auto dependent = GetServiceDependentData()) {
|
||||
dependent->peerId = (peerId != _history->peer->id)
|
||||
? peerId
|
||||
: 0;
|
||||
const auto id = data.vreply_to_msg_id().v;
|
||||
dependent->msgId = id;
|
||||
dependent->topId = data.vreply_to_top_id().value_or(id);
|
||||
dependent->topicPost = data.is_forum_topic()
|
||||
|| Has<HistoryServiceTopicInfo>();
|
||||
if (!updateServiceDependent()) {
|
||||
RequestDependentMessageItem(
|
||||
this,
|
||||
(dependent->peerId
|
||||
? dependent->peerId
|
||||
: _history->peer->id),
|
||||
dependent->msgId);
|
||||
const auto id = data.vreply_to_msg_id().value_or_empty();
|
||||
if (id) {
|
||||
dependent->peerId = (peerId != _history->peer->id)
|
||||
? peerId
|
||||
: 0;
|
||||
dependent->msgId = id;
|
||||
dependent->topId = data.vreply_to_top_id().value_or(id);
|
||||
dependent->topicPost = data.is_forum_topic()
|
||||
|| Has<HistoryServiceTopicInfo>();
|
||||
if (!updateServiceDependent()) {
|
||||
RequestDependentMessageItem(
|
||||
this,
|
||||
(dependent->peerId
|
||||
? dependent->peerId
|
||||
: _history->peer->id),
|
||||
dependent->msgId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [](const MTPDmessageReplyStoryHeader &data) {
|
||||
|
@ -4426,6 +4442,25 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
|||
return result;
|
||||
};
|
||||
|
||||
auto prepareGiftCode = [&](const MTPDmessageActionGiftCode &action) {
|
||||
auto result = PreparedServiceText();
|
||||
_history->session().giftBoxStickersPacks().load();
|
||||
const auto months = action.vmonths().v;
|
||||
|
||||
result.text = {
|
||||
(action.is_via_giveaway()
|
||||
? tr::lng_prize_about
|
||||
: tr::lng_prize_gift_about)(
|
||||
tr::now,
|
||||
lt_channel,
|
||||
(action.vboost_peer()
|
||||
? _from->owner().peer(
|
||||
peerFromMTP(*action.vboost_peer()))->name()
|
||||
: "a channel")),
|
||||
};
|
||||
return result;
|
||||
};
|
||||
|
||||
setServiceText(action.match([&](
|
||||
const MTPDmessageActionChatAddUser &data) {
|
||||
return prepareChatAddUserText(data);
|
||||
|
@ -4506,6 +4541,8 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
|||
return prepareSetChatWallPaper(data);
|
||||
}, [&](const MTPDmessageActionSetSameChatWallPaper &data) {
|
||||
return prepareSetSameChatWallPaper(data);
|
||||
}, [&](const MTPDmessageActionGiftCode &data) {
|
||||
return prepareGiftCode(data);
|
||||
}, [](const MTPDmessageActionEmpty &) {
|
||||
return PreparedServiceText{ { tr::lng_message_empty(tr::now) } };
|
||||
}));
|
||||
|
|
|
@ -370,13 +370,19 @@ MTPMessageReplyHeader NewMessageReplyHeader(const Api::SendAction &action) {
|
|||
: Flag(0))),
|
||||
MTP_int(replyTo.msgId),
|
||||
MTPPeer(),
|
||||
MTP_int(replyToTop));
|
||||
MTPMessageFwdHeader(), // reply_header
|
||||
MTP_int(replyToTop),
|
||||
MTPstring(), // quote_text
|
||||
MTPVector<MTPMessageEntity>()); // quote_entities
|
||||
}
|
||||
return MTP_messageReplyHeader(
|
||||
MTP_flags(0),
|
||||
MTP_int(replyTo.msgId),
|
||||
MTPPeer(),
|
||||
MTPint());
|
||||
MTPPeer(), // reply_to_peer_id
|
||||
MTPMessageFwdHeader(), // reply_header
|
||||
MTPint(), // reply_to_top_id
|
||||
MTPstring(), // quote_text
|
||||
MTPVector<MTPMessageEntity>()); // quote_entities
|
||||
}
|
||||
return MTPMessageReplyHeader();
|
||||
}
|
||||
|
@ -453,6 +459,8 @@ MediaCheckResult CheckMessageMedia(const MTPMessageMedia &media) {
|
|||
return data.is_via_mention()
|
||||
? Result::HasStoryMention
|
||||
: Result::Good;
|
||||
}, [](const MTPDmessageMediaGiveaway &) {
|
||||
return Result::Good;
|
||||
}, [](const MTPDmessageMediaUnsupported &) {
|
||||
return Result::Unsupported;
|
||||
});
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
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
|
||||
*/
|
||||
#include "history/view/media/history_view_giveaway.h"
|
||||
|
||||
#include "base/unixtime.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "history/history_item.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
#include "history/view/history_view_cursor_state.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
namespace HistoryView {
|
||||
|
||||
void TextRows::add(Ui::Text::String text, int skipTop) {
|
||||
}
|
||||
|
||||
bool TextRows::isEmpty() const {
|
||||
return _rows.empty()
|
||||
|| (_rows.size() == 1 && _rows.front().text.isEmpty());
|
||||
}
|
||||
|
||||
int TextRows::maxWidth() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TextRows::minHeight() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TextRows::countHeight(int newWidth) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TextRows::length() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TextSelection UnshiftItemSelection(
|
||||
TextSelection selection,
|
||||
const TextRows &byText) {
|
||||
return UnshiftItemSelection(selection, byText.length());
|
||||
}
|
||||
|
||||
TextSelection ShiftItemSelection(
|
||||
TextSelection selection,
|
||||
const TextRows &byText) {
|
||||
return ShiftItemSelection(selection, byText.length());
|
||||
}
|
||||
|
||||
Giveaway::Giveaway(
|
||||
not_null<Element*> parent,
|
||||
not_null<Data::Giveaway*> giveaway)
|
||||
: Media(parent) {
|
||||
fillFromData(giveaway);
|
||||
}
|
||||
|
||||
Giveaway::~Giveaway() = default;
|
||||
|
||||
void Giveaway::fillFromData(not_null<Data::Giveaway*> giveaway) {
|
||||
_rows.add(Ui::Text::String(
|
||||
st::semiboldTextStyle,
|
||||
tr::lng_prizes_title(tr::now, lt_count, giveaway->quantity),
|
||||
kDefaultTextOptions,
|
||||
st::msgMinWidth), st::chatGiveawayPrizesTop);
|
||||
|
||||
const auto duration = (giveaway->months < 12)
|
||||
? tr::lng_months(tr::now, lt_count, giveaway->months)
|
||||
: tr::lng_years(tr::now, lt_count, giveaway->months / 12);
|
||||
_rows.add(Ui::Text::String(
|
||||
st::defaultTextStyle,
|
||||
tr::lng_prizes_about(
|
||||
tr::now,
|
||||
lt_count,
|
||||
giveaway->quantity,
|
||||
lt_duration,
|
||||
Ui::Text::Bold(duration),
|
||||
Ui::Text::RichLangValue),
|
||||
kDefaultTextOptions,
|
||||
st::msgMinWidth), st::chatGiveawayPrizesSkip);
|
||||
|
||||
_rows.add(Ui::Text::String(
|
||||
st::semiboldTextStyle,
|
||||
tr::lng_prizes_participants(tr::now),
|
||||
kDefaultTextOptions,
|
||||
st::msgMinWidth), st::chatGiveawayParticipantsTop);
|
||||
|
||||
for (const auto &channel : giveaway->channels) {
|
||||
_channels.push_back({ Ui::Text::String(
|
||||
st::semiboldTextStyle,
|
||||
channel->name(),
|
||||
kDefaultTextOptions,
|
||||
st::msgMinWidth)
|
||||
});
|
||||
}
|
||||
|
||||
const auto channels = int(_channels.size());
|
||||
_rows.add(Ui::Text::String(
|
||||
st::defaultTextStyle,
|
||||
(giveaway->all
|
||||
? tr::lng_prizes_participants_all
|
||||
: tr::lng_prizes_participants_new)(tr::now, lt_count, channels),
|
||||
kDefaultTextOptions,
|
||||
st::msgMinWidth), st::chatGiveawayParticipantsSkip);
|
||||
|
||||
_date.add(Ui::Text::String(
|
||||
st::semiboldTextStyle,
|
||||
tr::lng_prizes_date(tr::now),
|
||||
kDefaultTextOptions,
|
||||
st::msgMinWidth), st::chatGiveawayDateTop);
|
||||
|
||||
_rows.add(Ui::Text::String(
|
||||
st::defaultTextStyle,
|
||||
langDateTime(base::unixtime::parse(giveaway->untilDate)),
|
||||
kDefaultTextOptions,
|
||||
st::msgMinWidth), st::chatGiveawayDateSkip);
|
||||
}
|
||||
|
||||
QSize Giveaway::countOptimalSize() {
|
||||
// init dimensions
|
||||
auto skipBlockWidth = _parent->skipBlockWidth();
|
||||
auto maxWidth = skipBlockWidth;
|
||||
auto minHeight = 0;
|
||||
|
||||
accumulate_max(maxWidth, _rows.maxWidth());
|
||||
minHeight += _rows.minHeight();
|
||||
|
||||
//minHeight +=
|
||||
|
||||
accumulate_max(maxWidth, _date.maxWidth());
|
||||
minHeight += _date.minHeight();
|
||||
|
||||
auto padding = inBubblePadding();
|
||||
maxWidth += padding.left() + padding.right();
|
||||
minHeight += padding.top() + padding.bottom();
|
||||
return { maxWidth, minHeight };
|
||||
}
|
||||
|
||||
QSize Giveaway::countCurrentSize(int newWidth) {
|
||||
accumulate_min(newWidth, maxWidth());
|
||||
auto innerWidth = newWidth
|
||||
- st::msgPadding.left()
|
||||
- st::msgPadding.right();
|
||||
|
||||
auto newHeight = 0;
|
||||
_rowsHeight = _rows.countHeight(innerWidth);
|
||||
newHeight += _rowsHeight;
|
||||
|
||||
//newHeight +=
|
||||
|
||||
newHeight += _date.countHeight(innerWidth);
|
||||
_dateHeight = _date.minHeight();
|
||||
newHeight += _dateHeight;
|
||||
|
||||
auto padding = inBubblePadding();
|
||||
newHeight += padding.top() + padding.bottom();
|
||||
|
||||
return { newWidth, newHeight };
|
||||
}
|
||||
|
||||
TextSelection Giveaway::toDateSelection(TextSelection selection) const {
|
||||
return UnshiftItemSelection(selection, _rows);
|
||||
}
|
||||
|
||||
TextSelection Giveaway::fromDateSelection(TextSelection selection) const {
|
||||
return ShiftItemSelection(selection, _rows);
|
||||
}
|
||||
|
||||
void Giveaway::draw(Painter &p, const PaintContext &context) const {
|
||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||
|
||||
const auto st = context.st;
|
||||
const auto sti = context.imageStyle();
|
||||
const auto stm = context.messageStyle();
|
||||
|
||||
auto &semibold = stm->msgServiceFg;
|
||||
|
||||
auto padding = inBubblePadding();
|
||||
auto tshift = padding.top();
|
||||
|
||||
//_rows.draw(p, {
|
||||
// .position = { padding.left(), tshift },
|
||||
// .outerWidth = width(),
|
||||
// .availableWidth = paintw,
|
||||
// .now = context.now,
|
||||
// .selection = context.selection,
|
||||
//});
|
||||
//tshift += _rows.countHeight(paintw);
|
||||
|
||||
//_date.draw(p, {
|
||||
// .position = { padding.left(), tshift },
|
||||
// .outerWidth = width(),
|
||||
// .availableWidth = paintw,
|
||||
// .now = context.now,
|
||||
// .selection = toDateSelection(context.selection),
|
||||
//});
|
||||
}
|
||||
|
||||
TextState Giveaway::textState(QPoint point, StateRequest request) const {
|
||||
auto result = TextState(_parent);
|
||||
|
||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) {
|
||||
return result;
|
||||
}
|
||||
|
||||
auto padding = inBubblePadding();
|
||||
auto tshift = padding.top();
|
||||
auto bshift = padding.bottom();
|
||||
|
||||
auto symbolAdd = 0;
|
||||
if (_rowsHeight > 0) {
|
||||
if (point.y() >= tshift && point.y() < tshift + _rowsHeight) {
|
||||
//result = TextState(_parent, _rows.getState(
|
||||
// point - QPoint(padding.left(), tshift),
|
||||
// paintw,
|
||||
// width(),
|
||||
// request.forText()));
|
||||
} else if (point.y() >= tshift + _rowsHeight) {
|
||||
symbolAdd += _rows.length();
|
||||
}
|
||||
tshift += _rowsHeight;
|
||||
}
|
||||
if (_channelsHeight > 0) {
|
||||
tshift += _channelsHeight;
|
||||
}
|
||||
if (_dateHeight > 0) {
|
||||
if (point.y() >= tshift && point.y() < tshift + _dateHeight) {
|
||||
//result = TextState(_parent, _date.getState(
|
||||
// point - QPoint(padding.left(), tshift),
|
||||
// paintw,
|
||||
// width(),
|
||||
// request.forText()));
|
||||
} else if (point.y() >= tshift + _dateHeight) {
|
||||
symbolAdd += _date.length();
|
||||
}
|
||||
tshift += _dateHeight;
|
||||
}
|
||||
result.symbol += symbolAdd;
|
||||
return result;
|
||||
}
|
||||
|
||||
TextSelection Giveaway::adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const {
|
||||
//if (_date.isEmpty() || selection.to <= _rows.length()) {
|
||||
// return _rows.adjustSelection(selection, type);
|
||||
//}
|
||||
//const auto dateSelection = _date.adjustSelection(
|
||||
// toDateSelection(selection),
|
||||
// type);
|
||||
//if (selection.from >= _rows.length()) {
|
||||
// return fromDateSelection(dateSelection);
|
||||
//}
|
||||
//const auto rowsSelection = _rows.adjustSelection(selection, type);
|
||||
//return { rowsSelection.from, fromDateSelection(dateSelection).to };
|
||||
return selection;
|
||||
}
|
||||
|
||||
bool Giveaway::hasHeavyPart() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Giveaway::unloadHeavyPart() {
|
||||
}
|
||||
|
||||
uint16 Giveaway::fullSelectionLength() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TextForMimeData Giveaway::selectedText(TextSelection selection) const {
|
||||
//auto rowsResult = _rows.toTextForMimeData(selection);
|
||||
//auto dateResult = _date.toTextForMimeData(toDateSelection(selection));
|
||||
//if (rowsResult.empty()) {
|
||||
// return dateResult;
|
||||
//} else if (dateResult.empty()) {
|
||||
// return rowsResult;
|
||||
//}
|
||||
//return rowsResult.append('\n').append(std::move(dateResult));
|
||||
return {};
|
||||
}
|
||||
|
||||
QMargins Giveaway::inBubblePadding() const {
|
||||
auto lshift = st::msgPadding.left();
|
||||
auto rshift = st::msgPadding.right();
|
||||
auto bshift = isBubbleBottom() ? st::msgPadding.top() : st::mediaInBubbleSkip;
|
||||
auto tshift = isBubbleTop() ? st::msgPadding.bottom() : st::mediaInBubbleSkip;
|
||||
return QMargins(lshift, tshift, rshift, bshift);
|
||||
}
|
||||
|
||||
} // namespace HistoryView
|
102
Telegram/SourceFiles/history/view/media/history_view_giveaway.h
Normal file
102
Telegram/SourceFiles/history/view/media/history_view_giveaway.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
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 "history/view/media/history_view_media.h"
|
||||
|
||||
namespace Data {
|
||||
struct Giveaway;
|
||||
} // namespace Data
|
||||
|
||||
namespace HistoryView {
|
||||
|
||||
class TextRows final {
|
||||
public:
|
||||
void add(Ui::Text::String text, int skipTop);
|
||||
|
||||
[[nodiscard]] bool isEmpty() const;
|
||||
[[nodiscard]] int maxWidth() const;
|
||||
[[nodiscard]] int minHeight() const;
|
||||
|
||||
[[nodiscard]] int countHeight(int newWidth) const;
|
||||
|
||||
[[nodiscard]] int length() const;
|
||||
|
||||
private:
|
||||
struct Row {
|
||||
Ui::Text::String text;
|
||||
int skipTop = 0;
|
||||
};
|
||||
std::vector<Row> _rows;
|
||||
};
|
||||
|
||||
[[nodiscard]] TextSelection UnshiftItemSelection(
|
||||
TextSelection selection,
|
||||
const TextRows &byText);
|
||||
[[nodiscard]] TextSelection ShiftItemSelection(
|
||||
TextSelection selection,
|
||||
const TextRows &byText);
|
||||
|
||||
class Giveaway final : public Media {
|
||||
public:
|
||||
Giveaway(
|
||||
not_null<Element*> parent,
|
||||
not_null<Data::Giveaway*> giveaway);
|
||||
~Giveaway();
|
||||
|
||||
void draw(Painter &p, const PaintContext &context) const override;
|
||||
TextState textState(QPoint point, StateRequest request) const override;
|
||||
|
||||
bool needsBubble() const override {
|
||||
return true;
|
||||
}
|
||||
bool customInfoLayout() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool toggleSelectionByHandlerClick(
|
||||
const ClickHandlerPtr &p) const override {
|
||||
return true;
|
||||
}
|
||||
bool dragItemByHandler(const ClickHandlerPtr &p) const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override;
|
||||
uint16 fullSelectionLength() const override;
|
||||
TextForMimeData selectedText(TextSelection selection) const override;
|
||||
|
||||
void unloadHeavyPart() override;
|
||||
bool hasHeavyPart() const override;
|
||||
|
||||
private:
|
||||
struct Channel {
|
||||
Ui::Text::String name;
|
||||
};
|
||||
|
||||
QSize countOptimalSize() override;
|
||||
QSize countCurrentSize(int newWidth) override;
|
||||
|
||||
void fillFromData(not_null<Data::Giveaway*> giveaway);
|
||||
|
||||
TextSelection toDateSelection(TextSelection selection) const;
|
||||
TextSelection fromDateSelection(TextSelection selection) const;
|
||||
QMargins inBubblePadding() const;
|
||||
|
||||
TextRows _rows;
|
||||
std::vector<Channel> _channels;
|
||||
TextRows _date;
|
||||
int _rowsHeight = 0;
|
||||
int _channelsHeight = 0;
|
||||
int _dateHeight = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace HistoryView
|
|
@ -130,6 +130,7 @@ messageMediaGeoLive#b940c666 flags:# geo:GeoPoint heading:flags.0?int period:int
|
|||
messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia;
|
||||
messageMediaDice#3f7ee58b value:int emoticon:string = MessageMedia;
|
||||
messageMediaStory#68cb6283 flags:# via_mention:flags.1?true peer:Peer id:int story:flags.0?StoryItem = MessageMedia;
|
||||
messageMediaGiveaway#4291677c flags:# only_new_subscribers:flags.0?true channels:Vector<long> quantity:int months:int until_date:int = MessageMedia;
|
||||
|
||||
messageActionEmpty#b6aef7b0 = MessageAction;
|
||||
messageActionChatCreate#bd47cbad title:string users:Vector<long> = MessageAction;
|
||||
|
@ -170,6 +171,7 @@ messageActionSuggestProfilePhoto#57de635e photo:Photo = MessageAction;
|
|||
messageActionRequestedPeer#fe77345d button_id:int peer:Peer = MessageAction;
|
||||
messageActionSetChatWallPaper#bc44a927 wallpaper:WallPaper = MessageAction;
|
||||
messageActionSetSameChatWallPaper#c0787d6d wallpaper:WallPaper = MessageAction;
|
||||
messageActionGiftCode#d2cfdb0e flags:# via_giveaway:flags.0?true boost_peer:flags.1?Peer months:int slug:string = MessageAction;
|
||||
|
||||
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
|
||||
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
|
||||
|
@ -755,7 +757,7 @@ contacts.topPeers#70b772a8 categories:Vector<TopPeerCategoryPeers> chats:Vector<
|
|||
contacts.topPeersDisabled#b52c939d = contacts.TopPeers;
|
||||
|
||||
draftMessageEmpty#1b0c841a flags:# date:flags.0?int = DraftMessage;
|
||||
draftMessage#fd8e711f flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int message:string entities:flags.3?Vector<MessageEntity> date:int = DraftMessage;
|
||||
draftMessage#95b0528b flags:# no_webpage:flags.1?true reply_to:flags.4?MessageReplyHeader message:string entities:flags.3?Vector<MessageEntity> date:int = DraftMessage;
|
||||
|
||||
messages.featuredStickersNotModified#c6dc0c66 count:int = messages.FeaturedStickers;
|
||||
messages.featuredStickers#be382906 flags:# premium:flags.0?true hash:long count:int sets:Vector<StickerSetCovered> unread:Vector<long> = messages.FeaturedStickers;
|
||||
|
@ -1256,7 +1258,7 @@ messages.messageViews#b6c4f543 views:Vector<MessageViews> chats:Vector<Chat> use
|
|||
|
||||
messages.discussionMessage#a6341782 flags:# messages:Vector<Message> max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int unread_count:int chats:Vector<Chat> users:Vector<User> = messages.DiscussionMessage;
|
||||
|
||||
messageReplyHeader#a6d57763 flags:# reply_to_scheduled:flags.2?true forum_topic:flags.3?true reply_to_msg_id:int reply_to_peer_id:flags.0?Peer reply_to_top_id:flags.1?int = MessageReplyHeader;
|
||||
messageReplyHeader#3d5c1693 flags:# reply_to_scheduled:flags.2?true forum_topic:flags.3?true reply_to_msg_id:flags.4?int reply_to_peer_id:flags.0?Peer reply_header:flags.5?MessageFwdHeader reply_to_top_id:flags.1?int quote_text:flags.6?string quote_entities:flags.7?Vector<MessageEntity> = MessageReplyHeader;
|
||||
messageReplyStoryHeader#9c98bfc1 user_id:long story_id:int = MessageReplyHeader;
|
||||
|
||||
messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector<Peer> channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;
|
||||
|
@ -1406,6 +1408,7 @@ attachMenuPeerTypeBroadcast#7bfbdefc = AttachMenuPeerType;
|
|||
|
||||
inputInvoiceMessage#c5b56859 peer:InputPeer msg_id:int = InputInvoice;
|
||||
inputInvoiceSlug#c326caef slug:string = InputInvoice;
|
||||
inputInvoicePremiumGiftCode#98986c0d purpose:InputStorePaymentPurpose option:PremiumGiftCodeOption = InputInvoice;
|
||||
|
||||
payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice;
|
||||
|
||||
|
@ -1416,6 +1419,7 @@ help.premiumPromo#5334759c status_text:string status_entities:Vector<MessageEnti
|
|||
inputStorePaymentPremiumSubscription#a6751e66 flags:# restore:flags.0?true upgrade:flags.1?true = InputStorePaymentPurpose;
|
||||
inputStorePaymentGiftPremium#616f7fe8 user_id:InputUser currency:string amount:long = InputStorePaymentPurpose;
|
||||
inputStorePaymentPremiumGiftCode#a3805f3f flags:# users:Vector<InputUser> boost_peer:flags.0?InputPeer currency:string amount:long = InputStorePaymentPurpose;
|
||||
inputStorePaymentPremiumGiveaway#e94a2529 flags:# only_new_subscribers:flags.0?true boost_peer:InputPeer additional_peers:flags.1?Vector<InputPeer> random_id:long until_date:int currency:string amount:long = InputStorePaymentPurpose;
|
||||
|
||||
premiumGiftOption#74c34319 flags:# months:int currency:string amount:long bot_url:string store_product:flags.0?string = PremiumGiftOption;
|
||||
|
||||
|
@ -1547,7 +1551,7 @@ stories.storyViewsList#46e9b9ec flags:# count:int reactions_count:int views:Vect
|
|||
|
||||
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
|
||||
|
||||
inputReplyToMessage#9c5386e4 flags:# reply_to_msg_id:int top_msg_id:flags.0?int = InputReplyTo;
|
||||
inputReplyToMessage#73ec805 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> = InputReplyTo;
|
||||
inputReplyToStory#15b0f283 user_id:InputUser story_id:int = InputReplyTo;
|
||||
|
||||
exportedStoryLink#3fc9053b link:string = ExportedStoryLink;
|
||||
|
@ -1576,9 +1580,12 @@ stories.boostersList#f3dd3d1d flags:# count:int boosters:Vector<Booster> next_of
|
|||
|
||||
messages.webPage#fd5e12bd webpage:WebPage chats:Vector<Chat> users:Vector<User> = messages.WebPage;
|
||||
|
||||
premiumGiftCodeOption#d579436c flags:# users:int months:int store_product:flags.0?string = PremiumGiftCodeOption;
|
||||
premiumGiftCodeOption#257e962b flags:# users:int months:int store_product:flags.0?string store_quantity:flags.1?int currency:string amount:long = PremiumGiftCodeOption;
|
||||
|
||||
payments.checkedGiftCode#ff70298c flags:# from_id:Peer to_id:flags.0?long date:int months:int used_date:flags.1?int chats:Vector<Chat> users:Vector<User> = payments.CheckedGiftCode;
|
||||
payments.checkedGiftCode#b722f158 flags:# via_giveaway:flags.2?true from_id:Peer giveaway_msg_id:flags.3?int to_id:flags.0?long date:int months:int used_date:flags.1?int chats:Vector<Chat> users:Vector<User> = payments.CheckedGiftCode;
|
||||
|
||||
payments.giveawayInfo#7a7bdc5a flags:# participating:flags.0?true preparing_results:flags.3?true joined_too_early_date:flags.1?int admin_disallowed_chat_id:flags.2?long = payments.GiveawayInfo;
|
||||
payments.giveawayInfoResults#38c32424 flags:# winner:flags.0?true refunded:flags.1?true gift_code_slug:flags.0?string finish_date:int winners_count:int activated_count:int = payments.GiveawayInfo;
|
||||
|
||||
---functions---
|
||||
|
||||
|
@ -1793,7 +1800,7 @@ messages.editInlineBotMessage#83557dba flags:# no_webpage:flags.1?true id:InputB
|
|||
messages.getBotCallbackAnswer#9342ca07 flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes password:flags.2?InputCheckPasswordSRP = messages.BotCallbackAnswer;
|
||||
messages.setBotCallbackAnswer#d58f130a flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string cache_time:int = Bool;
|
||||
messages.getPeerDialogs#e470bcfd peers:Vector<InputDialogPeer> = messages.PeerDialogs;
|
||||
messages.saveDraft#b4331e3f flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int top_msg_id:flags.2?int peer:InputPeer message:string entities:flags.3?Vector<MessageEntity> = Bool;
|
||||
messages.saveDraft#64a3026c flags:# no_webpage:flags.1?true reply_to:flags.0?InputReplyTo peer:InputPeer message:string entities:flags.3?Vector<MessageEntity> = Bool;
|
||||
messages.getAllDrafts#6a3f8d65 = Updates;
|
||||
messages.getFeaturedStickers#64780b14 hash:long = messages.FeaturedStickers;
|
||||
messages.readFeaturedStickers#5b118126 id:Vector<long> = Bool;
|
||||
|
@ -2051,6 +2058,7 @@ payments.canPurchasePremium#9fc19eb6 purpose:InputStorePaymentPurpose = Bool;
|
|||
payments.getPremiumGiftCodeOptions#2757ba54 flags:# boost_peer:flags.0?InputPeer = Vector<PremiumGiftCodeOption>;
|
||||
payments.checkGiftCode#8e51b4c1 slug:string = payments.CheckedGiftCode;
|
||||
payments.applyGiftCode#f6e26854 slug:string = Updates;
|
||||
payments.getGiveawayInfo#f4239425 peer:InputPeer msg_id:int = payments.GiveawayInfo;
|
||||
|
||||
stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true animated:flags.1?true videos:flags.4?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> software:flags.3?string = messages.StickerSet;
|
||||
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
|
||||
|
|
|
@ -931,3 +931,10 @@ storyMentionUnreadStrokeTwice: 6px;
|
|||
storyMentionReadSkipTwice: 7px;
|
||||
storyMentionReadStrokeTwice: 3px;
|
||||
storyMentionButtonSkip: 5px;
|
||||
|
||||
chatGiveawayPrizesTop: 4px;
|
||||
chatGiveawayPrizesSkip: 4px;
|
||||
chatGiveawayParticipantsTop: 16px;
|
||||
chatGiveawayParticipantsSkip: 4px;
|
||||
chatGiveawayDateTop: 16px;
|
||||
chatGiveawayDateSkip: 4px;
|
||||
|
|
Loading…
Add table
Reference in a new issue