Allow removing unique gift details.

This commit is contained in:
John Preston
2025-09-11 21:59:56 +04:00
parent 46f64f75c7
commit 09175d2b6b
11 changed files with 226 additions and 49 deletions
+4
View File
@@ -3694,6 +3694,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_unique_info_sender_comment" = "Gifted by {from} to {recipient} on {date} with the comment \"{text}\".";
"lng_gift_unique_info_reciever" = "Gifted to {recipient} on {date}.";
"lng_gift_unique_info_reciever_comment" = "Gifted to {recipient} on {date} with the comment \"{text}\".";
"lng_gift_unique_info_remove_title" = "Remove Description";
"lng_gift_unique_info_remove_text" = "Do you want to permanently remove this description from your gift?";
"lng_gift_unique_info_remove_confirm" = "Remove for {cost}";
"lng_gift_unique_info_removed" = "Removed {name}'s Description!";
"lng_gift_availability_left#one" = "{count} of {amount} left";
"lng_gift_availability_left#other" = "{count} of {amount} left";
"lng_gift_availability_none" = "None of {amount} left";
+2
View File
@@ -986,6 +986,8 @@ std::optional<Data::SavedStarGift> FromTL(
.starsConverted = int64(data.vconvert_stars().value_or_empty()),
.starsUpgradedBySender = int64(
data.vupgrade_stars().value_or_empty()),
.starsForDetailsRemove = int64(
data.vdrop_original_details_stars().value_or_empty()),
.giftPrepayUpgradeHash = qs(
data.vprepaid_upgrade_hash().value_or_empty()),
.fromId = (data.vfrom_id()
+149 -47
View File
@@ -45,6 +45,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_premium.h"
#include "ui/basic_click_handlers.h" // UrlClickHandler::Open.
#include "ui/boxes/boost_box.h" // StartFireworks.
#include "ui/boxes/confirm_box.h"
#include "ui/controls/userpic_button.h"
#include "ui/effects/credits_graphics.h"
#include "ui/effects/premium_graphics.h"
@@ -1433,13 +1434,108 @@ QString TonAddressUrl(
return prefix + address;
}
struct AddedUniqueDetails {
object_ptr<Ui::RpWidget> widget;
not_null<Ui::FlatLabel*> label;
};
[[nodiscard]] AddedUniqueDetails MakeUniqueDetails(
std::shared_ptr<ChatHelpers::Show> show,
not_null<QWidget*> parent,
rpl::producer<TextWithEntities> text,
Settings::CreditsEntryBoxStyleOverrides st,
Ui::Text::MarkedContext context,
int removeCost,
Fn<void(Fn<void()> removed)> remove) {
auto owned = object_ptr<Ui::FlatLabel>(
parent,
rpl::duplicate(text),
(st.tableValueMessage
? *st.tableValueMessage
: st::giveawayGiftMessage),
st::defaultPopupMenu,
context);
const auto label = owned.data();
if (!remove) {
return {
.widget = std::move(owned),
.label = label,
};
}
owned.release();
auto result = object_ptr<Ui::RpWidget>(parent);
const auto raw = result.data();
label->setParent(raw);
label->show();
const auto icon = Ui::CreateChild<Ui::IconButton>(
raw,
st::giveawayGiftMessageRemove);
raw->widthValue() | rpl::start_with_next([=](int outer) {
label->resizeToWidth(outer - icon->width());
const auto height = std::max(label->height(), icon->height());
icon->moveToRight(0, (height - icon->height()) / 2);
label->move(0, (height - label->height()) / 2);
raw->resize(outer, height);
}, raw->lifetime());
icon->setClickedCallback([=] {
const auto weak = base::make_weak(raw);
show->show(Box([=](not_null<Ui::GenericBox*> box) {
const auto confirming = base::make_weak(box);
const auto confirmed = [=] {
remove([=] {
delete weak.get();
if (const auto strong = confirming.get()) {
strong->closeBox();
}
});
};
Ui::ConfirmBox(box, {
.text = tr::lng_gift_unique_info_remove_text(),
.confirmed = confirmed,
.confirmText = tr::lng_gift_unique_info_remove_confirm(
lt_cost,
rpl::single(
Ui::Text::IconEmoji(&st::starIconEmoji).append(
Lang::FormatCountDecimal(removeCost))),
Ui::Text::RichLangValue),
.title = tr::lng_gift_unique_info_remove_title(),
});
box->addRow(
object_ptr<Ui::TableLayout>(
box,
st.table ? *st.table : st::giveawayGiftCodeTable)
)->addRow(
object_ptr<Ui::FlatLabel>(
parent,
rpl::duplicate(text),
(st.tableValueMessage
? *st.tableValueMessage
: st::giveawayGiftMessage),
st::defaultPopupMenu,
context),
nullptr,
st::giveawayGiftCodeLabelMargin,
st::giveawayGiftCodeValueMargin);
}));
});
return {
.widget = std::move(result),
.label = label,
};
}
void AddStarGiftTable(
std::shared_ptr<ChatHelpers::Show> show,
not_null<Ui::VerticalLayout*> container,
Settings::CreditsEntryBoxStyleOverrides st,
const Data::CreditsHistoryEntry &entry,
Fn<void()> convertToStars,
Fn<void()> startUpgrade) {
Fn<void()> startUpgrade,
Fn<void(Fn<void()> removed)> removeDetails) {
const auto table = container->add(
object_ptr<Ui::TableLayout>(
container,
@@ -1467,7 +1563,10 @@ void AddStarGiftTable(
AddTableRow(
table,
tr::lng_credits_box_history_entry_peer(),
MakePeerTableValue(table, show, PeerId(entry.bareGiftResaleRecipientId)),
MakePeerTableValue(
table,
show,
PeerId(entry.bareGiftResaleRecipientId)),
st::giveawayGiftCodePeerMargin);
} else if (unique && entry.bareGiftOwnerId) {
const auto ownerId = PeerId(entry.bareGiftOwnerId);
@@ -1638,60 +1737,63 @@ void AddStarGiftTable(
: nullptr;
const auto date = base::unixtime::parse(original.date).date();
const auto dateText = TextWithEntities{ langDayOfMonth(date) };
auto label = object_ptr<Ui::FlatLabel>(
auto details = from
? (original.message.empty()
? tr::lng_gift_unique_info_sender(
lt_from,
rpl::single(Ui::Text::Link(from->name(), 2)),
lt_recipient,
rpl::single(Ui::Text::Link(to->name(), 1)),
lt_date,
rpl::single(dateText),
Ui::Text::WithEntities)
: tr::lng_gift_unique_info_sender_comment(
lt_from,
rpl::single(Ui::Text::Link(from->name(), 2)),
lt_recipient,
rpl::single(Ui::Text::Link(to->name(), 1)),
lt_date,
rpl::single(dateText),
lt_text,
rpl::single(original.message),
Ui::Text::WithEntities))
: (original.message.empty()
? tr::lng_gift_unique_info_reciever(
lt_recipient,
rpl::single(Ui::Text::Link(to->name(), 1)),
lt_date,
rpl::single(dateText),
Ui::Text::WithEntities)
: tr::lng_gift_unique_info_reciever_comment(
lt_recipient,
rpl::single(Ui::Text::Link(to->name(), 1)),
lt_date,
rpl::single(dateText),
lt_text,
rpl::single(original.message),
Ui::Text::WithEntities));
const auto tmp = std::make_shared<Ui::RpWidget*>(nullptr);
auto made = MakeUniqueDetails(
show,
table,
(from
? (original.message.empty()
? tr::lng_gift_unique_info_sender(
lt_from,
rpl::single(Ui::Text::Link(from->name(), 2)),
lt_recipient,
rpl::single(Ui::Text::Link(to->name(), 1)),
lt_date,
rpl::single(dateText),
Ui::Text::WithEntities)
: tr::lng_gift_unique_info_sender_comment(
lt_from,
rpl::single(Ui::Text::Link(from->name(), 2)),
lt_recipient,
rpl::single(Ui::Text::Link(to->name(), 1)),
lt_date,
rpl::single(dateText),
lt_text,
rpl::single(original.message),
Ui::Text::WithEntities))
: (original.message.empty()
? tr::lng_gift_unique_info_reciever(
lt_recipient,
rpl::single(Ui::Text::Link(to->name(), 1)),
lt_date,
rpl::single(dateText),
Ui::Text::WithEntities)
: tr::lng_gift_unique_info_reciever_comment(
lt_recipient,
rpl::single(Ui::Text::Link(to->name(), 1)),
lt_date,
rpl::single(dateText),
lt_text,
rpl::single(original.message),
Ui::Text::WithEntities))),
(st.tableValueMessage
? *st.tableValueMessage
: st::giveawayGiftMessage),
st::defaultPopupMenu,
Core::TextContext({ .session = session }));
std::move(details),
st,
Core::TextContext({ .session = session }),
entry.starsForDetailsRemove,
std::move(removeDetails));
const auto showBoxLink = [=](not_null<PeerData*> peer) {
return std::make_shared<LambdaClickHandler>([=] {
show->showBox(PrepareShortInfoBox(peer, show));
});
};
label->setLink(1, showBoxLink(to));
made.label->setLink(1, showBoxLink(to));
if (from) {
label->setLink(2, showBoxLink(from));
made.label->setLink(2, showBoxLink(from));
}
label->setSelectable(true);
made.label->setSelectable(true);
*tmp = made.widget.data();
table->addRow(
std::move(label),
std::move(made.widget),
nullptr,
st::giveawayGiftCodeLabelMargin,
st::giveawayGiftCodeValueMargin);
@@ -78,7 +78,8 @@ void AddStarGiftTable(
Settings::CreditsEntryBoxStyleOverrides st,
const Data::CreditsHistoryEntry &entry,
Fn<void()> convertToStars,
Fn<void()> startUpgrade);
Fn<void()> startUpgrade,
Fn<void(Fn<void()> removed)> removeDetails);
void AddTransferGiftTable(
std::shared_ptr<ChatHelpers::Show> show,
not_null<Ui::VerticalLayout*> container,
@@ -5672,6 +5672,28 @@ void RequestOurForm(
} else {
fail(Payments::CheckoutResult::Failed);
}
}, [&](const MTPDpayments_paymentFormStars &data) {
show->session().data().processUsers(data.vusers());
const auto currency = qs(data.vinvoice().data().vcurrency());
const auto &prices = data.vinvoice().data().vprices().v;
if (!prices.empty()) {
const auto price = prices.front().data().vamount().v;
const auto amount = (currency == Ui::kCreditsCurrency)
? CreditsAmount(price)
: (currency == u"TON"_q)
? CreditsAmount(
price / Ui::kNanosInOne,
price % Ui::kNanosInOne,
CreditsType::Ton)
: std::optional<CreditsAmount>();
if (amount) {
done(data.vform_id().v, *amount, std::nullopt);
} else {
fail(Payments::CheckoutResult::Failed);
}
} else {
fail(Payments::CheckoutResult::Failed);
}
}, [&](const auto &) {
fail(Payments::CheckoutResult::Failed);
});
+1
View File
@@ -97,6 +97,7 @@ struct CreditsHistoryEntry final {
int starsConverted = 0;
int starsToUpgrade = 0;
int starsUpgradedBySender = 0;
int starsForDetailsRemove = 0;
int premiumMonthsForStars = 0;
int floodSkip = 0;
bool converted : 1 = false;
@@ -157,6 +157,7 @@ struct GiftCode {
int starsConverted = 0;
int starsToUpgrade = 0;
int starsUpgradedBySender = 0;
int starsForDetailsRemove = 0;
int limitedCount = 0;
int limitedLeft = 0;
int64 count = 0;
@@ -175,6 +175,7 @@ struct SavedStarGift {
TextWithEntities message;
int64 starsConverted = 0;
int64 starsUpgradedBySender = 0;
int64 starsForDetailsRemove = 0;
QString giftPrepayUpgradeHash;
PeerId fromId = 0;
TimeId date = 0;
@@ -6578,6 +6578,8 @@ void HistoryItem::applyAction(const MTPMessageAction &action) {
? history()->owner().peer(from).get()
: nullptr),
.channelSavedId = data.vsaved_id().value_or_empty(),
.starsForDetailsRemove = int(
data.vdrop_original_details_stars().value_or_empty()),
.type = Data::GiftType::StarGift,
.transferred = data.is_transferred(),
.refunded = data.is_refunded(),
@@ -91,6 +91,17 @@ giveawayGiftMessage: FlatLabel(defaultTableValue) {
minWidth: 128px;
maxHeight: 0px;
}
giveawayGiftMessageRemove: IconButton(defaultIconButton) {
width: 32px;
height: 32px;
icon: icon{{ "menu/delete", windowActiveTextFg }};
iconOver: icon{{ "menu/delete", windowActiveTextFg }};
rippleAreaPosition: point(0px, 0px);
rippleAreaSize: 32px;
ripple: RippleAnimation(defaultRippleAnimation) {
color: lightButtonBgRipple;
}
}
giveawayGiftCodeValueMargin: margins(13px, 9px, 13px, 9px);
giveawayGiftCodePeerMargin: margins(11px, 6px, 11px, 4px);
giveawayGiftCodeUserpic: UserpicButton(defaultUserpicButton) {
@@ -1848,6 +1848,8 @@ void GenericCreditsEntryBox(
const auto canGiftUpgrade = !e.uniqueGift
&& !e.in
&& !e.giftPrepayUpgradeHash.isEmpty();
const auto canRemoveDetails = e.uniqueGift
&& (e.starsForDetailsRemove > 0);
const auto upgradeGuard = std::make_shared<bool>();
const auto upgrade = [=] {
const auto window = show->resolveWindow();
@@ -1879,6 +1881,31 @@ void GenericCreditsEntryBox(
&& !e.anonymous)),
});
};
const auto removeDetails = [=](Fn<void()> removed) {
const auto session = &show->session();
const auto unique = e.uniqueGift;
const auto savedId = EntryToSavedStarGiftId(session, e);
auto done = [=](
Payments::CheckoutResult result,
const MTPUpdates *updates) {
if (result == Payments::CheckoutResult::Paid) {
removed();
const auto name = Data::UniqueGiftName(*unique);
show->showToast(tr::lng_gift_unique_info_removed(
tr::now,
lt_name,
Ui::Text::Bold(name),
Ui::Text::WithEntities));
unique->originalDetails = Data::UniqueGiftOriginalDetails();
}
};
RequestStarsFormAndSubmit(
show,
MTP_inputInvoiceStarGiftDropOriginalDetails(
Api::InputSavedStarGiftId(savedId, e.uniqueGift)),
std::move(done));
};
if (isStarGift && e.id.isEmpty()) {
const auto convert = [=, weak = base::make_weak(box)] {
@@ -1933,7 +1960,8 @@ void GenericCreditsEntryBox(
st,
e,
canConvert ? convert : Fn<void()>(),
canUpgrade ? upgrade : Fn<void()>());
canUpgrade ? upgrade : Fn<void()>(),
canRemoveDetails ? removeDetails : Fn<void(Fn<void()>)>());
} else {
AddCreditsHistoryEntryTable(show, content, st, e);
AddSubscriptionEntryTable(show, content, st, s);
@@ -2552,6 +2580,7 @@ Data::CreditsHistoryEntry SavedStarGiftEntry(
.starsConverted = int(data.starsConverted),
.starsToUpgrade = int(data.info.starsToUpgrade),
.starsUpgradedBySender = int(data.starsUpgradedBySender),
.starsForDetailsRemove = int(data.starsForDetailsRemove),
.converted = false,
.anonymous = data.anonymous,
.stargift = true,
@@ -2655,6 +2684,7 @@ void ShowStarGiftViewBox(
.starsConverted = data.starsConverted,
.starsToUpgrade = data.starsToUpgrade,
.starsUpgradedBySender = data.starsUpgradedBySender,
.starsForDetailsRemove = data.starsForDetailsRemove,
.converted = data.converted,
.anonymous = data.anonymous,
.stargift = true,