Update API scheme. Giveaway winners.

This commit is contained in:
John Preston 2023-12-13 08:14:41 +00:00
parent 62f9f3c94b
commit 4b9648d8d9
21 changed files with 552 additions and 156 deletions

Binary file not shown.

View file

@ -2246,6 +2246,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_prizes_cancelled" = "The channel cancelled the prizes by reversing the payment for them."; "lng_prizes_cancelled" = "The channel cancelled the prizes by reversing the payment for them.";
"lng_prizes_badge" = "x{amount}"; "lng_prizes_badge" = "x{amount}";
"lng_prizes_results_title" = "Winners Selected!";
"lng_prizes_results_about#one" = "**{count}** winner of the {link} was randomly selected by Telegram.";
"lng_prizes_results_about#other" = "**{count}** winners of the {link} were randomly selected by Telegram.";
"lng_prizes_results_link" = "Giveaway";
"lng_prizes_results_winners" = "Winners";
"lng_prizes_results_more#one" = "and {count} more!";
"lng_prizes_results_more#other" = "and {count} more!";
"lng_prizes_results_all" = "All winners received gift links in private messages.";
"lng_prizes_results_some" = "Some winners couldn't be selected.";
"lng_gift_link_title" = "Gift Link"; "lng_gift_link_title" = "Gift Link";
"lng_gift_link_about" = "This link allows you to activate\na **Telegram Premium** subscription."; "lng_gift_link_about" = "This link allows you to activate\na **Telegram Premium** subscription.";
"lng_gift_link_label_from" = "From"; "lng_gift_link_label_from" = "From";
@ -3629,6 +3639,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_set_background_emoji" = "{from} set channel background emoji to {emoji}"; "lng_admin_log_set_background_emoji" = "{from} set channel background emoji to {emoji}";
"lng_admin_log_change_background_emoji" = "{from} changed channel background emoji from {previous} to {emoji}"; "lng_admin_log_change_background_emoji" = "{from} changed channel background emoji from {previous} to {emoji}";
"lng_admin_log_removed_background_emoji" = "{from} removed channel background emoji {emoji}"; "lng_admin_log_removed_background_emoji" = "{from} removed channel background emoji {emoji}";
"lng_admin_log_change_profile_color" = "{from} changed channel profile color from {previous} to {color}";
"lng_admin_log_set_profile_background_emoji" = "{from} set channel profile background emoji to {emoji}";
"lng_admin_log_change_profile_background_emoji" = "{from} changed channel profile background emoji from {previous} to {emoji}";
"lng_admin_log_removed_profile_background_emoji" = "{from} removed channel profile background emoji {emoji}";
"lng_admin_log_change_wallpaper" = "{from} changed channel wallpaper";
"lng_admin_log_user_with_username" = "{name} ({mention})"; "lng_admin_log_user_with_username" = "{name} ({mention})";
"lng_admin_log_messages_ttl_set" = "{from} enabled messages auto-delete after {duration}"; "lng_admin_log_messages_ttl_set" = "{from} enabled messages auto-delete after {duration}";
"lng_admin_log_messages_ttl_changed" = "{from} changed messages auto-delete period from {previous} to {duration}"; "lng_admin_log_messages_ttl_changed" = "{from} changed messages auto-delete period from {previous} to {duration}";

View file

@ -15,6 +15,7 @@
<file alias="art/slot_2_idle.tgs">../../art/slot_2_idle.tgs</file> <file alias="art/slot_2_idle.tgs">../../art/slot_2_idle.tgs</file>
<file alias="art/slot_back.tgs">../../art/slot_back.tgs</file> <file alias="art/slot_back.tgs">../../art/slot_back.tgs</file>
<file alias="art/slot_pull.tgs">../../art/slot_pull.tgs</file> <file alias="art/slot_pull.tgs">../../art/slot_pull.tgs</file>
<file alias="art/winners.tgs">../../art/winners.tgs</file>
<file alias="day-blue.tdesktop-theme">../../day-blue.tdesktop-theme</file> <file alias="day-blue.tdesktop-theme">../../day-blue.tdesktop-theme</file>
<file alias="night.tdesktop-theme">../../night.tdesktop-theme</file> <file alias="night.tdesktop-theme">../../night.tdesktop-theme</file>
<file alias="night-green.tdesktop-theme">../../night-green.tdesktop-theme</file> <file alias="night-green.tdesktop-theme">../../night-green.tdesktop-theme</file>

View file

@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_boosts.h" #include "data/data_boosts.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_media_types.h" // Data::Giveaway #include "data/data_media_types.h" // Data::GiveawayStart.
#include "data/data_peer_values.h" // Data::PeerPremiumValue. #include "data/data_peer_values.h" // Data::PeerPremiumValue.
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_subscription_option.h" #include "data/data_subscription_option.h"
@ -739,8 +739,11 @@ void ResolveGiftCode(
void GiveawayInfoBox( void GiveawayInfoBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
not_null<Window::SessionNavigation*> controller, not_null<Window::SessionNavigation*> controller,
Data::Giveaway giveaway, std::optional<Data::GiveawayStart> start,
std::optional<Data::GiveawayResults> results,
Api::GiveawayInfo info) { Api::GiveawayInfo info) {
Expects(start || results);
using State = Api::GiveawayState; using State = Api::GiveawayState;
const auto finished = (info.state == State::Finished) const auto finished = (info.state == State::Finished)
|| (info.state == State::Refunded); || (info.state == State::Refunded);
@ -749,8 +752,10 @@ void GiveawayInfoBox(
? tr::lng_prizes_end_title ? tr::lng_prizes_end_title
: tr::lng_prizes_how_title)()); : tr::lng_prizes_how_title)());
const auto first = !giveaway.channels.empty() const auto first = results
? giveaway.channels.front()->name() ? results->channel->name()
: !start->channels.empty()
? start->channels.front()->name()
: u"channel"_q; : u"channel"_q;
auto text = TextWithEntities(); auto text = TextWithEntities();
@ -767,6 +772,10 @@ void GiveawayInfoBox(
text.append("\n\n"); text.append("\n\n");
} }
const auto quantity = start
? start->quantity
: (results->winnersCount + results->unclaimedCount);
const auto months = start ? start->months : results->months;
text.append((finished text.append((finished
? tr::lng_prizes_end_text ? tr::lng_prizes_end_text
: tr::lng_prizes_how_text)( : tr::lng_prizes_how_text)(
@ -775,18 +784,21 @@ void GiveawayInfoBox(
tr::lng_prizes_admins( tr::lng_prizes_admins(
tr::now, tr::now,
lt_count, lt_count,
giveaway.quantity, quantity,
lt_channel, lt_channel,
Ui::Text::Bold(first), Ui::Text::Bold(first),
lt_duration, lt_duration,
TextWithEntities{ GiftDuration(giveaway.months) }, TextWithEntities{ GiftDuration(months) },
Ui::Text::RichLangValue), Ui::Text::RichLangValue),
Ui::Text::RichLangValue)); Ui::Text::RichLangValue));
const auto many = (giveaway.channels.size() > 1); const auto many = start
? (start->channels.size() > 1)
: (results->additionalPeersCount > 0);
const auto count = info.winnersCount const auto count = info.winnersCount
? info.winnersCount ? info.winnersCount
: giveaway.quantity; : quantity;
auto winners = giveaway.all const auto all = start ? start->all : results->all;
auto winners = all
? (many ? (many
? tr::lng_prizes_winners_all_of_many ? tr::lng_prizes_winners_all_of_many
: tr::lng_prizes_winners_all_of_one)( : tr::lng_prizes_winners_all_of_one)(
@ -808,7 +820,10 @@ void GiveawayInfoBox(
Ui::Text::Bold( Ui::Text::Bold(
langDateTime(base::unixtime::parse(info.startDate))), langDateTime(base::unixtime::parse(info.startDate))),
Ui::Text::RichLangValue); Ui::Text::RichLangValue);
if (!giveaway.additionalPrize.isEmpty()) { const auto additionalPrize = results
? results->additionalPrize
: start->additionalPrize;
if (!additionalPrize.isEmpty()) {
text.append("\n\n").append(tr::lng_prizes_additional_added( text.append("\n\n").append(tr::lng_prizes_additional_added(
tr::now, tr::now,
lt_count, lt_count,
@ -816,16 +831,19 @@ void GiveawayInfoBox(
lt_channel, lt_channel,
Ui::Text::Bold(first), Ui::Text::Bold(first),
lt_prize, lt_prize,
TextWithEntities{ giveaway.additionalPrize }, TextWithEntities{ additionalPrize },
Ui::Text::RichLangValue)); Ui::Text::RichLangValue));
} }
const auto untilDate = start
? start->untilDate
: results->untilDate;
text.append("\n\n").append((finished text.append("\n\n").append((finished
? tr::lng_prizes_end_when_finish ? tr::lng_prizes_end_when_finish
: tr::lng_prizes_how_when_finish)( : tr::lng_prizes_how_when_finish)(
tr::now, tr::now,
lt_date, lt_date,
Ui::Text::Bold(langDayOfMonthFull( Ui::Text::Bold(langDayOfMonthFull(
base::unixtime::parse(giveaway.untilDate).date())), base::unixtime::parse(untilDate).date())),
lt_winners, lt_winners,
winners, winners,
Ui::Text::RichLangValue)); Ui::Text::RichLangValue));
@ -876,7 +894,7 @@ void GiveawayInfoBox(
Ui::Text::Bold(first), Ui::Text::Bold(first),
lt_date, lt_date,
Ui::Text::Bold(langDayOfMonthFull( Ui::Text::Bold(langDayOfMonthFull(
base::unixtime::parse(giveaway.untilDate).date())), base::unixtime::parse(untilDate).date())),
Ui::Text::RichLangValue)); Ui::Text::RichLangValue));
} }
} }
@ -920,14 +938,15 @@ void ResolveGiveawayInfo(
not_null<Window::SessionNavigation*> controller, not_null<Window::SessionNavigation*> controller,
not_null<PeerData*> peer, not_null<PeerData*> peer,
MsgId messageId, MsgId messageId,
Data::Giveaway giveaway) { std::optional<Data::GiveawayStart> start,
std::optional<Data::GiveawayResults> results) {
const auto show = [=](Api::GiveawayInfo info) { const auto show = [=](Api::GiveawayInfo info) {
if (!info) { if (!info) {
controller->showToast( controller->showToast(
tr::lng_confirm_phone_link_invalid(tr::now)); tr::lng_confirm_phone_link_invalid(tr::now));
} else { } else {
controller->uiShow()->showBox( controller->uiShow()->showBox(
Box(GiveawayInfoBox, controller, giveaway, info)); Box(GiveawayInfoBox, controller, start, results, info));
} }
}; };
controller->session().api().premium().resolveGiveawayInfo( controller->session().api().premium().resolveGiveawayInfo(

View file

@ -16,7 +16,8 @@ struct GiftCode;
} // namespace Api } // namespace Api
namespace Data { namespace Data {
struct Giveaway; struct GiveawayStart;
struct GiveawayResults;
} // namespace Data } // namespace Data
namespace Ui { namespace Ui {
@ -62,4 +63,5 @@ void ResolveGiveawayInfo(
not_null<Window::SessionNavigation*> controller, not_null<Window::SessionNavigation*> controller,
not_null<PeerData*> peer, not_null<PeerData*> peer,
MsgId messageId, MsgId messageId,
Data::Giveaway giveaway); std::optional<Data::GiveawayStart> start,
std::optional<Data::GiveawayResults> results);

View file

@ -26,6 +26,7 @@ const QString DicePacks::kDartString = QString::fromUtf8("\xF0\x9F\x8E\xAF");
const QString DicePacks::kSlotString = QString::fromUtf8("\xF0\x9F\x8E\xB0"); const QString DicePacks::kSlotString = QString::fromUtf8("\xF0\x9F\x8E\xB0");
const QString DicePacks::kFballString = QString::fromUtf8("\xE2\x9A\xBD"); const QString DicePacks::kFballString = QString::fromUtf8("\xE2\x9A\xBD");
const QString DicePacks::kBballString = QString::fromUtf8("\xF0\x9F\x8F\x80"); const QString DicePacks::kBballString = QString::fromUtf8("\xF0\x9F\x8F\x80");
const QString DicePacks::kPartyPopper = QString::fromUtf8("\xf0\x9f\x8e\x89");
DicePack::DicePack(not_null<Main::Session*> session, const QString &emoji) DicePack::DicePack(not_null<Main::Session*> session, const QString &emoji)
: _session(session) : _session(session)
@ -35,7 +36,7 @@ DicePack::DicePack(not_null<Main::Session*> session, const QString &emoji)
DicePack::~DicePack() = default; DicePack::~DicePack() = default;
DocumentData *DicePack::lookup(int value) { DocumentData *DicePack::lookup(int value) {
if (!_requestId) { if (!_requestId && _emoji != DicePacks::kPartyPopper) {
load(); load();
} }
tryGenerateLocalZero(); tryGenerateLocalZero();
@ -117,6 +118,8 @@ void DicePack::tryGenerateLocalZero() {
generateLocal(8, u"slot_0_idle"_q); generateLocal(8, u"slot_0_idle"_q);
generateLocal(14, u"slot_1_idle"_q); generateLocal(14, u"slot_1_idle"_q);
generateLocal(20, u"slot_2_idle"_q); generateLocal(20, u"slot_2_idle"_q);
} else if (_emoji == DicePacks::kPartyPopper) {
generateLocal(0, u"winners"_q);
} }
} }

View file

@ -44,6 +44,7 @@ public:
static const QString kSlotString; static const QString kSlotString;
static const QString kFballString; static const QString kFballString;
static const QString kBballString; static const QString kBballString;
static const QString kPartyPopper;
[[nodiscard]] static bool IsSlot(const QString &emoji) { [[nodiscard]] static bool IsSlot(const QString &emoji) {
return (emoji == kSlotString); return (emoji == kSlotString);

View file

@ -61,6 +61,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_stories.h" #include "data/data_stories.h"
#include "data/data_story.h" #include "data/data_story.h"
#include "data/data_user.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "main/main_session_settings.h" #include "main/main_session_settings.h"
#include "core/application.h" #include "core/application.h"
@ -363,10 +364,10 @@ Call ComputeCallData(const MTPDmessageActionPhoneCall &call) {
return result; return result;
} }
Giveaway ComputeGiveawayData( GiveawayStart ComputeGiveawayStartData(
not_null<HistoryItem*> item, not_null<HistoryItem*> item,
const MTPDmessageMediaGiveaway &data) { const MTPDmessageMediaGiveaway &data) {
auto result = Giveaway{ auto result = GiveawayStart{
.untilDate = data.vuntil_date().v, .untilDate = data.vuntil_date().v,
.quantity = data.vquantity().v, .quantity = data.vquantity().v,
.months = data.vmonths().v, .months = data.vmonths().v,
@ -389,6 +390,32 @@ Giveaway ComputeGiveawayData(
return result; return result;
} }
GiveawayResults ComputeGiveawayResultsData(
not_null<HistoryItem*> item,
const MTPDmessageMediaGiveawayResults &data) {
const auto additional = data.vadditional_peers_count();
auto result = GiveawayResults{
.channel = item->history()->owner().channel(data.vchannel_id()),
.untilDate = data.vuntil_date().v,
.launchId = data.vlaunch_msg_id().v,
.additionalPeersCount = additional.value_or_empty(),
.winnersCount = data.vwinners_count().v,
.unclaimedCount = data.vunclaimed_count().v,
.months = data.vmonths().v,
.refunded = data.is_refunded(),
.all = !data.is_only_new_subscribers(),
};
result.winners.reserve(data.vwinners().v.size());
const auto owner = &item->history()->owner();
for (const auto &id : data.vwinners().v) {
result.winners.push_back(owner->user(UserId(id)));
}
if (const auto additional = data.vprize_description()) {
result.additionalPrize = qs(*additional);
}
return result;
}
Media::Media(not_null<HistoryItem*> parent) : _parent(parent) { Media::Media(not_null<HistoryItem*> parent) : _parent(parent) {
} }
@ -456,7 +483,11 @@ bool Media::storyMention() const {
return false; return false;
} }
const Giveaway *Media::giveaway() const { const GiveawayStart *Media::giveawayStart() const {
return nullptr;
}
const GiveawayResults *Media::giveawayResults() const {
return nullptr; return nullptr;
} }
@ -2241,53 +2272,103 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
} }
} }
MediaGiveaway::MediaGiveaway( MediaGiveawayStart::MediaGiveawayStart(
not_null<HistoryItem*> parent, not_null<HistoryItem*> parent,
const Giveaway &data) const GiveawayStart &data)
: Media(parent) : Media(parent)
, _giveaway(data) { , _data(data) {
parent->history()->session().giftBoxStickersPacks().load(); parent->history()->session().giftBoxStickersPacks().load();
} }
std::unique_ptr<Media> MediaGiveaway::clone(not_null<HistoryItem*> parent) { std::unique_ptr<Media> MediaGiveawayStart::clone(
return std::make_unique<MediaGiveaway>(parent, _giveaway); not_null<HistoryItem*> parent) {
return std::make_unique<MediaGiveawayStart>(parent, _data);
} }
const Giveaway *MediaGiveaway::giveaway() const { const GiveawayStart *MediaGiveawayStart::giveawayStart() const {
return &_giveaway; return &_data;
} }
TextWithEntities MediaGiveaway::notificationText() const { TextWithEntities MediaGiveawayStart::notificationText() const {
return { return {
.text = tr::lng_prizes_title(tr::now, lt_count, _giveaway.quantity), .text = tr::lng_prizes_title(tr::now, lt_count, _data.quantity),
}; };
} }
QString MediaGiveaway::pinnedTextSubstring() const { QString MediaGiveawayStart::pinnedTextSubstring() const {
return QString::fromUtf8("\xC2\xAB") return QString::fromUtf8("\xC2\xAB")
+ notificationText().text + notificationText().text
+ QString::fromUtf8("\xC2\xBB"); + QString::fromUtf8("\xC2\xBB");
} }
TextForMimeData MediaGiveaway::clipboardText() const { TextForMimeData MediaGiveawayStart::clipboardText() const {
return TextForMimeData(); return TextForMimeData();
} }
bool MediaGiveaway::updateInlineResultMedia(const MTPMessageMedia &media) { bool MediaGiveawayStart::updateInlineResultMedia(const MTPMessageMedia &media) {
return true; return true;
} }
bool MediaGiveaway::updateSentMedia(const MTPMessageMedia &media) { bool MediaGiveawayStart::updateSentMedia(const MTPMessageMedia &media) {
return true; return true;
} }
std::unique_ptr<HistoryView::Media> MediaGiveaway::createView( std::unique_ptr<HistoryView::Media> MediaGiveawayStart::createView(
not_null<HistoryView::Element*> message, not_null<HistoryView::Element*> message,
not_null<HistoryItem*> realParent, not_null<HistoryItem*> realParent,
HistoryView::Element *replacing) { HistoryView::Element *replacing) {
return std::make_unique<HistoryView::MediaInBubble>( return std::make_unique<HistoryView::MediaInBubble>(
message, message,
HistoryView::GenerateGiveawayStart(message, &_giveaway)); HistoryView::GenerateGiveawayStart(message, &_data));
}
MediaGiveawayResults::MediaGiveawayResults(
not_null<HistoryItem*> parent,
const GiveawayResults &data)
: Media(parent)
, _data(data) {
}
std::unique_ptr<Media> MediaGiveawayResults::clone(
not_null<HistoryItem*> parent) {
return std::make_unique<MediaGiveawayResults>(parent, _data);
}
const GiveawayResults *MediaGiveawayResults::giveawayResults() const {
return &_data;
}
TextWithEntities MediaGiveawayResults::notificationText() const {
return {
.text = tr::lng_prizes_results_title(tr::now),
};
}
QString MediaGiveawayResults::pinnedTextSubstring() const {
return QString::fromUtf8("\xC2\xAB")
+ notificationText().text
+ QString::fromUtf8("\xC2\xBB");
}
TextForMimeData MediaGiveawayResults::clipboardText() const {
return TextForMimeData();
}
bool MediaGiveawayResults::updateInlineResultMedia(const MTPMessageMedia &media) {
return true;
}
bool MediaGiveawayResults::updateSentMedia(const MTPMessageMedia &media) {
return true;
}
std::unique_ptr<HistoryView::Media> MediaGiveawayResults::createView(
not_null<HistoryView::Element*> message,
not_null<HistoryItem*> realParent,
HistoryView::Element *replacing) {
return std::make_unique<HistoryView::MediaInBubble>(
message,
HistoryView::GenerateGiveawayResults(message, &_data));
} }
} // namespace Data } // namespace Data

View file

@ -90,7 +90,7 @@ struct Invoice {
bool isTest = false; bool isTest = false;
}; };
struct Giveaway { struct GiveawayStart {
std::vector<not_null<ChannelData*>> channels; std::vector<not_null<ChannelData*>> channels;
std::vector<QString> countries; std::vector<QString> countries;
QString additionalPrize; QString additionalPrize;
@ -100,6 +100,20 @@ struct Giveaway {
bool all = false; bool all = false;
}; };
struct GiveawayResults {
not_null<ChannelData*> channel;
std::vector<not_null<PeerData*>> winners;
QString additionalPrize;
TimeId untilDate = 0;
MsgId launchId = 0;
int additionalPeersCount = 0;
int winnersCount = 0;
int unclaimedCount = 0;
int months = 0;
bool refunded = false;
bool all = false;
};
struct GiftCode { struct GiftCode {
QString slug; QString slug;
ChannelData *channel = nullptr; ChannelData *channel = nullptr;
@ -136,7 +150,8 @@ public:
virtual FullStoryId storyId() const; virtual FullStoryId storyId() const;
virtual bool storyExpired(bool revalidate = false); virtual bool storyExpired(bool revalidate = false);
virtual bool storyMention() const; virtual bool storyMention() const;
virtual const Giveaway *giveaway() const; virtual const GiveawayStart *giveawayStart() const;
virtual const GiveawayResults *giveawayResults() const;
virtual bool uploading() const; virtual bool uploading() const;
virtual Storage::SharedMediaTypesMask sharedMediaTypes() const; virtual Storage::SharedMediaTypesMask sharedMediaTypes() const;
@ -635,15 +650,15 @@ private:
}; };
class MediaGiveaway final : public Media { class MediaGiveawayStart final : public Media {
public: public:
MediaGiveaway( MediaGiveawayStart(
not_null<HistoryItem*> parent, not_null<HistoryItem*> parent,
const Giveaway &data); const GiveawayStart &data);
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override; std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
const Giveaway *giveaway() const override; const GiveawayStart *giveawayStart() const override;
TextWithEntities notificationText() const override; TextWithEntities notificationText() const override;
QString pinnedTextSubstring() const override; QString pinnedTextSubstring() const override;
@ -657,7 +672,33 @@ public:
HistoryView::Element *replacing = nullptr) override; HistoryView::Element *replacing = nullptr) override;
private: private:
Giveaway _giveaway; GiveawayStart _data;
};
class MediaGiveawayResults final : public Media {
public:
MediaGiveawayResults(
not_null<HistoryItem*> parent,
const GiveawayResults &data);
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
const GiveawayResults *giveawayResults() 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:
GiveawayResults _data;
}; };
@ -671,8 +712,12 @@ private:
[[nodiscard]] Call ComputeCallData(const MTPDmessageActionPhoneCall &call); [[nodiscard]] Call ComputeCallData(const MTPDmessageActionPhoneCall &call);
[[nodiscard]] Giveaway ComputeGiveawayData( [[nodiscard]] GiveawayStart ComputeGiveawayStartData(
not_null<HistoryItem*> item, not_null<HistoryItem*> item,
const MTPDmessageMediaGiveaway &data); const MTPDmessageMediaGiveaway &data);
[[nodiscard]] GiveawayResults ComputeGiveawayResultsData(
not_null<HistoryItem*> item,
const MTPDmessageMediaGiveawayResults &data);
} // namespace Data } // namespace Data

View file

@ -681,8 +681,8 @@ Poll ParsePoll(const MTPDmessageMediaPoll &data) {
return result; return result;
} }
Giveaway ParseGiveaway(const MTPDmessageMediaGiveaway &data) { GiveawayStart ParseGiveaway(const MTPDmessageMediaGiveaway &data) {
auto result = Giveaway{ auto result = GiveawayStart{
.untilDate = data.vuntil_date().v, .untilDate = data.vuntil_date().v,
.quantity = data.vquantity().v, .quantity = data.vquantity().v,
.months = data.vmonths().v, .months = data.vmonths().v,

View file

@ -197,7 +197,7 @@ struct Poll {
bool closed = false; bool closed = false;
}; };
struct Giveaway { struct GiveawayStart {
std::vector<ChannelId> channels; std::vector<ChannelId> channels;
TimeId untilDate = 0; TimeId untilDate = 0;
int quantity = 0; int quantity = 0;
@ -336,7 +336,7 @@ struct Media {
Game, Game,
Invoice, Invoice,
Poll, Poll,
Giveaway, GiveawayStart,
UnsupportedMedia> content; UnsupportedMedia> content;
TimeId ttl = 0; TimeId ttl = 0;

View file

@ -613,7 +613,7 @@ private:
[[nodiscard]] QByteArray pushPoll(const Data::Poll &data); [[nodiscard]] QByteArray pushPoll(const Data::Poll &data);
[[nodiscard]] QByteArray pushGiveaway( [[nodiscard]] QByteArray pushGiveaway(
const PeersMap &peers, const PeersMap &peers,
const Data::Giveaway &data); const Data::GiveawayStart &data);
File _file; File _file;
QByteArray _composedStart; QByteArray _composedStart;
@ -1501,7 +1501,7 @@ QByteArray HtmlWriter::Wrap::pushMedia(
return pushPhotoMedia(*photo, basePath); return pushPhotoMedia(*photo, basePath);
} else if (const auto poll = std::get_if<Poll>(&content)) { } else if (const auto poll = std::get_if<Poll>(&content)) {
return pushPoll(*poll); return pushPoll(*poll);
} else if (const auto giveaway = std::get_if<Giveaway>(&content)) { } else if (const auto giveaway = std::get_if<GiveawayStart>(&content)) {
return pushGiveaway(peers, *giveaway); return pushGiveaway(peers, *giveaway);
} }
Assert(v::is_null(content)); Assert(v::is_null(content));
@ -1826,7 +1826,7 @@ QByteArray HtmlWriter::Wrap::pushPoll(const Data::Poll &data) {
QByteArray HtmlWriter::Wrap::pushGiveaway( QByteArray HtmlWriter::Wrap::pushGiveaway(
const PeersMap &peers, const PeersMap &peers,
const Data::Giveaway &data) { const Data::GiveawayStart &data) {
auto result = pushDiv("media_wrap clearfix"); auto result = pushDiv("media_wrap clearfix");
result.append(pushDiv("media_giveaway")); result.append(pushDiv("media_giveaway"));
@ -2028,7 +2028,7 @@ MediaData HtmlWriter::Wrap::prepareMediaData(
result.description = data.description; result.description = data.description;
result.status = Data::FormatMoneyAmount(data.amount, data.currency); result.status = Data::FormatMoneyAmount(data.amount, data.currency);
}, [](const Poll &data) { }, [](const Poll &data) {
}, [](const Giveaway &data) { }, [](const GiveawayStart &data) {
}, [](const UnsupportedMedia &data) { }, [](const UnsupportedMedia &data) {
Unexpected("Unsupported message."); Unexpected("Unsupported message.");
}, [](v::null_t) {}); }, [](v::null_t) {});

View file

@ -753,7 +753,7 @@ QByteArray SerializeMessage(
{ "total_voters", NumberToString(data.totalVotes) }, { "total_voters", NumberToString(data.totalVotes) },
{ "answers", serialized } { "answers", serialized }
})); }));
}, [&](const Giveaway &data) { }, [&](const GiveawayStart &data) {
context.nesting.push_back(Context::kObject); context.nesting.push_back(Context::kObject);
const auto channels = ranges::views::all( const auto channels = ranges::views::all(
data.channels data.channels

View file

@ -767,8 +767,9 @@ void GenerateItems(
using LogDeleteTopic = MTPDchannelAdminLogEventActionDeleteTopic; using LogDeleteTopic = MTPDchannelAdminLogEventActionDeleteTopic;
using LogPinTopic = MTPDchannelAdminLogEventActionPinTopic; using LogPinTopic = MTPDchannelAdminLogEventActionPinTopic;
using LogToggleAntiSpam = MTPDchannelAdminLogEventActionToggleAntiSpam; using LogToggleAntiSpam = MTPDchannelAdminLogEventActionToggleAntiSpam;
using LogChangeColor = MTPDchannelAdminLogEventActionChangeColor; using LogChangePeerColor = MTPDchannelAdminLogEventActionChangePeerColor;
using LogChangeBackgroundEmoji = MTPDchannelAdminLogEventActionChangeBackgroundEmoji; using LogChangeProfilePeerColor = MTPDchannelAdminLogEventActionChangeProfilePeerColor;
using LogChangeWallpaper = MTPDchannelAdminLogEventActionChangeWallpaper;
const auto session = &history->session(); const auto session = &history->session();
const auto id = event.vid().v; const auto id = event.vid().v;
@ -1817,52 +1818,94 @@ void GenerateItems(
addSimpleServiceMessage(text); addSimpleServiceMessage(text);
}; };
const auto createChangeColor = [&](const LogChangeColor &data) { const auto createColorChange = [&](
const auto text = tr::lng_admin_log_change_color( const MTPPeerColor &was,
tr::now, const MTPPeerColor &now,
lt_from, const auto &colorPhrase,
fromLinkText, const auto &setEmoji,
lt_previous, const auto &removeEmoji,
{ '#' + QString::number(data.vprev_value().v + 1) }, const auto &changeEmoji) {
lt_color, const auto prevColor = was.data().vcolor();
{ '#' + QString::number(data.vnew_value().v + 1) }, const auto nextColor = now.data().vcolor();
Ui::Text::WithEntities); if (prevColor != nextColor) {
addSimpleServiceMessage(text); const auto wrap = [&](tl::conditional<MTPint> value) {
}; return value
? value->v
const auto createChangeBackgroundEmoji = [&](const LogChangeBackgroundEmoji &data) { : Data::DecideColorIndex(history->peer->id);
const auto was = data.vprev_value().v; };
const auto now = data.vnew_value().v; const auto text = colorPhrase(
const auto text = !was
? tr::lng_admin_log_set_background_emoji(
tr::now,
lt_from,
fromLinkText,
lt_emoji,
Ui::Text::SingleCustomEmoji(
Data::SerializeCustomEmojiId(now)),
Ui::Text::WithEntities)
: !now
? tr::lng_admin_log_removed_background_emoji(
tr::now,
lt_from,
fromLinkText,
lt_emoji,
Ui::Text::SingleCustomEmoji(
Data::SerializeCustomEmojiId(was)),
Ui::Text::WithEntities)
: tr::lng_admin_log_change_background_emoji(
tr::now, tr::now,
lt_from, lt_from,
fromLinkText, fromLinkText,
lt_previous, lt_previous,
Ui::Text::SingleCustomEmoji( { '#' + QString::number(wrap(prevColor) + 1) },
Data::SerializeCustomEmojiId(was)), lt_color,
lt_emoji, { '#' + QString::number(wrap(nextColor) + 1) },
Ui::Text::SingleCustomEmoji(
Data::SerializeCustomEmojiId(now)),
Ui::Text::WithEntities); Ui::Text::WithEntities);
addSimpleServiceMessage(text); addSimpleServiceMessage(text);
}
const auto prevEmoji = was.data().vbackground_emoji_id().value_or_empty();
const auto nextEmoji = now.data().vbackground_emoji_id().value_or_empty();
if (prevEmoji != nextEmoji) {
const auto text = !prevEmoji
? setEmoji(
tr::now,
lt_from,
fromLinkText,
lt_emoji,
Ui::Text::SingleCustomEmoji(
Data::SerializeCustomEmojiId(nextEmoji)),
Ui::Text::WithEntities)
: !nextEmoji
? removeEmoji(
tr::now,
lt_from,
fromLinkText,
lt_emoji,
Ui::Text::SingleCustomEmoji(
Data::SerializeCustomEmojiId(prevEmoji)),
Ui::Text::WithEntities)
: changeEmoji(
tr::now,
lt_from,
fromLinkText,
lt_previous,
Ui::Text::SingleCustomEmoji(
Data::SerializeCustomEmojiId(prevEmoji)),
lt_emoji,
Ui::Text::SingleCustomEmoji(
Data::SerializeCustomEmojiId(nextEmoji)),
Ui::Text::WithEntities);
addSimpleServiceMessage(text);
}
};
const auto createChangePeerColor = [&](const LogChangePeerColor &data) {
createColorChange(
data.vprev_value(),
data.vnew_value(),
tr::lng_admin_log_change_color,
tr::lng_admin_log_set_background_emoji,
tr::lng_admin_log_removed_background_emoji,
tr::lng_admin_log_change_background_emoji);
};
const auto createChangeProfilePeerColor = [&](const LogChangeProfilePeerColor &data) {
createColorChange(
data.vprev_value(),
data.vnew_value(),
tr::lng_admin_log_change_profile_color,
tr::lng_admin_log_set_profile_background_emoji,
tr::lng_admin_log_removed_profile_background_emoji,
tr::lng_admin_log_change_profile_background_emoji);
};
const auto createChangeWallpaper = [&](const LogChangeWallpaper &data) {
addSimpleServiceMessage(tr::lng_admin_log_change_wallpaper(
tr::now,
lt_from,
fromLinkText,
Ui::Text::WithEntities));
}; };
action.match( action.match(
@ -1909,8 +1952,9 @@ void GenerateItems(
createDeleteTopic, createDeleteTopic,
createPinTopic, createPinTopic,
createToggleAntiSpam, createToggleAntiSpam,
createChangeColor, createChangePeerColor,
createChangeBackgroundEmoji); createChangeProfilePeerColor,
createChangeWallpaper);
} }
} // namespace AdminLog } // namespace AdminLog

View file

@ -311,13 +311,13 @@ std::unique_ptr<Data::Media> HistoryItem::CreateMedia(
media.vid().v, media.vid().v,
}, media.is_via_mention()); }, media.is_via_mention());
}, [&](const MTPDmessageMediaGiveaway &media) -> Result { }, [&](const MTPDmessageMediaGiveaway &media) -> Result {
return std::make_unique<Data::MediaGiveaway>( return std::make_unique<Data::MediaGiveawayStart>(
item, item,
Data::ComputeGiveawayData(item, media)); Data::ComputeGiveawayStartData(item, media));
}, [&](const MTPDmessageMediaGiveawayResults &media) -> Result { }, [&](const MTPDmessageMediaGiveawayResults &media) -> Result {
return nullptr;/* std::make_unique<Data::MediaGiveaway>( return std::make_unique<Data::MediaGiveawayResults>(
item, item,
Data::ComputeGiveawayData(item, media));*/ Data::ComputeGiveawayResultsData(item, media));
}, [](const MTPDmessageMediaEmpty &) -> Result { }, [](const MTPDmessageMediaEmpty &) -> Result {
return nullptr; return nullptr;
}, [](const MTPDmessageMediaUnsupported &) -> Result { }, [](const MTPDmessageMediaUnsupported &) -> Result {

View file

@ -403,6 +403,11 @@ Message::Message(
, _bottomInfo( , _bottomInfo(
&data->history()->owner().reactions(), &data->history()->owner().reactions(),
BottomInfoDataFromMessage(this)) { BottomInfoDataFromMessage(this)) {
if (const auto media = data->media()) {
if (media->giveawayResults()) {
_hideReply = 1;
}
}
initLogEntryOriginal(); initLogEntryOriginal();
initPsa(); initPsa();
refreshReactions(); refreshReactions();

View file

@ -23,14 +23,21 @@ namespace {
[[nodiscard]] ClickHandlerPtr MakeMediaButtonClickHandler( [[nodiscard]] ClickHandlerPtr MakeMediaButtonClickHandler(
not_null<Data::Media*> media) { not_null<Data::Media*> media) {
const auto giveaway = media->giveaway(); const auto start = media->giveawayStart();
Assert(giveaway != nullptr); const auto results = media->giveawayResults();
Assert(start || results);
const auto peer = media->parent()->history()->peer; const auto peer = media->parent()->history()->peer;
const auto messageId = media->parent()->id; const auto messageId = media->parent()->id;
if (media->parent()->isSending() || media->parent()->hasFailed()) { if (media->parent()->isSending() || media->parent()->hasFailed()) {
return nullptr; return nullptr;
} }
const auto info = *giveaway; const auto maybeStart = start
? *start
: std::optional<Data::GiveawayStart>();
const auto maybeResults = results
? *results
: std::optional<Data::GiveawayResults>();
return std::make_shared<LambdaClickHandler>([=]( return std::make_shared<LambdaClickHandler>([=](
ClickContext context) { ClickContext context) {
const auto my = context.other.value<ClickHandlerContext>(); const auto my = context.other.value<ClickHandlerContext>();
@ -38,13 +45,18 @@ namespace {
if (!controller) { if (!controller) {
return; return;
} }
ResolveGiveawayInfo(controller, peer, messageId, info); ResolveGiveawayInfo(
controller,
peer,
messageId,
maybeStart,
maybeResults);
}); });
} }
[[nodiscard]] QString MakeMediaButtonText(not_null<Data::Media*> media) { [[nodiscard]] QString MakeMediaButtonText(not_null<Data::Media*> media) {
const auto giveaway = media->giveaway(); Expects(media->giveawayStart() || media->giveawayResults());
Assert(giveaway != nullptr);
return Ui::Text::Upper(tr::lng_prizes_how_works(tr::now)); return Ui::Text::Upper(tr::lng_prizes_how_works(tr::now));
} }
@ -72,7 +84,7 @@ struct ViewButton::Inner {
}; };
bool ViewButton::MediaHasViewButton(not_null<Data::Media*> media) { bool ViewButton::MediaHasViewButton(not_null<Data::Media*> media) {
return (media->giveaway() != nullptr); return media->giveawayStart() || media->giveawayResults();
} }
ViewButton::Inner::Inner( ViewButton::Inner::Inner(

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h" #include "base/unixtime.h"
#include "boxes/gift_premium_box.h" #include "boxes/gift_premium_box.h"
#include "chat_helpers/stickers_gift_box_pack.h" #include "chat_helpers/stickers_gift_box_pack.h"
#include "chat_helpers/stickers_dice_pack.h"
#include "countries/countries_instance.h" #include "countries/countries_instance.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_document.h" #include "data/data_document.h"
@ -19,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "history/history_item_components.h" #include "history/history_item_components.h"
#include "history/history_item_helpers.h"
#include "history/view/history_view_element.h" #include "history/view/history_view_element.h"
#include "history/view/history_view_cursor_state.h" #include "history/view/history_view_cursor_state.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -54,7 +56,8 @@ constexpr auto kAdditionalPrizesWithLineOpacity = 0.6;
TextState MediaInBubble::Part::textState( TextState MediaInBubble::Part::textState(
QPoint point, QPoint point,
StateRequest request) const { StateRequest request,
int outerWidth) const {
return {}; return {};
} }
@ -127,7 +130,8 @@ TextState MediaInBubble::textState(
StateRequest request) const { StateRequest request) const {
auto result = TextState(_parent); auto result = TextState(_parent);
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) { const auto outer = width();
if (outer < st::msgPadding.left() + st::msgPadding.right() + 1) {
return result; return result;
} }
@ -135,7 +139,7 @@ TextState MediaInBubble::textState(
const auto raw = entry.object.get(); const auto raw = entry.object.get();
const auto height = raw->height(); const auto height = raw->height();
if (point.y() >= 0 && point.y() < height) { if (point.y() >= 0 && point.y() < height) {
const auto part = raw->textState(point, request); const auto part = raw->textState(point, request, outer);
result.link = part.link; result.link = part.link;
return result; return result;
} }
@ -186,10 +190,14 @@ QMargins MediaInBubble::inBubblePadding() const {
TextMediaInBubblePart::TextMediaInBubblePart( TextMediaInBubblePart::TextMediaInBubblePart(
TextWithEntities text, TextWithEntities text,
QMargins margins) QMargins margins,
const base::flat_map<uint16, ClickHandlerPtr> &links)
: _text(st::msgMinWidth) : _text(st::msgMinWidth)
, _margins(margins) { , _margins(margins) {
_text.setMarkedText(st::defaultTextStyle, text); _text.setMarkedText(st::defaultTextStyle, text);
for (const auto &[index, link] : links) {
_text.setLink(index, link);
}
} }
void TextMediaInBubblePart::draw( void TextMediaInBubblePart::draw(
@ -207,6 +215,18 @@ void TextMediaInBubblePart::draw(
}); });
} }
TextState TextMediaInBubblePart::textState(
QPoint point,
StateRequest request,
int outerWidth) const {
point -= QPoint{ (outerWidth - width()) / 2, _margins.top() };
auto result = TextState();
auto forText = request.forText();
forText.align = style::al_top;
result.link = _text.getState(point, width(), forText).link;
return result;
}
QSize TextMediaInBubblePart::countOptimalSize() { QSize TextMediaInBubblePart::countOptimalSize() {
return { return {
_margins.left() + _text.maxWidth() + _margins.right(), _margins.left() + _text.maxWidth() + _margins.right(),
@ -278,7 +298,7 @@ QSize TextDelimeterPart::countCurrentSize(int newWidth) {
StickerWithBadgePart::StickerWithBadgePart( StickerWithBadgePart::StickerWithBadgePart(
not_null<Element*> parent, not_null<Element*> parent,
Fn<DocumentData*()> lookup, Fn<Data()> lookup,
QString badge) QString badge)
: _parent(parent) : _parent(parent)
, _lookup(std::move(lookup)) , _lookup(std::move(lookup))
@ -293,7 +313,7 @@ void StickerWithBadgePart::draw(
const auto stickerSize = st::msgServiceGiftBoxStickerSize; const auto stickerSize = st::msgServiceGiftBoxStickerSize;
const auto sticker = QRect( const auto sticker = QRect(
(outerWidth - stickerSize.width()) / 2, (outerWidth - stickerSize.width()) / 2,
st::chatGiveawayStickerTop, st::chatGiveawayStickerTop + _skipTop,
stickerSize.width(), stickerSize.width(),
stickerSize.height()); stickerSize.height());
@ -327,12 +347,14 @@ QSize StickerWithBadgePart::countCurrentSize(int newWidth) {
void StickerWithBadgePart::ensureCreated() const { void StickerWithBadgePart::ensureCreated() const {
if (_sticker) { if (_sticker) {
return; return;
} else if (const auto document = _lookup()) { } else if (const auto data = _lookup()) {
const auto document = data.sticker;
if (const auto sticker = document->sticker()) { if (const auto sticker = document->sticker()) {
const auto skipPremiumEffect = false; const auto skipPremiumEffect = false;
_skipTop = data.skipTop;
_sticker.emplace(_parent, document, skipPremiumEffect, _parent); _sticker.emplace(_parent, document, skipPremiumEffect, _parent);
_sticker->setDiceIndex(sticker->alt, 1); _sticker->setDiceIndex(sticker->alt, 1);
_sticker->setGiftBoxSticker(true); _sticker->setGiftBoxSticker(data.isGiftBoxSticker);
_sticker->initSize(); _sticker->initSize();
} }
} }
@ -427,6 +449,7 @@ PeerBubbleListPart::PeerBubbleListPart(
kDefaultTextOptions, kDefaultTextOptions,
st::msgMinWidth), st::msgMinWidth),
.thumbnail = Dialogs::Stories::MakeUserpicThumbnail(peer), .thumbnail = Dialogs::Stories::MakeUserpicThumbnail(peer),
.link = peer->openLink(),
.colorIndex = peer->colorIndex(), .colorIndex = peer->colorIndex(),
}); });
} }
@ -528,9 +551,43 @@ int PeerBubbleListPart::layout(int x, int y, int available) {
return y + size + skip; return y + size + skip;
} }
TextState PeerBubbleListPart::textState(
QPoint point,
StateRequest request,
int outerWidth) const {
auto result = TextState(_parent);
for (const auto &peer : _peers) {
if (peer.geometry.contains(point)) {
result.link = peer.link;
_lastPoint = point;
break;
}
}
return result;
}
void PeerBubbleListPart::clickHandlerPressedChanged( void PeerBubbleListPart::clickHandlerPressedChanged(
const ClickHandlerPtr &p, const ClickHandlerPtr &p,
bool pressed) { bool pressed) {
for (auto &peer : _peers) {
if (peer.link != p) {
continue;
}
if (pressed) {
if (!peer.ripple) {
peer.ripple = std::make_unique<Ui::RippleAnimation>(
st::defaultRippleAnimation,
Ui::RippleAnimation::RoundRectMask(
peer.geometry.size(),
peer.geometry.height() / 2),
[=] { _parent->repaint(); });
}
peer.ripple->add(_lastPoint - peer.geometry.topLeft());
} else if (peer.ripple) {
peer.ripple->lastStop();
}
break;
}
} }
bool PeerBubbleListPart::hasHeavyPart() { bool PeerBubbleListPart::hasHeavyPart() {
@ -579,18 +636,19 @@ QSize PeerBubbleListPart::countCurrentSize(int newWidth) {
auto GenerateGiveawayStart( auto GenerateGiveawayStart(
not_null<Element*> parent, not_null<Element*> parent,
not_null<Data::Giveaway*> giveaway) not_null<Data::GiveawayStart*> data)
-> Fn<void(Fn<void(std::unique_ptr<MediaInBubble::Part>)>)> { -> Fn<void(Fn<void(std::unique_ptr<MediaInBubble::Part>)>)> {
return [=](Fn<void(std::unique_ptr<MediaInBubble::Part>)> push) { return [=](Fn<void(std::unique_ptr<MediaInBubble::Part>)> push) {
const auto months = giveaway->months; const auto months = data->months;
const auto quantity = giveaway->quantity; const auto quantity = data->quantity;
using Data = StickerWithBadgePart::Data;
const auto sticker = [=] { const auto sticker = [=] {
const auto &session = parent->history()->session(); const auto &session = parent->history()->session();
auto &packs = session.giftBoxStickersPacks(); auto &packs = session.giftBoxStickersPacks();
return packs.lookup(months); return Data{ packs.lookup(months), 0, true };
}; };
push(std::make_unique<HistoryView::StickerWithBadgePart>( push(std::make_unique<StickerWithBadgePart>(
parent, parent,
sticker, sticker,
tr::lng_prizes_badge( tr::lng_prizes_badge(
@ -598,27 +656,31 @@ auto GenerateGiveawayStart(
lt_amount, lt_amount,
QString::number(quantity)))); QString::number(quantity))));
auto pushText = [&](TextWithEntities text, QMargins margins = {}) { auto pushText = [&](
push(std::make_unique<HistoryView::TextMediaInBubblePart>( TextWithEntities text,
QMargins margins = {},
const base::flat_map<uint16, ClickHandlerPtr> &links = {}) {
push(std::make_unique<TextMediaInBubblePart>(
std::move(text), std::move(text),
margins)); margins,
links));
}; };
pushText( pushText(
Ui::Text::Bold( Ui::Text::Bold(
tr::lng_prizes_title(tr::now, lt_count, quantity)), tr::lng_prizes_title(tr::now, lt_count, quantity)),
st::chatGiveawayPrizesTitleMargin); st::chatGiveawayPrizesTitleMargin);
if (!giveaway->additionalPrize.isEmpty()) { if (!data->additionalPrize.isEmpty()) {
pushText( pushText(
tr::lng_prizes_additional( tr::lng_prizes_additional(
tr::now, tr::now,
lt_count, lt_count,
quantity, quantity,
lt_prize, lt_prize,
TextWithEntities{ giveaway->additionalPrize }, TextWithEntities{ data->additionalPrize },
Ui::Text::RichLangValue), Ui::Text::RichLangValue),
st::chatGiveawayPrizesMargin); st::chatGiveawayPrizesMargin);
push(std::make_unique<HistoryView::TextDelimeterPart>( push(std::make_unique<TextDelimeterPart>(
tr::lng_prizes_additional_with(tr::now), tr::lng_prizes_additional_with(tr::now),
st::chatGiveawayPrizesWithPadding)); st::chatGiveawayPrizesWithPadding));
} }
@ -636,26 +698,26 @@ auto GenerateGiveawayStart(
Ui::Text::Bold(tr::lng_prizes_participants(tr::now)), Ui::Text::Bold(tr::lng_prizes_participants(tr::now)),
st::chatGiveawayPrizesTitleMargin); st::chatGiveawayPrizesTitleMargin);
pushText({ (giveaway->all pushText({ (data->all
? tr::lng_prizes_participants_all ? tr::lng_prizes_participants_all
: tr::lng_prizes_participants_new)( : tr::lng_prizes_participants_new)(
tr::now, tr::now,
lt_count, lt_count,
giveaway->channels.size()), data->channels.size()),
}, st::chatGiveawayParticipantsMargin); }, st::chatGiveawayParticipantsMargin);
auto list = ranges::views::all( auto list = ranges::views::all(
giveaway->channels data->channels
) | ranges::views::transform([](not_null<ChannelData*> channel) { ) | ranges::views::transform([](not_null<ChannelData*> channel) {
return not_null<PeerData*>(channel); return not_null<PeerData*>(channel);
}) | ranges::to_vector; }) | ranges::to_vector;
push(std::make_unique<HistoryView::PeerBubbleListPart>( push(std::make_unique<PeerBubbleListPart>(
parent, parent,
std::move(list))); std::move(list)));
const auto &instance = Countries::Instance(); const auto &instance = Countries::Instance();
auto countries = QStringList(); auto countries = QStringList();
for (const auto &country : giveaway->countries) { for (const auto &country : data->countries) {
const auto name = instance.countryNameByISO2(country); const auto name = instance.countryNameByISO2(country);
const auto flag = instance.flagEmojiByISO2(country); const auto flag = instance.flagEmojiByISO2(country);
countries.push_back(flag + QChar(0xA0) + name); countries.push_back(flag + QChar(0xA0) + name);
@ -683,7 +745,80 @@ auto GenerateGiveawayStart(
? st::chatGiveawayNoCountriesTitleMargin ? st::chatGiveawayNoCountriesTitleMargin
: st::chatGiveawayPrizesMargin)); : st::chatGiveawayPrizesMargin));
pushText({ pushText({
langDateTime(base::unixtime::parse(giveaway->untilDate)), langDateTime(base::unixtime::parse(data->untilDate)),
}, st::chatGiveawayEndDateMargin);
};
}
auto GenerateGiveawayResults(
not_null<Element*> parent,
not_null<Data::GiveawayResults*> data)
-> Fn<void(Fn<void(std::unique_ptr<MediaInBubble::Part>)>)> {
return [=](Fn<void(std::unique_ptr<MediaInBubble::Part>)> push) {
const auto months = data->months;
const auto quantity = data->winnersCount;
using Data = StickerWithBadgePart::Data;
const auto sticker = [=] {
const auto &session = parent->history()->session();
auto &packs = session.diceStickersPacks();
const auto &emoji = Stickers::DicePacks::kPartyPopper;
const auto skip = st::chatGiveawayWinnersTopSkip;
return Data{ packs.lookup(emoji, 0), skip };
};
push(std::make_unique<StickerWithBadgePart>(
parent,
sticker,
tr::lng_prizes_badge(
tr::now,
lt_amount,
QString::number(quantity))));
auto pushText = [&](
TextWithEntities text,
QMargins margins = {},
const base::flat_map<uint16, ClickHandlerPtr> &links = {}) {
push(std::make_unique<TextMediaInBubblePart>(
std::move(text),
margins,
links));
};
pushText(
Ui::Text::Bold(
tr::lng_prizes_results_title(tr::now)),
st::chatGiveawayPrizesTitleMargin);
const auto showGiveawayHandler = JumpToMessageClickHandler(
data->channel,
data->launchId,
parent->data()->fullId());
pushText(
tr::lng_prizes_results_about(
tr::now,
lt_count,
quantity,
lt_link,
Ui::Text::Link(tr::lng_prizes_results_link(tr::now)),
Ui::Text::RichLangValue),
st::chatGiveawayPrizesMargin,
{ { 1, showGiveawayHandler } });
pushText(
Ui::Text::Bold(tr::lng_prizes_results_winners(tr::now)),
st::chatGiveawayPrizesTitleMargin);
push(std::make_unique<PeerBubbleListPart>(
parent,
data->winners));
if (data->winnersCount > data->winners.size()) {
pushText(
Ui::Text::Bold(tr::lng_prizes_results_more(
tr::now,
lt_count,
data->winnersCount - data->winners.size())),
st::chatGiveawayNoCountriesTitleMargin);
}
pushText({ data->unclaimedCount
? tr::lng_prizes_results_some(tr::now)
: tr::lng_prizes_results_all(tr::now)
}, st::chatGiveawayEndDateMargin); }, st::chatGiveawayEndDateMargin);
}; };
} }

View file

@ -11,7 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/media/history_view_sticker.h" #include "history/view/media/history_view_sticker.h"
namespace Data { namespace Data {
struct Giveaway; struct GiveawayStart;
struct GiveawayResults;
} // namespace Data } // namespace Data
namespace Dialogs::Stories { namespace Dialogs::Stories {
@ -36,7 +37,8 @@ public:
int outerWidth) const = 0; int outerWidth) const = 0;
[[nodiscard]] virtual TextState textState( [[nodiscard]] virtual TextState textState(
QPoint point, QPoint point,
StateRequest request) const; StateRequest request,
int outerWidth) const;
virtual void clickHandlerPressedChanged( virtual void clickHandlerPressedChanged(
const ClickHandlerPtr &p, const ClickHandlerPtr &p,
bool pressed); bool pressed);
@ -82,7 +84,6 @@ public:
private: private:
struct Entry { struct Entry {
std::unique_ptr<Part> object; std::unique_ptr<Part> object;
int top = 0;
}; };
QSize countOptimalSize() override; QSize countOptimalSize() override;
@ -96,12 +97,19 @@ private:
class TextMediaInBubblePart final : public MediaInBubble::Part { class TextMediaInBubblePart final : public MediaInBubble::Part {
public: public:
TextMediaInBubblePart(TextWithEntities text, QMargins margins); TextMediaInBubblePart(
TextWithEntities text,
QMargins margins,
const base::flat_map<uint16, ClickHandlerPtr> &links = {});
void draw( void draw(
Painter &p, Painter &p,
const PaintContext &context, const PaintContext &context,
int outerWidth) const override; int outerWidth) const override;
TextState textState(
QPoint point,
StateRequest request,
int outerWidth) const override;
QSize countOptimalSize() override; QSize countOptimalSize() override;
QSize countCurrentSize(int newWidth) override; QSize countCurrentSize(int newWidth) override;
@ -132,9 +140,18 @@ private:
class StickerWithBadgePart final : public MediaInBubble::Part { class StickerWithBadgePart final : public MediaInBubble::Part {
public: public:
struct Data {
DocumentData *sticker = nullptr;
int skipTop = 0;
bool isGiftBoxSticker = false;
explicit operator bool() const {
return sticker != nullptr;
}
};
StickerWithBadgePart( StickerWithBadgePart(
not_null<Element*> parent, not_null<Element*> parent,
Fn<DocumentData*()> lookup, Fn<Data()> lookup,
QString badge); QString badge);
void draw( void draw(
@ -153,8 +170,9 @@ private:
void paintBadge(Painter &p, const PaintContext &context) const; void paintBadge(Painter &p, const PaintContext &context) const;
const not_null<Element*> _parent; const not_null<Element*> _parent;
Fn<DocumentData*()> _lookup; Fn<Data()> _lookup;
QString _badgeText; QString _badgeText;
mutable int _skipTop = 0;
mutable std::optional<Sticker> _sticker; mutable std::optional<Sticker> _sticker;
mutable QColor _badgeFg; mutable QColor _badgeFg;
mutable QColor _badgeBorder; mutable QColor _badgeBorder;
@ -173,6 +191,10 @@ public:
Painter &p, Painter &p,
const PaintContext &context, const PaintContext &context,
int outerWidth) const override; int outerWidth) const override;
TextState textState(
QPoint point,
StateRequest request,
int outerWidth) const override;
void clickHandlerPressedChanged( void clickHandlerPressedChanged(
const ClickHandlerPtr &p, const ClickHandlerPtr &p,
bool pressed) override; bool pressed) override;
@ -199,13 +221,19 @@ private:
const not_null<Element*> _parent; const not_null<Element*> _parent;
std::vector<Peer> _peers; std::vector<Peer> _peers;
mutable QPoint _lastPoint;
mutable bool _subscribed = false; mutable bool _subscribed = false;
}; };
[[nodiscard]] auto GenerateGiveawayStart( [[nodiscard]] auto GenerateGiveawayStart(
not_null<Element*> parent, not_null<Element*> parent,
not_null<Data::Giveaway*> giveaway) not_null<Data::GiveawayStart*> data)
-> Fn<void(Fn<void(std::unique_ptr<MediaInBubble::Part>)>)>;
[[nodiscard]] auto GenerateGiveawayResults(
not_null<Element*> parent,
not_null<Data::GiveawayResults*> data)
-> Fn<void(Fn<void(std::unique_ptr<MediaInBubble::Part>)>)>; -> Fn<void(Fn<void(std::unique_ptr<MediaInBubble::Part>)>)>;
} // namespace HistoryView } // namespace HistoryView

View file

@ -97,11 +97,11 @@ userStatusLastMonth#77ebc742 = UserStatus;
chatEmpty#29562865 id:long = Chat; chatEmpty#29562865 id:long = Chat;
chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat; chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
chatForbidden#6592a1a7 id:long title:string = Chat; chatForbidden#6592a1a7 id:long title:string = Chat;
channel#8e87ccd8 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor = Chat; channel#a636a3e2 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor = Chat;
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat; channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions = ChatFull; chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions = ChatFull;
channelFull#723027bd flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions stories:flags2.4?PeerStories = ChatFull; channelFull#f2bcb6f flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant; chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant; chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
@ -132,7 +132,7 @@ messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia;
messageMediaDice#3f7ee58b value:int emoticon:string = 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; messageMediaStory#68cb6283 flags:# via_mention:flags.1?true peer:Peer id:int story:flags.0?StoryItem = MessageMedia;
messageMediaGiveaway#daad85b0 flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.2?true channels:Vector<long> countries_iso2:flags.1?Vector<string> prize_description:flags.3?string quantity:int months:int until_date:int = MessageMedia; messageMediaGiveaway#daad85b0 flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.2?true channels:Vector<long> countries_iso2:flags.1?Vector<string> prize_description:flags.3?string quantity:int months:int until_date:int = MessageMedia;
messageMediaGiveawayResults#b11ff5a1 flags:# refunded:flags.0?true channel_id:long launch_msg_id:int winners_count:int unclaimed_count:int winners:Vector<long> months:int prize_description:flags.1?string = MessageMedia; messageMediaGiveawayResults#c6991068 flags:# only_new_subscribers:flags.0?true refunded:flags.2?true channel_id:long additional_peers_count:flags.3?int launch_msg_id:int winners_count:int unclaimed_count:int winners:Vector<long> months:int prize_description:flags.1?string until_date:int = MessageMedia;
messageActionEmpty#b6aef7b0 = MessageAction; messageActionEmpty#b6aef7b0 = MessageAction;
messageActionChatCreate#bd47cbad title:string users:Vector<long> = MessageAction; messageActionChatCreate#bd47cbad title:string users:Vector<long> = MessageAction;
@ -172,7 +172,7 @@ messageActionTopicEdit#c0944820 flags:# title:flags.0?string icon_emoji_id:flags
messageActionSuggestProfilePhoto#57de635e photo:Photo = MessageAction; messageActionSuggestProfilePhoto#57de635e photo:Photo = MessageAction;
messageActionRequestedPeer#fe77345d button_id:int peer:Peer = MessageAction; messageActionRequestedPeer#fe77345d button_id:int peer:Peer = MessageAction;
messageActionSetChatWallPaper#5060a3f4 flags:# same:flags.0?true for_both:flags.1?true wallpaper:WallPaper = MessageAction; messageActionSetChatWallPaper#5060a3f4 flags:# same:flags.0?true for_both:flags.1?true wallpaper:WallPaper = MessageAction;
messageActionGiftCode#d2cfdb0e flags:# via_giveaway:flags.0?true unclaimed:flags.2?true boost_peer:flags.1?Peer months:int slug:string = MessageAction; messageActionGiftCode#678c2e09 flags:# via_giveaway:flags.0?true unclaimed:flags.2?true boost_peer:flags.1?Peer months:int slug:string currency:flags.2?string amount:flags.2?long crypto_currency:flags.3?string crypto_amount:flags.3?long = MessageAction;
messageActionGiveawayLaunch#332ba9ed = MessageAction; messageActionGiveawayLaunch#332ba9ed = MessageAction;
messageActionGiveawayResults#2a9fadc5 winners_count:int unclaimed_count:int = MessageAction; messageActionGiveawayResults#2a9fadc5 winners_count:int unclaimed_count:int = MessageAction;
@ -970,8 +970,9 @@ channelAdminLogEventActionEditTopic#f06fe208 prev_topic:ForumTopic new_topic:For
channelAdminLogEventActionDeleteTopic#ae168909 topic:ForumTopic = ChannelAdminLogEventAction; channelAdminLogEventActionDeleteTopic#ae168909 topic:ForumTopic = ChannelAdminLogEventAction;
channelAdminLogEventActionPinTopic#5d8d353b flags:# prev_topic:flags.0?ForumTopic new_topic:flags.1?ForumTopic = ChannelAdminLogEventAction; channelAdminLogEventActionPinTopic#5d8d353b flags:# prev_topic:flags.0?ForumTopic new_topic:flags.1?ForumTopic = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleAntiSpam#64f36dfc new_value:Bool = ChannelAdminLogEventAction; channelAdminLogEventActionToggleAntiSpam#64f36dfc new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeColor#3c2b247b prev_value:int new_value:int = ChannelAdminLogEventAction; channelAdminLogEventActionChangePeerColor#5796e780 prev_value:PeerColor new_value:PeerColor = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeBackgroundEmoji#445fc434 prev_value:long new_value:long = ChannelAdminLogEventAction; channelAdminLogEventActionChangeProfilePeerColor#5e477b25 prev_value:PeerColor new_value:PeerColor = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeWallpaper#31bb5d52 prev_value:WallPaper new_value:WallPaper = ChannelAdminLogEventAction;
channelAdminLogEvent#1fad68cd id:long date:int user_id:long action:ChannelAdminLogEventAction = ChannelAdminLogEvent; channelAdminLogEvent#1fad68cd id:long date:int user_id:long action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
@ -1554,8 +1555,10 @@ stories.allStories#6efc5e81 flags:# has_more:flags.0?true count:int state:string
stories.stories#5dd8c3c8 count:int stories:Vector<StoryItem> chats:Vector<Chat> users:Vector<User> = stories.Stories; stories.stories#5dd8c3c8 count:int stories:Vector<StoryItem> chats:Vector<Chat> users:Vector<User> = stories.Stories;
storyView#b0bdeac5 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true user_id:long date:int reaction:flags.2?Reaction = StoryView; storyView#b0bdeac5 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true user_id:long date:int reaction:flags.2?Reaction = StoryView;
//storyViewPublicForward#9083670b flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true message:Message = StoryView;
//storyViewPublicRepost#bd74cf49 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true peer_id:Peer story:StoryItem = StoryView;
stories.storyViewsList#46e9b9ec flags:# count:int reactions_count:int views:Vector<StoryView> users:Vector<User> next_offset:flags.0?string = stories.StoryViewsList; stories.storyViewsList#19a16886 flags:# count:int views_count:int forwards_count:int reactions_count:int views:Vector<StoryView> users:Vector<User> next_offset:flags.0?string = stories.StoryViewsList;
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews; stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
@ -1620,10 +1623,11 @@ help.peerColorOption#135bd42f flags:# hidden:flags.0?true color_id:int colors:fl
help.peerColorsNotModified#2ba1f5ce = help.PeerColors; help.peerColorsNotModified#2ba1f5ce = help.PeerColors;
help.peerColors#f8ed08 hash:int colors:Vector<help.PeerColorOption> = help.PeerColors; help.peerColors#f8ed08 hash:int colors:Vector<help.PeerColorOption> = help.PeerColors;
storyPeerReaction#7decc433 peer_id:Peer date:int reaction:Reaction = StoryPeerReaction; storyReaction#6090d6d5 peer_id:Peer date:int reaction:Reaction = StoryReaction;
storyPeerPublicRepost#f7fbc17d peer_id:Peer story:StoryItem = StoryPeerReaction; storyReactionPublicForward#bbab2643 message:Message = StoryReaction;
storyReactionPublicRepost#cfcd0f13 peer_id:Peer story:StoryItem = StoryReaction;
stories.storyReactionsList#d86c162a flags:# count:int reactions:Vector<StoryPeerReaction> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = stories.StoryReactionsList; stories.storyReactionsList#aa5f789c flags:# count:int reactions:Vector<StoryReaction> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = stories.StoryReactionsList;
---functions--- ---functions---
@ -2068,7 +2072,7 @@ channels.toggleAntiSpam#68f3e4eb channel:InputChannel enabled:Bool = Updates;
channels.reportAntiSpamFalsePositive#a850a693 channel:InputChannel msg_id:int = Bool; channels.reportAntiSpamFalsePositive#a850a693 channel:InputChannel msg_id:int = Bool;
channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = Updates; channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = Updates;
channels.clickSponsoredMessage#18afbc93 channel:InputChannel random_id:bytes = Bool; channels.clickSponsoredMessage#18afbc93 channel:InputChannel random_id:bytes = Bool;
channels.updateColor#621a201f flags:# channel:InputChannel color:int background_emoji_id:flags.0?long = Updates; channels.updateColor#d8aa3671 flags:# for_profile:flags.1?true channel:InputChannel color:flags.2?int background_emoji_id:flags.0?long = Updates;
channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates; channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates;
channels.getChannelRecommendations#83b70d97 channel:InputChannel = messages.Chats; channels.getChannelRecommendations#83b70d97 channel:InputChannel = messages.Chats;
@ -2189,7 +2193,7 @@ stories.getStoriesByID#5774ca74 peer:InputPeer id:Vector<int> = stories.Stories;
stories.toggleAllStoriesHidden#7c2557c4 hidden:Bool = Bool; stories.toggleAllStoriesHidden#7c2557c4 hidden:Bool = Bool;
stories.readStories#a556dac8 peer:InputPeer max_id:int = Vector<int>; stories.readStories#a556dac8 peer:InputPeer max_id:int = Vector<int>;
stories.incrementStoryViews#b2028afb peer:InputPeer id:Vector<int> = Bool; stories.incrementStoryViews#b2028afb peer:InputPeer id:Vector<int> = Bool;
stories.getStoryViewsList#7ed23c57 flags:# just_contacts:flags.0?true reactions_first:flags.2?true peer:InputPeer q:flags.1?string id:int offset:string limit:int = stories.StoryViewsList; stories.getStoryViewsList#7ed23c57 flags:# just_contacts:flags.0?true reactions_first:flags.2?true forwards_first:flags.3?true peer:InputPeer q:flags.1?string id:int offset:string limit:int = stories.StoryViewsList;
stories.getStoriesViews#28e16cc8 peer:InputPeer id:Vector<int> = stories.StoryViews; stories.getStoriesViews#28e16cc8 peer:InputPeer id:Vector<int> = stories.StoryViews;
stories.exportStoryLink#7b8def20 peer:InputPeer id:int = ExportedStoryLink; stories.exportStoryLink#7b8def20 peer:InputPeer id:int = ExportedStoryLink;
stories.report#1923fa8c peer:InputPeer id:Vector<int> reason:ReportReason message:string = Bool; stories.report#1923fa8c peer:InputPeer id:Vector<int> reason:ReportReason message:string = Bool;
@ -2200,7 +2204,7 @@ stories.getAllReadPeerStories#9b5ae7f9 = Updates;
stories.getPeerMaxIDs#535983c3 id:Vector<InputPeer> = Vector<int>; stories.getPeerMaxIDs#535983c3 id:Vector<InputPeer> = Vector<int>;
stories.getChatsToSend#a56a8b60 = messages.Chats; stories.getChatsToSend#a56a8b60 = messages.Chats;
stories.togglePeerStoriesHidden#bd0415c4 peer:InputPeer hidden:Bool = Bool; stories.togglePeerStoriesHidden#bd0415c4 peer:InputPeer hidden:Bool = Bool;
stories.getStoryReactionsList#b9b2881f flags:# reposts_first:flags.2?true peer:InputPeer id:int reaction:flags.0?Reaction offset:flags.1?string limit:int = stories.StoryReactionsList; stories.getStoryReactionsList#b9b2881f flags:# forwards_first:flags.2?true peer:InputPeer id:int reaction:flags.0?Reaction offset:flags.1?string limit:int = stories.StoryReactionsList;
premium.getBoostsList#60f67660 flags:# gifts:flags.0?true peer:InputPeer offset:string limit:int = premium.BoostsList; premium.getBoostsList#60f67660 flags:# gifts:flags.0?true peer:InputPeer offset:string limit:int = premium.BoostsList;
premium.getMyBoosts#be77b4a = premium.MyBoosts; premium.getMyBoosts#be77b4a = premium.MyBoosts;

View file

@ -974,6 +974,7 @@ storyMentionButtonSkip: 5px;
chatGiveawayWidth: 292px; chatGiveawayWidth: 292px;
chatGiveawayStickerTop: -16px; chatGiveawayStickerTop: -16px;
chatGiveawayWinnersTopSkip: 25px;
chatGiveawayBadgeFont: font(12px bold); chatGiveawayBadgeFont: font(12px bold);
chatGiveawayBadgeTop: 106px; chatGiveawayBadgeTop: 106px;
chatGiveawayBadgePadding: margins(7px, 1px, 5px, 3px); chatGiveawayBadgePadding: margins(7px, 1px, 5px, 3px);