Added menu with about box to sponsored messages that can be reported.

This commit is contained in:
23rd 2024-03-27 16:07:43 +03:00 committed by John Preston
parent 57789c1272
commit 341b9e4a29
20 changed files with 289 additions and 3 deletions

View file

@ -1141,6 +1141,8 @@ PRIVATE
menu/menu_mute.h
menu/menu_send.cpp
menu/menu_send.h
menu/menu_sponsored.cpp
menu/menu_sponsored.h
menu/menu_ttl_validator.cpp
menu/menu_ttl_validator.h
mtproto/config_loader.cpp

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -4656,6 +4656,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_sponsored_info_description2" = "Sponsored Messages are currently in test mode. Once they are fully launched and allow Telegram to cover its basic costs, we will start sharing ad revenue with the owners of public channels in which sponsored messages are displayed.\n\nOnline ads should no longer be synonymous with abuse of user privacy. Let us redefine how a tech company should operate together.";
"lng_sponsored_info_menu" = "About this ad";
"lng_sponsored_info_submenu" = "Advertiser: {text}";
"lng_sponsored_menu_revenued_about" = "About These Ads";
"lng_sponsored_revenued_subtitle" = "Telegram Ads are very different from ads on other platforms. Ads such as this one:";
"lng_sponsored_revenued_info1_title" = "Respect Your Privacy";
"lng_sponsored_revenued_info1_description" = "Ads on Telegram do not use your personal information and are abased on the channel in which you see them.";
"lng_sponsored_revenued_info2_title" = "Help the Channel Creator";
"lng_sponsored_revenued_info2_description" = "50% of the revenue from Telegram Ads goes to the owner of the channel where they are displayed.";
"lng_sponsored_revenued_info3_title" = "Can Be Removed";
"lng_sponsored_revenued_info3_description#one" = "You can turn off ads by subscribing to {link}, and Level {count} channels can remove them for their subscribers.";
"lng_sponsored_revenued_info3_description#other" = "You can turn off ads by subscribing to {link}, and Level {count} channels can remove them for their subscribers.";
"lng_sponsored_revenued_footer_title" = "Can I Launch an Ad?";
"lng_sponsored_revenued_footer_description" = "Anyone can create an ad to display in this channel — with minimal budgets. Check out the **Telegram Ad Platform** for details. {link}";
"lng_telegram_features_url" = "https://t.me/TelegramTips";

View file

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_domain.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "menu/menu_sponsored.h"
#include "platform/platform_notifications_manager.h"
#include "window/window_controller.h"
#include "window/window_session_controller.h"
@ -367,8 +368,15 @@ ClickHandlerPtr HideSponsoredClickHandler() {
});
}
ClickHandlerPtr ReportSponsoredClickHandler() {
ClickHandlerPtr ReportSponsoredClickHandler(not_null<HistoryItem*> item) {
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
const auto my = context.other.value<ClickHandlerContext>();
if (const auto controller = my.sessionWindow.get()) {
Menu::ShowSponsored(
controller->widget(),
controller->uiShow(),
item);
}
});
}

View file

@ -142,7 +142,8 @@ ClickHandlerPtr JumpToStoryClickHandler(
not_null<PeerData*> peer,
StoryId storyId);
[[nodiscard]] ClickHandlerPtr HideSponsoredClickHandler();
[[nodiscard]] ClickHandlerPtr ReportSponsoredClickHandler();
[[nodiscard]] ClickHandlerPtr ReportSponsoredClickHandler(
not_null<HistoryItem*> item);
[[nodiscard]] not_null<HistoryItem*> GenerateJoinedMessage(
not_null<History*> history,

View file

@ -441,7 +441,7 @@ Message::Message(
_rightAction = std::make_unique<RightAction>();
_rightAction->second = std::make_unique<SecondRightAction>();
_rightAction->second->link = ReportSponsoredClickHandler();
_rightAction->second->link = ReportSponsoredClickHandler(data);
}
}
}

View file

@ -108,3 +108,8 @@ channelEarnLearnDescription: FlatLabel(defaultFlatLabel) {
minWidth: 280px;
align: align(top);
}
sponsoredAboutTitleIcon: icon {{ "sponsored/large_about", activeButtonFg }};
sponsoredAboutPrivacyIcon: icon {{ "sponsored/privacy_about", boxTextFg }};
sponsoredAboutRemoveIcon: icon {{ "sponsored/remove_about", boxTextFg }};
sponsoredAboutSplitIcon: icon {{ "sponsored/revenue_split", boxTextFg }};

View file

@ -0,0 +1,235 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "menu/menu_sponsored.h"
#include "core/ui_integration.h" // Core::MarkedTextContext.
#include "data/data_premium_limits.h"
#include "data/data_session.h"
#include "data/stickers/data_custom_emoji.h"
#include "history/history.h"
#include "history/history_item.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "ui/layers/generic_box.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/text_utilities.h"
#include "ui/vertical_list.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h"
#include "styles/style_channel_earn.h"
#include "styles/style_chat.h"
#include "styles/style_layers.h"
#include "styles/style_menu_icons.h"
#include "styles/style_premium.h"
#include "styles/style_settings.h"
namespace Menu {
namespace {
void AboutBox(
not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session) {
constexpr auto kUrl = "https://promote.telegram.org"_cs;
box->setNoContentMargin(true);
const auto content = box->verticalLayout().get();
const auto levels = Data::LevelLimits(session)
.channelRestrictSponsoredLevelMin();
Ui::AddSkip(content);
Ui::AddSkip(content);
Ui::AddSkip(content);
{
const auto &icon = st::sponsoredAboutTitleIcon;
const auto rect = Rect(icon.size() * 1.4);
auto owned = object_ptr<Ui::RpWidget>(content);
owned->resize(rect.size());
const auto widget = box->addRow(object_ptr<Ui::CenterWrap<>>(
content,
std::move(owned)))->entity();
widget->paintRequest(
) | rpl::start_with_next([=] {
auto p = Painter(widget);
p.setPen(Qt::NoPen);
p.setBrush(st::activeButtonBg);
p.drawEllipse(rect);
icon.paintInCenter(p, rect);
}, widget->lifetime());
}
Ui::AddSkip(content);
Ui::AddSkip(content);
box->addRow(object_ptr<Ui::CenterWrap<>>(
content,
object_ptr<Ui::FlatLabel>(
content,
tr::lng_sponsored_menu_revenued_about(),
st::boxTitle)));
Ui::AddSkip(content);
box->addRow(object_ptr<Ui::CenterWrap<>>(
content,
object_ptr<Ui::FlatLabel>(
content,
tr::lng_sponsored_revenued_subtitle(),
st::channelEarnLearnDescription)));
Ui::AddSkip(content);
Ui::AddSkip(content);
{
const auto padding = QMargins(
st::settingsButton.padding.left(),
st::boxRowPadding.top(),
st::boxRowPadding.right(),
st::boxRowPadding.bottom());
const auto addEntry = [&](
rpl::producer<QString> title,
rpl::producer<TextWithEntities> about,
const style::icon &icon) {
const auto top = content->add(
object_ptr<Ui::FlatLabel>(
content,
std::move(title),
st::channelEarnSemiboldLabel),
padding);
Ui::AddSkip(content, st::channelEarnHistoryThreeSkip);
content->add(
object_ptr<Ui::FlatLabel>(
content,
std::move(about),
st::channelEarnHistoryRecipientLabel),
padding);
const auto left = Ui::CreateChild<Ui::RpWidget>(
box->verticalLayout().get());
left->paintRequest(
) | rpl::start_with_next([=] {
auto p = Painter(left);
icon.paint(p, 0, 0, left->width());
}, left->lifetime());
left->resize(icon.size());
top->geometryValue(
) | rpl::start_with_next([=](const QRect &g) {
left->moveToLeft(
(g.left() - left->width()) / 2,
g.top() + st::channelEarnHistoryThreeSkip);
}, left->lifetime());
};
addEntry(
tr::lng_sponsored_revenued_info1_title(),
tr::lng_sponsored_revenued_info1_description(
Ui::Text::RichLangValue),
st::sponsoredAboutPrivacyIcon);
Ui::AddSkip(content);
Ui::AddSkip(content);
addEntry(
tr::lng_sponsored_revenued_info2_title(),
tr::lng_sponsored_revenued_info2_description(
Ui::Text::RichLangValue),
st::sponsoredAboutSplitIcon);
Ui::AddSkip(content);
Ui::AddSkip(content);
addEntry(
tr::lng_sponsored_revenued_info3_title(),
tr::lng_sponsored_revenued_info3_description(
lt_count,
rpl::single(float64(levels)),
lt_link,
tr::lng_settings_privacy_premium_link(
) | rpl::map([=](QString t) {
return Ui::Text::Link(t, kUrl.utf8());
}),
Ui::Text::RichLangValue),
st::sponsoredAboutRemoveIcon);
Ui::AddSkip(content);
Ui::AddSkip(content);
}
Ui::AddSkip(content);
Ui::AddSkip(content);
{
box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
content,
object_ptr<Ui::FlatLabel>(
content,
tr::lng_sponsored_revenued_footer_title(),
st::boxTitle)));
}
Ui::AddSkip(content);
{
const auto arrow = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::topicButtonArrow,
st::channelEarnLearnArrowMargins,
false));
const auto label = box->addRow(
object_ptr<Ui::FlatLabel>(
content,
st::channelEarnLearnDescription));
tr::lng_sponsored_revenued_footer_description(
lt_link,
tr::lng_channel_earn_about_link(
lt_emoji,
rpl::single(arrow),
Ui::Text::RichLangValue
) | rpl::map([=](TextWithEntities text) {
return Ui::Text::Link(std::move(text), kUrl.utf8());
}),
Ui::Text::RichLangValue
) | rpl::start_with_next([=, l = label](
TextWithEntities t) {
l->setMarkedText(
std::move(t),
Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [=] { l->update(); },
});
l->resizeToWidth(box->width()
- rect::m::sum::h(st::boxRowPadding));
}, label->lifetime());
}
Ui::AddSkip(content);
Ui::AddSkip(content);
{
const auto &st = st::premiumPreviewDoubledLimitsBox;
box->setStyle(st);
auto button = object_ptr<Ui::RoundButton>(
box,
tr::lng_box_ok(),
st::defaultActiveButton);
button->resizeToWidth(box->width()
- st.buttonPadding.left()
- st.buttonPadding.left());
button->setClickedCallback([=] { box->closeBox(); });
box->addButton(std::move(button));
}
}
} // namespace
void ShowSponsored(
not_null<Ui::RpWidget*> parent,
std::shared_ptr<Ui::Show> show,
not_null<HistoryItem*> item) {
Expects(item->isSponsored());
struct State final {
};
const auto state = std::make_shared<State>();
const auto menu = Ui::CreateChild<Ui::PopupMenu>(
parent.get(),
st::popupMenuWithIcons);
menu->addAction(tr::lng_sponsored_menu_revenued_about(tr::now), [=] {
show->show(Box(AboutBox, &item->history()->session()));
}, &st::menuIconInfo);
menu->popup(QCursor::pos());
}
} // namespace Menu

View file

@ -0,0 +1,24 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Ui {
class RpWidget;
class Show;
} // namespace Ui
class HistoryItem;
namespace Menu {
void ShowSponsored(
not_null<Ui::RpWidget*> parent,
std::shared_ptr<Ui::Show> show,
not_null<HistoryItem*> item);
} // namespace Menu