Improve channel gifts viewing.

This commit is contained in:
John Preston 2025-01-22 22:12:50 +04:00
parent 27bba8250a
commit 80db076f38
9 changed files with 156 additions and 86 deletions

View file

@ -3298,6 +3298,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_visible_hint" = "This gift is visible on your page.";
"lng_gift_hidden_hint_channel" = "This gift is hidden from visitors of your channel.";
"lng_gift_visible_hint_channel" = "This gift is visible in your channel's Gifts.";
"lng_gift_in_blockchain" = "This gift is in TON blockchain. {link}";
"lng_gift_in_blockchain_link" = "View >";
"lng_gift_visible_hide" = "Hide >";
"lng_gift_show_on_page" = "Display on my Page";
"lng_gift_show_on_channel" = "Display in channel's Gifts";
@ -3309,6 +3311,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_channel_title" = "Send a Gift";
"lng_gift_channel_about" = "Select a gift to show appreciation for {name}.";
"lng_gift_unique_owner" = "Owner";
"lng_gift_unique_address_copied" = "Address copied to clipboard.";
"lng_gift_unique_status" = "Status";
"lng_gift_unique_status_non" = "Non-Unique";
"lng_gift_unique_status_upgrade" = "upgrade";

View file

@ -808,6 +808,7 @@ std::optional<Data::StarGift> FromTL(
.id = data.vid().v,
.slug = qs(data.vslug()),
.title = qs(data.vtitle()),
.ownerAddress = qs(data.vowner_address().value_or_empty()),
.ownerName = qs(data.vowner_name().value_or_empty()),
.ownerId = (data.vowner_id()
? peerFromMTP(*data.vowner_id())

View file

@ -34,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/profile/info_profile_badge.h"
#include "info/profile/info_profile_values.h"
#include "lang/lang_keys.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
#include "mainwidget.h"
#include "payments/payments_checkout_process.h"
@ -131,6 +132,23 @@ constexpr auto kRarityTooltipDuration = 3 * crl::time(1000);
: tr::lng_premium_gift_duration_years;
}
[[nodiscard]] object_ptr<Ui::FlatLabel> MakeMaybeMultilineTokenValue(
not_null<Ui::TableLayout*> table,
const QString &token,
Settings::CreditsEntryBoxStyleOverrides st) {
constexpr auto kOneLineCount = 24;
const auto oneLine = token.length() <= kOneLineCount;
return object_ptr<Ui::FlatLabel>(
table,
rpl::single(
Ui::Text::Wrapped({ token }, EntityType::Code, {})),
(oneLine
? table->st().defaultValue
: st.tableValueMultiline
? *st.tableValueMultiline
: st::giveawayGiftCodeValueMultiline));
}
[[nodiscard]] object_ptr<Ui::RpWidget> MakePeerTableValue(
not_null<Ui::TableLayout*> table,
std::shared_ptr<ChatHelpers::Show> show,
@ -1223,6 +1241,15 @@ void ResolveGiveawayInfo(
crl::guard(controller, show));
}
QString TonAddressUrl(
not_null<Main::Session*> session,
const QString &address) {
const auto prefix = session->appConfig().get<QString>(
u"ton_blockchain_explorer_url"_q,
u"https://tonviewer.com/"_q);
return prefix + address;
}
void AddStarGiftTable(
std::shared_ptr<ChatHelpers::Show> show,
not_null<Ui::VerticalLayout*> container,
@ -1335,10 +1362,26 @@ void AddStarGiftTable(
MakePeerWithStatusValue(table, show, ownerId, handleChange),
st::giveawayGiftCodePeerMargin);
} else if (unique) {
AddTableRow(
table,
tr::lng_gift_unique_owner(),
rpl::single(TextWithEntities{ unique->ownerName }));
if (!unique->ownerName.isEmpty()) {
AddTableRow(
table,
tr::lng_gift_unique_owner(),
rpl::single(TextWithEntities{ unique->ownerName }));
} else if (auto address = unique->ownerAddress; !address.isEmpty()) {
auto label = MakeMaybeMultilineTokenValue(table, address, st);
label->setClickHandlerFilter([=](const auto &...) {
TextUtilities::SetClipboardText(
TextForMimeData::Simple(address));
show->showToast(
tr::lng_gift_unique_address_copied(tr::now));
return false;
});
AddTableRow(
table,
tr::lng_gift_unique_owner(),
std::move(label),
st::giveawayGiftCodeValueMargin);
}
} else if (giftToChannel) {
AddTableRow(
table,
@ -1724,17 +1767,7 @@ void AddCreditsHistoryEntryTable(
Ui::Text::WithEntities));
}
if (!entry.id.isEmpty()) {
constexpr auto kOneLineCount = 24;
const auto oneLine = entry.id.length() <= kOneLineCount;
auto label = object_ptr<Ui::FlatLabel>(
table,
rpl::single(
Ui::Text::Wrapped({ entry.id }, EntityType::Code, {})),
(oneLine
? table->st().defaultValue
: st.tableValueMultiline
? *st.tableValueMultiline
: st::giveawayGiftCodeValueMultiline));
auto label = MakeMaybeMultilineTokenValue(table, entry.id, st);
label->setClickHandlerFilter([=](const auto &...) {
TextUtilities::SetClipboardText(
TextForMimeData::Simple(entry.id));

View file

@ -25,6 +25,10 @@ struct GiveawayResults;
struct SubscriptionEntry;
} // namespace Data
namespace Main {
class Session;
} // namespace Main
namespace Settings {
struct CreditsEntryBoxStyleOverrides;
} // namespace Settings
@ -62,6 +66,10 @@ void ResolveGiveawayInfo(
std::optional<Data::GiveawayStart> start,
std::optional<Data::GiveawayResults> results);
[[nodiscard]] QString TonAddressUrl(
not_null<Main::Session*> session,
const QString &address);
void AddStarGiftTable(
std::shared_ptr<ChatHelpers::Show> show,
not_null<Ui::VerticalLayout*> container,

View file

@ -40,6 +40,7 @@ struct UniqueGift {
CollectibleId id = 0;
QString slug;
QString title;
QString ownerAddress;
QString ownerName;
PeerId ownerId = 0;
int number = 0;

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/media/history_view_premium_gift.h"
#include "apiwrap.h"
#include "api/api_credits.h" // InputSavedStarGiftId
#include "api/api_premium.h"
#include "base/unixtime.h"
#include "boxes/gift_premium_box.h" // ResolveGiftCode
@ -219,6 +220,9 @@ bool PremiumGift::buttonMinistars() {
}
ClickHandlerPtr PremiumGift::createViewLink() {
if (auto link = OpenStarGiftLink(_parent->data())) {
return link;
}
const auto from = _gift->from();
const auto itemId = _parent->data()->fullId();
const auto peer = _parent->history()->peer;
@ -232,16 +236,7 @@ ClickHandlerPtr PremiumGift::createViewLink() {
}
const auto selfId = controller->session().userPeerId();
const auto sent = (from->id == selfId);
if (starGift()) {
const auto item = controller->session().data().message(itemId);
if (item) {
controller->show(Box(
Settings::StarGiftViewBox,
controller,
data,
item));
}
} else if (creditsPrize()) {
if (creditsPrize()) {
controller->show(Box(
Settings::CreditsPrizeBox,
controller,
@ -265,49 +260,6 @@ ClickHandlerPtr PremiumGift::createViewLink() {
ResolveGiftCode(controller, data.slug, fromId, toId);
}
};
if (const auto upgradeTo = data.upgradeMsgId) {
const auto requesting = std::make_shared<bool>();
return std::make_shared<LambdaClickHandler>([=](
ClickContext context) {
const auto my = context.other.value<ClickHandlerContext>();
const auto weak = my.sessionWindow;
const auto controller = weak.get();
if (!controller || *requesting) {
return;
}
*requesting = true;
controller->session().api().request(MTPpayments_GetSavedStarGift(
MTP_vector<MTPInputSavedStarGift>(
1,
MTP_inputSavedStarGiftUser(MTP_int(upgradeTo)))
)).done([=](const MTPpayments_SavedStarGifts &result) {
*requesting = false;
if (const auto window = weak.get()) {
const auto &data = result.data();
window->session().data().processUsers(data.vusers());
window->session().data().processChats(data.vchats());
const auto self = window->session().user();
const auto &list = data.vgifts().v;
if (list.empty()) {
showForWeakWindow(weak);
} else if (auto parsed = Api::FromTL(self, list[0])) {
window->show(Box(
Settings::SavedStarGiftBox,
window,
self,
*parsed));
}
}
}).fail([=](const MTP::Error &error) {
*requesting = false;
if (const auto window = weak.get()) {
window->showToast(error.type());
}
showForWeakWindow(weak);
}).send();
});
}
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
showForWeakWindow(
context.other.value<ClickHandlerContext>().sessionWindow);
@ -447,4 +399,76 @@ void PremiumGift::ensureStickerCreated() const {
}
}
ClickHandlerPtr OpenStarGiftLink(not_null<HistoryItem*> item) {
const auto media = item->media();
const auto gift = media ? media->gift() : nullptr;
if (!gift || gift->type != Data::GiftType::StarGift) {
return nullptr;
}
const auto data = *gift;
const auto itemId = item->fullId();
const auto openInsteadId = data.upgradeMsgId
? Data::SavedStarGiftId::User(data.upgradeMsgId)
: (data.channel && data.channelSavedId)
? Data::SavedStarGiftId::Chat(data.channel, data.channelSavedId)
: Data::SavedStarGiftId();
const auto requesting = std::make_shared<bool>();
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
const auto my = context.other.value<ClickHandlerContext>();
const auto weak = my.sessionWindow;
const auto controller = weak.get();
if (!controller) {
return;
}
const auto quick = [=](not_null<Window::SessionController*> window) {
const auto item = window->session().data().message(itemId);
if (item) {
window->show(Box(
Settings::StarGiftViewBox,
window,
data,
item));
}
};
if (!openInsteadId) {
quick(controller);
return;
} else if (*requesting) {
return;
}
*requesting = true;
controller->session().api().request(MTPpayments_GetSavedStarGift(
MTP_vector<MTPInputSavedStarGift>(
1,
Api::InputSavedStarGiftId(openInsteadId))
)).done([=](const MTPpayments_SavedStarGifts &result) {
*requesting = false;
if (const auto window = weak.get()) {
const auto &data = result.data();
window->session().data().processUsers(data.vusers());
window->session().data().processChats(data.vchats());
const auto owner = openInsteadId.chat()
? openInsteadId.chat()
: window->session().user();
const auto &list = data.vgifts().v;
if (list.empty()) {
quick(window);
} else if (auto parsed = Api::FromTL(owner, list[0])) {
window->show(Box(
Settings::SavedStarGiftBox,
window,
owner,
*parsed));
}
}
}).fail([=](const MTP::Error &error) {
*requesting = false;
if (const auto window = weak.get()) {
window->showToast(error.type());
quick(window);
}
}).send();
});
}
} // namespace HistoryView

View file

@ -68,4 +68,6 @@ private:
};
[[nodiscard]] ClickHandlerPtr OpenStarGiftLink(not_null<HistoryItem*> item);
} // namespace HistoryView

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "data/data_star_gift.h"
#include "history/view/media/history_view_media_generic.h"
#include "history/view/media/history_view_premium_gift.h"
#include "history/view/history_view_cursor_state.h"
#include "history/view/history_view_element.h"
#include "history/history.h"
@ -457,24 +458,7 @@ auto GenerateUniqueGiftMedia(
gift->backdrop.textColor));
const auto itemId = parent->data()->fullId();
auto link = std::make_shared<LambdaClickHandler>([=](
ClickContext context) {
const auto my = context.other.value<ClickHandlerContext>();
if (const auto controller = my.sessionWindow.get()) {
const auto owner = &controller->session().data();
if (const auto item = owner->message(itemId)) {
if (const auto media = item->media()) {
if (const auto gift = media->gift()) {
controller->show(Box(
Settings::StarGiftViewBox,
controller,
*gift,
item));
}
}
}
}
});
auto link = OpenStarGiftLink(parent->data());
push(std::make_unique<ButtonPart>(
tr::lng_sticker_premium_view(tr::now),
st::chatUniqueButtonPadding,

View file

@ -1604,6 +1604,20 @@ void GenericCreditsEntryBox(
toggleVisibility(!e.savedToProfile);
return false;
});
} else if (uniqueGift && !uniqueGift->ownerAddress.isEmpty()) {
const auto label = box->addRow(
object_ptr<Ui::FlatLabel>(
box,
tr::lng_gift_in_blockchain(
lt_link,
tr::lng_gift_in_blockchain_link() | Ui::Text::ToLink(),
Ui::Text::WithEntities),
st::creditsBoxAboutDivider));
label->setClickHandlerFilter([=](const auto &...) {
UrlClickHandler::Open(
TonAddressUrl(session, uniqueGift->ownerAddress));
return false;
});
}
if (s) {
const auto user = peer ? peer->asUser() : nullptr;