Update API scheme to layer 220.
Allow offering to buy gifts.
This commit is contained in:
@@ -2348,6 +2348,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_action_gift_premium_about" = "Subscription for exclusive Telegram features.";
|
||||
"lng_action_gift_refunded" = "This gift was downgraded because a request to refund the payment related to this gift was made, and the money was returned.";
|
||||
"lng_action_gift_got_ton" = "Use TON to suggest posts to channels.";
|
||||
"lng_action_gift_offer" = "{user} offered you {cost} for {name}.";
|
||||
"lng_action_gift_offer_you" = "You offered {cost} for {name}.";
|
||||
"lng_action_gift_offer_state_expires" = "This offer expires in {time}.";
|
||||
"lng_action_gift_offer_state_accepted" = "This offer was accepted.";
|
||||
"lng_action_gift_offer_state_rejected" = "This offer was rejected.";
|
||||
"lng_action_gift_offer_state_expired" = "This offer has expired.";
|
||||
"lng_action_gift_offer_sold" = "{user} sold {name} for {cost}.";
|
||||
"lng_action_gift_offer_sold_you" = "You sold {name} for {cost}.";
|
||||
"lng_action_gift_offer_decline" = "Reject";
|
||||
"lng_action_gift_offer_accept" = "Accept";
|
||||
"lng_action_gift_offer_expired" = "The offer from {user} to buy your {name} for {cost} has expired.";
|
||||
"lng_action_gift_offer_expired_you" = "Your offer to buy {name} for {cost} has expired.";
|
||||
"lng_action_gift_offer_declined" = "{user} rejected your offer to buy {name} for {cost}.";
|
||||
"lng_action_gift_offer_declined_you" = "You rejected {user}'s offer to buy your {name} for {cost}.";
|
||||
"lng_action_suggested_photo_me" = "You suggested this photo for {user}'s Telegram profile.";
|
||||
"lng_action_suggested_photo" = "{user} suggests this photo for your Telegram profile.";
|
||||
"lng_action_suggested_photo_button" = "View Photo";
|
||||
@@ -3936,6 +3950,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_gift_transfer_unlist" = "Unlist";
|
||||
"lng_gift_transfer_locked_title" = "Action Locked";
|
||||
"lng_gift_transfer_locked_text" = "Transfer this gift to your Telegram account on Fragment to unlock this action.";
|
||||
"lng_gift_offer_button" = "Offer to Buy";
|
||||
"lng_gift_offer_title" = "Offer to Buy";
|
||||
"lng_gift_offer_stars_about" = "Choose how many Stars you'd like to offer for {name}.";
|
||||
"lng_gift_offer_ton_about" = "Choose how many TON you'd like to offer for {name}.";
|
||||
"lng_gift_offer_duration" = "Offer Duration";
|
||||
"lng_gift_offer_duration_about" = "Choose how long {user} can accept your offer. When the time expires, the amount will be refunded.";
|
||||
"lng_gift_offer_cost_button" = "Offer {cost}";
|
||||
"lng_gift_sell_unlist_title" = "Unlist {name}";
|
||||
"lng_gift_sell_unlist_sure" = "Are you sure you want to unlist your gift?";
|
||||
"lng_gift_sell_title" = "Price in Stars";
|
||||
|
||||
@@ -930,6 +930,7 @@ std::optional<Data::StarGift> FromTL(
|
||||
.themeUser = themeUser,
|
||||
.nanoTonForResale = FindTonForResale(data.vresell_amount()),
|
||||
.starsForResale = FindStarsForResale(data.vresell_amount()),
|
||||
.starsMinOffer = data.voffer_min_stars().value_or(-1),
|
||||
.number = data.vnum().v,
|
||||
.onlyAcceptTon = data.is_resale_ton_only(),
|
||||
.canBeTheme = data.is_theme_available(),
|
||||
|
||||
@@ -3560,6 +3560,63 @@ void ShowUniqueGiftSellBox(
|
||||
});
|
||||
}
|
||||
|
||||
void SendOfferBuyGift(
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
std::shared_ptr<Data::UniqueGift> unique,
|
||||
SuggestPostOptions options,
|
||||
Fn<void()> done) {
|
||||
const auto randomId = base::RandomValue<uint64>();
|
||||
const auto owner = show->session().data().peer(unique->ownerId);
|
||||
|
||||
using Flag = MTPpayments_SendStarGiftOffer::Flag;
|
||||
show->session().api().request(MTPpayments_SendStarGiftOffer(
|
||||
MTP_flags(Flag() | Flag()),//Flag::f_allow_paid_stars)
|
||||
owner->input,
|
||||
MTP_string(unique->slug),
|
||||
StarsAmountToTL(options.price()),
|
||||
MTP_int(options.offerDuration),
|
||||
MTP_long(randomId),
|
||||
MTP_long(0) // allow_paid_stars
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
show->session().api().applyUpdates(result);
|
||||
done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
if (error.type() == u""_q) {
|
||||
|
||||
} else {
|
||||
show->showToast(error.type());
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ShowOfferBuyBox(
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
std::shared_ptr<Data::UniqueGift> unique) {
|
||||
Expects(unique->starsMinOffer >= 0);
|
||||
|
||||
const auto weak = std::make_shared<base::weak_qptr<Ui::BoxContent>>();
|
||||
const auto done = [=](SuggestPostOptions result) {
|
||||
SendOfferBuyGift(show, unique, result, [=] {
|
||||
if (const auto strong = weak->get()) {
|
||||
strong->closeBox();
|
||||
}
|
||||
});
|
||||
};
|
||||
using namespace HistoryView;
|
||||
const auto options = SuggestPostOptions{
|
||||
.exists = 1,
|
||||
.priceWhole = uint32(unique->starsMinOffer),
|
||||
};
|
||||
auto priceBox = Box(ChooseSuggestPriceBox, SuggestPriceBoxArgs{
|
||||
.peer = show->session().data().peer(unique->ownerId),
|
||||
.done = done,
|
||||
.value = options,
|
||||
.mode = SuggestMode::Gift,
|
||||
});
|
||||
*weak = priceBox.data();
|
||||
show->show(std::move(priceBox));
|
||||
}
|
||||
|
||||
void GiftReleasedByHandler(not_null<PeerData*> peer) {
|
||||
const auto session = &peer->session();
|
||||
const auto window = session->tryResolveWindow(peer);
|
||||
|
||||
@@ -95,6 +95,10 @@ void ShowUniqueGiftSellBox(
|
||||
Data::SavedStarGiftId savedId,
|
||||
Settings::GiftWearBoxStyleOverride st);
|
||||
|
||||
void ShowOfferBuyBox(
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
std::shared_ptr<Data::UniqueGift> unique);
|
||||
|
||||
void GiftReleasedByHandler(not_null<PeerData*> peer);
|
||||
|
||||
struct StarGiftUpgradeArgs {
|
||||
|
||||
@@ -213,6 +213,7 @@ struct SuggestPostOptions {
|
||||
uint32 priceNano : 31 = 0;
|
||||
uint32 ton : 1 = 0;
|
||||
TimeId date = 0;
|
||||
TimeId offerDuration = 0;
|
||||
|
||||
[[nodiscard]] CreditsAmount price() const {
|
||||
return CreditsAmount(
|
||||
|
||||
@@ -76,6 +76,7 @@ struct UniqueGift {
|
||||
int64 nanoTonForResale = -1;
|
||||
int starsForResale = -1;
|
||||
int starsForTransfer = -1;
|
||||
int starsMinOffer = -1;
|
||||
int number = 0;
|
||||
bool onlyAcceptTon = false;
|
||||
bool canBeTheme = false;
|
||||
|
||||
@@ -905,6 +905,20 @@ UserpicsSlice ParseUserpicsSlice(
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] ActionStarGift ParseStarGift(const MTPStarGift &gift) {
|
||||
return gift.match([&](const MTPDstarGift &gift) {
|
||||
return ActionStarGift{
|
||||
.giftId = uint64(gift.vid().v),
|
||||
.stars = int64(gift.vstars().v),
|
||||
.limited = gift.is_limited(),
|
||||
};
|
||||
}, [&](const MTPDstarGiftUnique &gift) {
|
||||
return ActionStarGift{
|
||||
.giftId = uint64(gift.vid().v),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
File &Story::file() {
|
||||
return media.file();
|
||||
}
|
||||
@@ -1744,41 +1758,16 @@ ServiceAction ParseServiceAction(
|
||||
.isUnclaimed = data.is_unclaimed(),
|
||||
};
|
||||
}, [&](const MTPDmessageActionStarGift &data) {
|
||||
data.vgift().match([&](const MTPDstarGift &gift) {
|
||||
result.content = ActionStarGift{
|
||||
.giftId = uint64(gift.vid().v),
|
||||
.stars = int64(gift.vstars().v),
|
||||
.text = (data.vmessage()
|
||||
? ParseText(
|
||||
data.vmessage()->data().vtext(),
|
||||
data.vmessage()->data().ventities().v)
|
||||
: std::vector<TextPart>()),
|
||||
.anonymous = data.is_name_hidden(),
|
||||
.limited = gift.is_limited(),
|
||||
};
|
||||
}, [&](const MTPDstarGiftUnique &gift) {
|
||||
result.content = ActionStarGift{
|
||||
.giftId = uint64(gift.vid().v),
|
||||
.text = (data.vmessage()
|
||||
? ParseText(
|
||||
data.vmessage()->data().vtext(),
|
||||
data.vmessage()->data().ventities().v)
|
||||
: std::vector<TextPart>()),
|
||||
.anonymous = data.is_name_hidden(),
|
||||
};
|
||||
});
|
||||
auto content = ParseStarGift(data.vgift());
|
||||
content.text = (data.vmessage()
|
||||
? ParseText(
|
||||
data.vmessage()->data().vtext(),
|
||||
data.vmessage()->data().ventities().v)
|
||||
: std::vector<TextPart>());
|
||||
content.anonymous = data.is_name_hidden();
|
||||
result.content = content;
|
||||
}, [&](const MTPDmessageActionStarGiftUnique &data) {
|
||||
data.vgift().match([&](const MTPDstarGift &gift) {
|
||||
result.content = ActionStarGift{
|
||||
.giftId = uint64(gift.vid().v),
|
||||
.stars = int64(gift.vstars().v),
|
||||
.limited = gift.is_limited(),
|
||||
};
|
||||
}, [&](const MTPDstarGiftUnique &gift) {
|
||||
result.content = ActionStarGift{
|
||||
.giftId = uint64(gift.vid().v),
|
||||
};
|
||||
});
|
||||
result.content = ParseStarGift(data.vgift());
|
||||
}, [&](const MTPDmessageActionPaidMessagesRefunded &data) {
|
||||
result.content = ActionPaidMessagesRefunded{
|
||||
.messages = data.vcount().v,
|
||||
@@ -1844,6 +1833,21 @@ ServiceAction ParseServiceAction(
|
||||
fields.vmonth().v,
|
||||
fields.vyear().value_or_empty());
|
||||
result.content = content;
|
||||
}, [&](const MTPDmessageActionStarGiftPurchaseOffer &data) {
|
||||
auto content = ParseStarGift(data.vgift());
|
||||
content.offer = true;
|
||||
content.offerPrice = CreditsAmountFromTL(data.vprice());
|
||||
content.offerExpireAt = data.vexpires_at().v;
|
||||
content.offerAccepted = data.is_accepted();
|
||||
content.offerDeclined = data.is_declined();
|
||||
result.content = content;
|
||||
}, [&](const MTPDmessageActionStarGiftPurchaseOfferDeclined &data) {
|
||||
auto content = ParseStarGift(data.vgift());
|
||||
content.offer = true;
|
||||
content.offerDeclined = true;
|
||||
content.offerExpired = data.is_expired();
|
||||
content.offerPrice = CreditsAmountFromTL(data.vprice());
|
||||
result.content = content;
|
||||
}, [](const MTPDmessageActionEmpty &data) {});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -690,6 +690,13 @@ struct ActionStarGift {
|
||||
std::vector<TextPart> text;
|
||||
bool anonymous = false;
|
||||
bool limited = false;
|
||||
|
||||
CreditsAmount offerPrice;
|
||||
TimeId offerExpireAt = 0;
|
||||
bool offer = false;
|
||||
bool offerAccepted = false;
|
||||
bool offerDeclined = false;
|
||||
bool offerExpired = false;
|
||||
};
|
||||
|
||||
struct ActionPaidMessagesRefunded {
|
||||
|
||||
@@ -6393,7 +6393,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
||||
Unexpected("PhoneCall type in setServiceMessageFromMtp.");
|
||||
};
|
||||
|
||||
auto prepareSuggestBirthday = [this](const MTPDmessageActionSuggestBirthday &action) {
|
||||
auto prepareSuggestBirthday = [&](const MTPDmessageActionSuggestBirthday &action) {
|
||||
auto result = PreparedServiceText{};
|
||||
const auto isSelf = (_from->id == _from->session().userPeerId());
|
||||
const auto peer = isSelf ? history()->peer : _from;
|
||||
@@ -6412,6 +6412,16 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
||||
return result;
|
||||
};
|
||||
|
||||
auto prepareStarGiftPurchaseOffer = [&](const MTPDmessageActionStarGiftPurchaseOffer &action) {
|
||||
auto result = PreparedServiceText{};
|
||||
return result;
|
||||
};
|
||||
|
||||
auto prepareStarGiftPurchaseOfferDeclined = [&](const MTPDmessageActionStarGiftPurchaseOfferDeclined &action) {
|
||||
auto result = PreparedServiceText{};
|
||||
return result;
|
||||
};
|
||||
|
||||
setServiceText(action.match(
|
||||
prepareChatAddUserText,
|
||||
prepareChatJoinedByLink,
|
||||
@@ -6469,6 +6479,8 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
||||
prepareSuggestedPostSuccess,
|
||||
prepareSuggestedPostRefund,
|
||||
prepareSuggestBirthday,
|
||||
prepareStarGiftPurchaseOffer,
|
||||
prepareStarGiftPurchaseOfferDeclined,
|
||||
PrepareEmptyText<MTPDmessageActionRequestedPeerSentMe>,
|
||||
PrepareErrorText<MTPDmessageActionEmpty>));
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/boxes/choose_date_time.h"
|
||||
#include "ui/boxes/single_choice_box.h"
|
||||
#include "ui/controls/ton_common.h"
|
||||
#include "ui/widgets/fields/number_input.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
@@ -401,6 +402,7 @@ void ChooseSuggestPriceBox(
|
||||
rpl::event_stream<> fieldsChanges;
|
||||
rpl::variable<CreditsAmount> price;
|
||||
rpl::variable<TimeId> date;
|
||||
rpl::variable<TimeId> offerDuration;
|
||||
rpl::variable<bool> ton;
|
||||
Fn<std::optional<CreditsAmount>()> computePrice;
|
||||
Fn<void()> save;
|
||||
@@ -413,6 +415,7 @@ void ChooseSuggestPriceBox(
|
||||
state->price = args.value.price();
|
||||
|
||||
const auto peer = args.peer;
|
||||
const auto mode = args.mode;
|
||||
const auto admin = peer->amMonoforumAdmin();
|
||||
const auto broadcast = peer->monoforumBroadcast();
|
||||
const auto usePeer = broadcast ? broadcast : peer;
|
||||
@@ -426,7 +429,9 @@ void ChooseSuggestPriceBox(
|
||||
|
||||
box->setStyle(st::suggestPriceBox);
|
||||
|
||||
auto title = (args.mode == SuggestMode::New)
|
||||
auto title = (mode == SuggestMode::Gift)
|
||||
? tr::lng_gift_offer_title()
|
||||
: (mode == SuggestMode::New)
|
||||
? tr::lng_suggest_options_title()
|
||||
: tr::lng_suggest_options_change();
|
||||
if (admin) {
|
||||
@@ -567,17 +572,27 @@ void ChooseSuggestPriceBox(
|
||||
auto starsAbout = admin
|
||||
? rpl::combine(
|
||||
youGet(StarsPriceValue(state->price.value()), true),
|
||||
tr::lng_suggest_options_stars_warning(Ui::Text::RichLangValue)
|
||||
tr::lng_suggest_options_stars_warning(tr::rich)
|
||||
) | rpl::map([=](const QString &t1, const TextWithEntities &t2) {
|
||||
return TextWithEntities{ t1 }.append("\n\n").append(t2);
|
||||
})
|
||||
: tr::lng_suggest_options_stars_price_about(Ui::Text::WithEntities);
|
||||
: (mode == SuggestMode::Gift)
|
||||
? tr::lng_gift_offer_stars_about(
|
||||
lt_name,
|
||||
rpl::single(tr::marked(args.giftName)),
|
||||
tr::rich)
|
||||
: tr::lng_suggest_options_stars_price_about(tr::rich);
|
||||
auto tonAbout = admin
|
||||
? youGet(
|
||||
TonPriceValue(state->price.value()),
|
||||
false
|
||||
) | Ui::Text::ToWithEntities()
|
||||
: tr::lng_suggest_options_ton_price_about(Ui::Text::WithEntities);
|
||||
) | rpl::map(tr::rich)
|
||||
: (mode == SuggestMode::Gift)
|
||||
? tr::lng_gift_offer_ton_about(
|
||||
lt_name,
|
||||
rpl::single(tr::marked(args.giftName)),
|
||||
tr::rich)
|
||||
: tr::lng_suggest_options_ton_price_about(tr::rich);
|
||||
auto priceInput = AddStarsTonPriceInput(container, {
|
||||
.session = session,
|
||||
.showTon = state->ton.value(),
|
||||
@@ -595,39 +610,94 @@ void ChooseSuggestPriceBox(
|
||||
|
||||
Ui::AddSkip(container);
|
||||
|
||||
const auto time = Settings::AddButtonWithLabel(
|
||||
container,
|
||||
tr::lng_suggest_options_date(),
|
||||
state->date.value() | rpl::map([](TimeId date) {
|
||||
return date
|
||||
? langDateTime(base::unixtime::parse(date))
|
||||
: tr::lng_suggest_options_date_any(tr::now);
|
||||
}),
|
||||
st::settingsButtonNoIcon);
|
||||
|
||||
time->setClickedCallback([=] {
|
||||
const auto weak = std::make_shared<base::weak_qptr<Ui::BoxContent>>();
|
||||
const auto parentWeak = base::make_weak(box);
|
||||
const auto done = [=](TimeId result) {
|
||||
if (parentWeak) {
|
||||
state->date = result;
|
||||
}
|
||||
if (const auto strong = weak->get()) {
|
||||
strong->closeBox();
|
||||
}
|
||||
if (args.mode == SuggestMode::Gift) {
|
||||
const auto day = 86400;
|
||||
auto durations = std::vector{
|
||||
day / 4,
|
||||
day / 2,
|
||||
day,
|
||||
day + day / 2,
|
||||
day * 2,
|
||||
day * 3,
|
||||
};
|
||||
auto dateBox = Box(ChooseSuggestTimeBox, SuggestTimeBoxArgs{
|
||||
.session = session,
|
||||
.done = done,
|
||||
.value = state->date.current(),
|
||||
.mode = args.mode,
|
||||
});
|
||||
*weak = dateBox.data();
|
||||
box->uiShow()->show(std::move(dateBox));
|
||||
});
|
||||
if (peer->session().isTestMode()) {
|
||||
durations.insert(begin(durations), 120);
|
||||
}
|
||||
const auto durationToText = [](TimeId date) {
|
||||
return (date >= 3600)
|
||||
? tr::lng_hours(tr::now, lt_count, date / 3600)
|
||||
: tr::lng_minutes(tr::now, lt_count, date / 60);
|
||||
};
|
||||
state->offerDuration = day;
|
||||
const auto duration = Settings::AddButtonWithLabel(
|
||||
container,
|
||||
tr::lng_gift_offer_duration(),
|
||||
state->offerDuration.value() | rpl::map(durationToText),
|
||||
st::settingsButtonNoIcon);
|
||||
|
||||
Ui::AddSkip(container);
|
||||
Ui::AddDividerText(container, tr::lng_suggest_options_date_about());
|
||||
duration->setClickedCallback([=] {
|
||||
box->uiShow()->show(Box([=](not_null<Ui::GenericBox*> box) {
|
||||
const auto save = [=](int index) {
|
||||
state->offerDuration = durations[index];
|
||||
};
|
||||
auto options = durations
|
||||
| ranges::views::transform(durationToText)
|
||||
| ranges::to_vector;
|
||||
const auto selected = ranges::find(
|
||||
durations,
|
||||
state->offerDuration.current());
|
||||
SingleChoiceBox(box, {
|
||||
.title = tr::lng_settings_angle_backend(),
|
||||
.options = options,
|
||||
.initialSelection = int(selected - begin(durations)),
|
||||
.callback = save,
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
Ui::AddSkip(container);
|
||||
Ui::AddDividerText(
|
||||
container,
|
||||
tr::lng_gift_offer_duration_about(
|
||||
lt_user,
|
||||
rpl::single(peer->shortName())));
|
||||
} else {
|
||||
const auto time = Settings::AddButtonWithLabel(
|
||||
container,
|
||||
tr::lng_suggest_options_date(),
|
||||
state->date.value() | rpl::map([](TimeId date) {
|
||||
return date
|
||||
? langDateTime(base::unixtime::parse(date))
|
||||
: tr::lng_suggest_options_date_any(tr::now);
|
||||
}),
|
||||
st::settingsButtonNoIcon);
|
||||
|
||||
time->setClickedCallback([=] {
|
||||
const auto weak = std::make_shared<
|
||||
base::weak_qptr<Ui::BoxContent>
|
||||
>();
|
||||
const auto parentWeak = base::make_weak(box);
|
||||
const auto done = [=](TimeId result) {
|
||||
if (parentWeak) {
|
||||
state->date = result;
|
||||
}
|
||||
if (const auto strong = weak->get()) {
|
||||
strong->closeBox();
|
||||
}
|
||||
};
|
||||
auto dateBox = Box(ChooseSuggestTimeBox, SuggestTimeBoxArgs{
|
||||
.session = session,
|
||||
.done = done,
|
||||
.value = state->date.current(),
|
||||
.mode = args.mode,
|
||||
});
|
||||
*weak = dateBox.data();
|
||||
box->uiShow()->show(std::move(dateBox));
|
||||
});
|
||||
|
||||
Ui::AddSkip(container);
|
||||
Ui::AddDividerText(container, tr::lng_suggest_options_date_about());
|
||||
}
|
||||
|
||||
state->save = [=] {
|
||||
const auto ton = uint32(state->ton.current() ? 1 : 0);
|
||||
@@ -674,6 +744,7 @@ void ChooseSuggestPriceBox(
|
||||
.priceNano = uint32(value.nano()),
|
||||
.ton = ton,
|
||||
.date = state->date.current(),
|
||||
.offerDuration = state->offerDuration.current(),
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ enum class SuggestMode {
|
||||
New,
|
||||
Change,
|
||||
Publish,
|
||||
Gift,
|
||||
};
|
||||
|
||||
struct SuggestTimeBoxArgs {
|
||||
@@ -91,6 +92,7 @@ struct SuggestPriceBoxArgs {
|
||||
Fn<void(SuggestPostOptions)> done;
|
||||
SuggestPostOptions value;
|
||||
SuggestMode mode = SuggestMode::New;
|
||||
QString giftName;
|
||||
};
|
||||
void ChooseSuggestPriceBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
|
||||
@@ -235,6 +235,7 @@ darkGiftHide: icon {{ "menu/stealth", groupCallMembersFg }};
|
||||
darkGiftShow: icon {{ "menu/show_in_chat", groupCallMembersFg }};
|
||||
darkGiftPin: icon {{ "menu/pin", groupCallMembersFg }};
|
||||
darkGiftUnpin: icon {{ "menu/unpin", groupCallMembersFg }};
|
||||
darkGiftOffer: icon {{ "menu/earn", groupCallMembersFg }};
|
||||
darkGiftPalette: TextPalette(defaultTextPalette) {
|
||||
linkFg: mediaviewTextLinkFg;
|
||||
monoFg: groupCallMembersFg;
|
||||
|
||||
@@ -187,7 +187,7 @@ messageActionPaymentRefunded#41b3e202 flags:# peer:Peer currency:string total_am
|
||||
messageActionGiftStars#45d5b021 flags:# currency:string amount:long stars:long crypto_currency:flags.0?string crypto_amount:flags.0?long transaction_id:flags.1?string = MessageAction;
|
||||
messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long transaction_id:string boost_peer:Peer giveaway_msg_id:int = MessageAction;
|
||||
messageActionStarGift#db596550 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true prepaid_upgrade:flags.13?true upgrade_separate:flags.16?true auction_acquired:flags.17?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long prepaid_upgrade_hash:flags.14?string gift_msg_id:flags.15?int to_id:flags.18?Peer = MessageAction;
|
||||
messageActionStarGiftUnique#95728543 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true prepaid_upgrade:flags.11?true assigned:flags.13?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long resale_amount:flags.8?StarsAmount can_transfer_at:flags.9?int can_resell_at:flags.10?int drop_original_details_stars:flags.12?long = MessageAction;
|
||||
messageActionStarGiftUnique#95728543 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true prepaid_upgrade:flags.11?true assigned:flags.13?true from_offer:flags.14?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long resale_amount:flags.8?StarsAmount can_transfer_at:flags.9?int can_resell_at:flags.10?int drop_original_details_stars:flags.12?long = MessageAction;
|
||||
messageActionPaidMessagesRefunded#ac1f1fcd count:int stars:long = MessageAction;
|
||||
messageActionPaidMessagesPrice#84b88578 flags:# broadcast_messages_allowed:flags.0?true stars:long = MessageAction;
|
||||
messageActionConferenceCall#2ffe2f7a flags:# missed:flags.0?true active:flags.1?true video:flags.4?true call_id:long duration:flags.2?int other_participants:flags.3?Vector<Peer> = MessageAction;
|
||||
@@ -198,6 +198,8 @@ messageActionSuggestedPostSuccess#95ddcf69 price:StarsAmount = MessageAction;
|
||||
messageActionSuggestedPostRefund#69f916f8 flags:# payer_initiated:flags.0?true = MessageAction;
|
||||
messageActionGiftTon#a8a3c699 flags:# currency:string amount:long crypto_currency:string crypto_amount:long transaction_id:flags.0?string = MessageAction;
|
||||
messageActionSuggestBirthday#2c8f2a25 birthday:Birthday = MessageAction;
|
||||
messageActionStarGiftPurchaseOffer#774278d4 flags:# accepted:flags.0?true declined:flags.1?true gift:StarGift price:StarsAmount expires_at:int = MessageAction;
|
||||
messageActionStarGiftPurchaseOfferDeclined#73ada76b flags:# expired:flags.0?true gift:StarGift price:StarsAmount = MessageAction;
|
||||
|
||||
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?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;
|
||||
@@ -1915,7 +1917,7 @@ starsGiveawayOption#94ce852a flags:# extended:flags.0?true default:flags.1?true
|
||||
starsGiveawayWinnersOption#54236209 flags:# default:flags.0?true users:int per_user_stars:long = StarsGiveawayWinnersOption;
|
||||
|
||||
starGift#1b9a4d7f flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true require_premium:flags.7?true limited_per_user:flags.8?true peer_color_available:flags.10?true auction:flags.11?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int availability_resale:flags.4?long convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long resell_min_stars:flags.4?long title:flags.5?string released_by:flags.6?Peer per_user_total:flags.8?int per_user_remains:flags.8?int locked_until_date:flags.9?int auction_slug:flags.11?string gifts_per_round:flags.11?int = StarGift;
|
||||
starGiftUnique#b0bf741b flags:# require_premium:flags.6?true resale_ton_only:flags.7?true theme_available:flags.9?true id:long gift_id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int gift_address:flags.3?string resell_amount:flags.4?Vector<StarsAmount> released_by:flags.5?Peer value_amount:flags.8?long value_currency:flags.8?string theme_peer:flags.10?Peer peer_color:flags.11?PeerColor host_id:flags.12?Peer = StarGift;
|
||||
starGiftUnique#9f2fb096 flags:# require_premium:flags.6?true resale_ton_only:flags.7?true theme_available:flags.9?true id:long gift_id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int gift_address:flags.3?string resell_amount:flags.4?Vector<StarsAmount> released_by:flags.5?Peer value_amount:flags.8?long value_currency:flags.8?string theme_peer:flags.10?Peer peer_color:flags.11?PeerColor host_id:flags.12?Peer offer_min_stars:flags.13?int = StarGift;
|
||||
|
||||
payments.starGiftsNotModified#a388a368 = payments.StarGifts;
|
||||
payments.starGifts#2ed82995 hash:int gifts:Vector<StarGift> chats:Vector<Chat> users:Vector<User> = payments.StarGifts;
|
||||
@@ -2732,6 +2734,8 @@ payments.checkCanSendGift#c0c4edc9 gift_id:long = payments.CheckCanSendGiftResul
|
||||
payments.getStarGiftAuctionState#5c9ff4d6 auction:InputStarGiftAuction version:int = payments.StarGiftAuctionState;
|
||||
payments.getStarGiftAuctionAcquiredGifts#6ba2cbec gift_id:long = payments.StarGiftAuctionAcquiredGifts;
|
||||
payments.getStarGiftActiveAuctions#a5d0514d hash:long = payments.StarGiftActiveAuctions;
|
||||
payments.resolveStarGiftOffer#e9ce781c flags:# decline:flags.0?true offer_msg_id:int = Updates;
|
||||
payments.sendStarGiftOffer#8fb86b41 flags:# peer:InputPeer slug:string price:StarsAmount duration:int random_id:long allow_paid_stars:flags.0?long = Updates;
|
||||
|
||||
stickers.createStickerSet#9021ab67 flags:# masks:flags.0?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;
|
||||
@@ -2867,4 +2871,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool;
|
||||
|
||||
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;
|
||||
|
||||
// LAYER 219
|
||||
// LAYER 220
|
||||
|
||||
@@ -964,6 +964,21 @@ void ProcessReceivedSubscriptions(
|
||||
// (owner->isChannel() && owner->asChannel()->canTransferGifts());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool ShowOfferBuyButton(
|
||||
not_null<Main::Session*> session,
|
||||
const Data::CreditsHistoryEntry &e) {
|
||||
const auto unique = e.uniqueGift.get();
|
||||
const auto owner = (unique && unique->ownerId)
|
||||
? session->data().peer(unique->ownerId).get()
|
||||
: nullptr;
|
||||
return owner
|
||||
&& owner->isUser()
|
||||
&& !owner->isSelf()
|
||||
&& (unique->starsMinOffer >= 0);
|
||||
// Currently we're not making offers for channel gifts.
|
||||
// (owner->isChannel() && !owner->asChannel()->canTransferGifts());
|
||||
}
|
||||
|
||||
void FillUniqueGiftMenu(
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
@@ -1158,6 +1173,10 @@ void FillUniqueGiftMenu(
|
||||
}));
|
||||
}, st.unlist ? st.unlist : &st::menuIconTagRemove);
|
||||
}
|
||||
} else if (ShowOfferBuyButton(&show->session(), e)) {
|
||||
menu->addAction(tr::lng_gift_offer_button(tr::now), [=] {
|
||||
ShowOfferBuyBox(show, unique);
|
||||
}, st.offer ? st.offer : &st::menuIconEarn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1193,6 +1212,7 @@ CreditsEntryBoxStyleOverrides DarkCreditsEntryBoxStyle() {
|
||||
.hide = &st::darkGiftHide,
|
||||
.pin = &st::darkGiftPin,
|
||||
.unpin = &st::darkGiftUnpin,
|
||||
.offer = &st::darkGiftOffer,
|
||||
.shareBox = std::make_shared<ShareBoxStyleOverrides>(
|
||||
DarkShareBoxStyle()),
|
||||
.giftWearBox = std::make_shared<GiftWearBoxStyleOverride>(
|
||||
|
||||
@@ -127,6 +127,7 @@ struct CreditsEntryBoxStyleOverrides {
|
||||
const style::icon *hide = nullptr;
|
||||
const style::icon *pin = nullptr;
|
||||
const style::icon *unpin = nullptr;
|
||||
const style::icon *offer = nullptr;
|
||||
std::shared_ptr<ShareBoxStyleOverrides> shareBox;
|
||||
std::shared_ptr<GiftWearBoxStyleOverride> giftWearBox;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user