mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-03 21:54:05 +02:00
Support sponsored peers in search results.
This commit is contained in:
parent
33c5b35444
commit
a0764190f2
17 changed files with 546 additions and 227 deletions
|
@ -4392,6 +4392,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_search_filter_private" = "Private chats";
|
||||
"lng_search_filter_group" = "Group chats";
|
||||
"lng_search_filter_channel" = "Channels";
|
||||
"lng_search_sponsored_button" = "Ad ⋮";
|
||||
|
||||
"lng_media_save_progress" = "{ready} of {total} {mb}";
|
||||
"lng_mediaview_save_as" = "Save As...";
|
||||
|
@ -5806,6 +5807,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_sponsored_revenued_info1_title" = "Respect Your Privacy";
|
||||
"lng_sponsored_revenued_info1_description" = "Ads on Telegram do not use your personal information and are based on the channel in which you see them.";
|
||||
"lng_sponsored_revenued_info1_bot_description" = "Ads on Telegram do not use your personal information and are based on the mini app in which you see them.";
|
||||
"lng_sponsored_revenued_info1_search_description" = "Ads on Telegram do not use your personal information and are based on the search query you entered.";
|
||||
"lng_sponsored_revenued_info2_title" = "Help the Channel Creator";
|
||||
"lng_sponsored_revenued_info2_bot_title" = "Help the Bot Developer";
|
||||
"lng_sponsored_revenued_info2_description" = "50% of the revenue from Telegram Ads goes to the owner of the channel where they are displayed.";
|
||||
|
@ -5814,9 +5816,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"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_info3_bot_description" = "You can turn off ads in mini apps by subscribing to {link}.";
|
||||
"lng_sponsored_revenued_info3_search_description" = "You can turn off ads by subscribing to Telegram Premium. {link}";
|
||||
"lng_sponsored_revenued_info3_search_link" = "Subscribe {arrow}";
|
||||
"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_sponsored_revenued_footer_bot_description" = "Anyone can create an ad to display in this bot — with minimal budgets. Check out the **Telegram Ad Platform** for details. {link}";
|
||||
"lng_sponsored_revenued_footer_search_description" = "Anyone can create an ad to display in search results for any query. Check out the **Telegram Ad Platform** for details. {link}";
|
||||
"lng_sponsored_top_bar_hide" = "remove";
|
||||
|
||||
"lng_telegram_features_url" = "https://t.me/TelegramTips";
|
||||
|
|
|
@ -106,9 +106,10 @@ void PeerSearch::requestSponsored() {
|
|||
parsed.sponsored.push_back({
|
||||
.peer = _session->data().peer(peerId),
|
||||
.randomId = data.vrandom_id().v,
|
||||
.sponsorInfo = qs(data.vsponsor_info().value_or_empty()),
|
||||
.additionalInfo = qs(
|
||||
data.vadditional_info().value_or_empty()),
|
||||
.sponsorInfo = TextWithEntities::Simple(
|
||||
qs(data.vsponsor_info().value_or_empty())),
|
||||
.additionalInfo = TextWithEntities::Simple(
|
||||
qs(data.vadditional_info().value_or_empty())),
|
||||
});
|
||||
}
|
||||
finishSponsored(requestId, std::move(parsed));
|
||||
|
|
|
@ -16,8 +16,8 @@ namespace Api {
|
|||
struct SponsoredSearchResult {
|
||||
not_null<PeerData*> peer;
|
||||
QByteArray randomId;
|
||||
QString sponsorInfo;
|
||||
QString additionalInfo;
|
||||
TextWithEntities sponsorInfo;
|
||||
TextWithEntities additionalInfo;
|
||||
};
|
||||
|
||||
struct PeerSearchResult {
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/components/sponsored_messages.h"
|
||||
|
||||
#include "api/api_text_entities.h"
|
||||
#include "api/api_peer_search.h" // SponsoredSearchResult
|
||||
#include "apiwrap.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "data/data_channel.h"
|
||||
|
@ -33,6 +34,19 @@ constexpr auto kRequestTimeLimit = 5 * 60 * crl::time(1000);
|
|||
return (received > 0) && (received + kRequestTimeLimit > crl::now());
|
||||
}
|
||||
|
||||
template <typename Fields>
|
||||
[[nodiscard]] std::vector<TextWithEntities> Prepare(const Fields &fields) {
|
||||
using InfoList = std::vector<TextWithEntities>;
|
||||
return (!fields.sponsorInfo.text.isEmpty()
|
||||
&& !fields.additionalInfo.text.isEmpty())
|
||||
? InfoList{ fields.sponsorInfo, fields.additionalInfo }
|
||||
: !fields.sponsorInfo.text.isEmpty()
|
||||
? InfoList{ fields.sponsorInfo }
|
||||
: !fields.additionalInfo.text.isEmpty()
|
||||
? InfoList{ fields.additionalInfo }
|
||||
: InfoList{};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SponsoredMessages::SponsoredMessages(not_null<Main::Session*> session)
|
||||
|
@ -535,18 +549,8 @@ SponsoredMessages::Details SponsoredMessages::lookupDetails(
|
|||
return {};
|
||||
}
|
||||
const auto &data = entryPtr->sponsored;
|
||||
|
||||
using InfoList = std::vector<TextWithEntities>;
|
||||
auto info = (!data.sponsorInfo.text.isEmpty()
|
||||
&& !data.additionalInfo.text.isEmpty())
|
||||
? InfoList{ data.sponsorInfo, data.additionalInfo }
|
||||
: !data.sponsorInfo.text.isEmpty()
|
||||
? InfoList{ data.sponsorInfo }
|
||||
: !data.additionalInfo.text.isEmpty()
|
||||
? InfoList{ data.additionalInfo }
|
||||
: InfoList{};
|
||||
return {
|
||||
.info = std::move(info),
|
||||
.info = Prepare(data),
|
||||
.link = data.link,
|
||||
.buttonText = data.from.buttonText,
|
||||
.photoId = data.from.photoId,
|
||||
|
@ -559,6 +563,14 @@ SponsoredMessages::Details SponsoredMessages::lookupDetails(
|
|||
};
|
||||
}
|
||||
|
||||
SponsoredMessages::Details SponsoredMessages::lookupDetails(
|
||||
const Api::SponsoredSearchResult &data) const {
|
||||
return {
|
||||
.info = Prepare(data),
|
||||
.canReport = true,
|
||||
};
|
||||
}
|
||||
|
||||
void SponsoredMessages::clicked(
|
||||
const FullMsgId &fullId,
|
||||
bool isMedia,
|
||||
|
@ -583,9 +595,29 @@ void SponsoredMessages::clicked(
|
|||
)).send();
|
||||
}
|
||||
|
||||
SponsoredReportAction SponsoredMessages::createReportCallback(
|
||||
const FullMsgId &fullId) {
|
||||
const auto entry = find(fullId);
|
||||
if (!entry) {
|
||||
return { .callback = [=](const auto &...) {} };
|
||||
}
|
||||
const auto history = _session->data().history(fullId.peer);
|
||||
const auto erase = [=] {
|
||||
const auto it = _data.find(history);
|
||||
if (it != end(_data)) {
|
||||
auto &list = it->second.entries;
|
||||
const auto proj = [&](const Entry &e) {
|
||||
return e.itemFullId == fullId;
|
||||
};
|
||||
list.erase(ranges::remove_if(list, proj), end(list));
|
||||
}
|
||||
};
|
||||
return createReportCallback(entry->sponsored.randomId, erase);
|
||||
}
|
||||
|
||||
auto SponsoredMessages::createReportCallback(const FullMsgId &fullId)
|
||||
-> Fn<void(SponsoredReportResult::Id, Fn<void(SponsoredReportResult)>)> {
|
||||
SponsoredReportAction SponsoredMessages::createReportCallback(
|
||||
const QByteArray &randomId,
|
||||
Fn<void()> erase) {
|
||||
using TLChoose = MTPDchannels_sponsoredMessageReportResultChooseOption;
|
||||
using TLAdsHidden = MTPDchannels_sponsoredMessageReportResultAdsHidden;
|
||||
using TLReported = MTPDchannels_sponsoredMessageReportResultReported;
|
||||
|
@ -601,25 +633,7 @@ auto SponsoredMessages::createReportCallback(const FullMsgId &fullId)
|
|||
};
|
||||
const auto state = std::make_shared<State>();
|
||||
|
||||
return [=](Result::Id optionId, Fn<void(Result)> done) {
|
||||
const auto entry = find(fullId);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto history = _session->data().history(fullId.peer);
|
||||
|
||||
const auto erase = [=] {
|
||||
const auto it = _data.find(history);
|
||||
if (it != end(_data)) {
|
||||
auto &list = it->second.entries;
|
||||
const auto proj = [&](const Entry &e) {
|
||||
return e.itemFullId == fullId;
|
||||
};
|
||||
list.erase(ranges::remove_if(list, proj), end(list));
|
||||
}
|
||||
};
|
||||
|
||||
return { .callback = [=](Result::Id optionId, Fn<void(Result)> done) {
|
||||
if (optionId == Result::Id("-1")) {
|
||||
erase();
|
||||
return;
|
||||
|
@ -627,7 +641,7 @@ auto SponsoredMessages::createReportCallback(const FullMsgId &fullId)
|
|||
|
||||
state->requestId = _session->api().request(
|
||||
MTPmessages_ReportSponsoredMessage(
|
||||
MTP_bytes(entry->sponsored.randomId),
|
||||
MTP_bytes(randomId),
|
||||
MTP_bytes(optionId))
|
||||
).done([=](
|
||||
const MTPchannels_SponsoredMessageReportResult &result,
|
||||
|
@ -664,7 +678,7 @@ auto SponsoredMessages::createReportCallback(const FullMsgId &fullId)
|
|||
done({ .error = error.type() });
|
||||
}
|
||||
}).send();
|
||||
};
|
||||
} };
|
||||
}
|
||||
|
||||
SponsoredMessages::State SponsoredMessages::state(
|
||||
|
|
|
@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
class History;
|
||||
|
||||
namespace Api {
|
||||
struct SponsoredSearchResult;
|
||||
} // namespace Api
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
@ -69,6 +73,25 @@ struct SponsoredMessage {
|
|||
TextWithEntities additionalInfo;
|
||||
};
|
||||
|
||||
struct SponsoredMessageDetails {
|
||||
std::vector<TextWithEntities> info;
|
||||
QString link;
|
||||
QString buttonText;
|
||||
PhotoId photoId = PhotoId(0);
|
||||
PhotoId mediaPhotoId = PhotoId(0);
|
||||
DocumentId mediaDocumentId = DocumentId(0);
|
||||
uint64 backgroundEmojiId = 0;
|
||||
uint8 colorIndex : 6 = 0;
|
||||
bool isLinkInternal = false;
|
||||
bool canReport = false;
|
||||
};
|
||||
|
||||
struct SponsoredReportAction {
|
||||
Fn<void(
|
||||
Data::SponsoredReportResult::Id,
|
||||
Fn<void(Data::SponsoredReportResult)>)> callback;
|
||||
};
|
||||
|
||||
class SponsoredMessages final {
|
||||
public:
|
||||
enum class AppendResult {
|
||||
|
@ -82,18 +105,7 @@ public:
|
|||
InjectToMiddle,
|
||||
AppendToTopBar,
|
||||
};
|
||||
struct Details {
|
||||
std::vector<TextWithEntities> info;
|
||||
QString link;
|
||||
QString buttonText;
|
||||
PhotoId photoId = PhotoId(0);
|
||||
PhotoId mediaPhotoId = PhotoId(0);
|
||||
DocumentId mediaDocumentId = DocumentId(0);
|
||||
uint64 backgroundEmojiId = 0;
|
||||
uint8 colorIndex : 6 = 0;
|
||||
bool isLinkInternal = false;
|
||||
bool canReport = false;
|
||||
};
|
||||
using Details = SponsoredMessageDetails;
|
||||
using RandomId = QByteArray;
|
||||
explicit SponsoredMessages(not_null<Main::Session*> session);
|
||||
~SponsoredMessages();
|
||||
|
@ -103,6 +115,8 @@ public:
|
|||
void request(not_null<History*> history, Fn<void()> done);
|
||||
void clearItems(not_null<History*> history);
|
||||
[[nodiscard]] Details lookupDetails(const FullMsgId &fullId) const;
|
||||
[[nodiscard]] Details lookupDetails(
|
||||
const Api::SponsoredSearchResult &data) const;
|
||||
void clicked(const FullMsgId &fullId, bool isMedia, bool isFullscreen);
|
||||
void clicked(
|
||||
const QByteArray &randomId,
|
||||
|
@ -125,8 +139,11 @@ public:
|
|||
|
||||
[[nodiscard]] State state(not_null<History*> history) const;
|
||||
|
||||
[[nodiscard]] auto createReportCallback(const FullMsgId &fullId)
|
||||
-> Fn<void(SponsoredReportResult::Id, Fn<void(SponsoredReportResult)>)>;
|
||||
[[nodiscard]] SponsoredReportAction createReportCallback(
|
||||
const FullMsgId &fullId);
|
||||
[[nodiscard]] SponsoredReportAction createReportCallback(
|
||||
const QByteArray &randomId,
|
||||
Fn<void()> erase);
|
||||
|
||||
void clear();
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@ DialogRow {
|
|||
unreadMarkDiameter: pixels;
|
||||
tagTop: pixels;
|
||||
}
|
||||
DialogRightButton {
|
||||
button: RoundButton;
|
||||
margin: margins;
|
||||
}
|
||||
|
||||
ThreeStateIcon {
|
||||
icon: icon;
|
||||
|
@ -115,11 +119,16 @@ dialogRowFilterTagSkip: 4px;
|
|||
dialogRowFilterTagStyle: TextStyle(defaultTextStyle) {
|
||||
font: font(10px);
|
||||
}
|
||||
dialogRowOpenBotTextStyle: semiboldTextStyle;
|
||||
dialogRowOpenBotHeight: 20px;
|
||||
dialogRowOpenBotRight: 10px;
|
||||
dialogRowOpenBotTop: 32px;
|
||||
dialogRowOpenBotRecentTop: 28px;
|
||||
dialogRowOpenBot: DialogRightButton {
|
||||
button: RoundButton(defaultActiveButton) {
|
||||
height: 20px;
|
||||
textTop: 1px;
|
||||
}
|
||||
margin: margins(0px, 32px, 10px, 0px);
|
||||
}
|
||||
dialogRowOpenBotRecent: DialogRightButton(dialogRowOpenBot) {
|
||||
margin: margins(0px, 32px, 28px, 0px);
|
||||
}
|
||||
|
||||
forumDialogJumpArrow: icon{{ "dialogs/dialogs_topic_arrow", dialogsTextFg }};
|
||||
forumDialogJumpArrowOver: icon{{ "dialogs/dialogs_topic_arrow", dialogsTextFgOver }};
|
||||
|
@ -792,3 +801,15 @@ dialogsPopularAppsAbout: FlatLabel(boxDividerLabel) {
|
|||
|
||||
dialogsQuickActionSize: 20px;
|
||||
dialogsQuickActionRippleSize: 80px;
|
||||
|
||||
dialogsSponsoredButton: DialogRightButton(dialogRowOpenBot) {
|
||||
button: RoundButton(defaultLightButton) {
|
||||
textFg: windowActiveTextFg;
|
||||
textFgOver: windowActiveTextFg;
|
||||
textBg: lightButtonBgOver;
|
||||
textBgOver: lightButtonBgOver;
|
||||
height: 20px;
|
||||
textTop: 1px;
|
||||
}
|
||||
margin: margins(0px, 9px, 10px, 0px);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
namespace style {
|
||||
struct DialogRightButton;
|
||||
} // namespace style
|
||||
|
||||
namespace Ui {
|
||||
class RippleAnimation;
|
||||
} // namespace Ui
|
||||
|
@ -114,11 +118,16 @@ struct RowsByLetter {
|
|||
};
|
||||
|
||||
struct RightButton final {
|
||||
const style::DialogRightButton *st = nullptr;
|
||||
QImage bg;
|
||||
QImage selectedBg;
|
||||
QImage activeBg;
|
||||
Ui::Text::String text;
|
||||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
|
||||
explicit operator bool() const {
|
||||
return st != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Dialogs
|
||||
|
|
|
@ -63,6 +63,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "apiwrap.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_session_settings.h"
|
||||
#include "menu/menu_sponsored.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
@ -241,12 +242,17 @@ struct InnerWidget::HashtagResult {
|
|||
BasicRow row;
|
||||
};
|
||||
|
||||
struct InnerWidget::SponsoredSearchResult {
|
||||
Api::SponsoredSearchResult data;
|
||||
RightButton button;
|
||||
};
|
||||
|
||||
struct InnerWidget::PeerSearchResult {
|
||||
explicit PeerSearchResult(not_null<PeerData*> peer) : peer(peer) {
|
||||
}
|
||||
|
||||
not_null<PeerData*> peer;
|
||||
std::unique_ptr<Api::SponsoredSearchResult> sponsored;
|
||||
std::unique_ptr<SponsoredSearchResult> sponsored;
|
||||
mutable Ui::Text::String name;
|
||||
mutable Ui::PeerBadge badge;
|
||||
BasicRow row;
|
||||
|
@ -287,6 +293,12 @@ InnerWidget::InnerWidget(
|
|||
_topicJumpCache = nullptr;
|
||||
_chatsFilterTags.clear();
|
||||
_rightButtons.clear();
|
||||
_pressedRightButtonData = nullptr;
|
||||
for (const auto &result : _peerSearchResults) {
|
||||
if (const auto sponsored = result->sponsored.get()) {
|
||||
sponsored->button = {};
|
||||
}
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
session().downloaderTaskFinished(
|
||||
|
@ -1139,17 +1151,32 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
&& r.y() <= (skip + from * st::dialogsRowHeight)
|
||||
&& r.y() + r.height() >= (skip + (from + 1) * st::dialogsRowHeight)) {
|
||||
session().sponsoredMessages().view(
|
||||
result->sponsored->randomId);
|
||||
result->sponsored->data.randomId);
|
||||
}
|
||||
const auto peer = result->peer;
|
||||
const auto active = !activeEntry.fullId
|
||||
&& activePeer
|
||||
&& ((peer == activePeer)
|
||||
|| (peer->migrateTo() == activePeer));
|
||||
const auto selected = (from == (isPressed()
|
||||
const auto selected = (from == ((_peerSearchMenu >= 0)
|
||||
? _peerSearchMenu
|
||||
: isPressed()
|
||||
? _peerSearchPressed
|
||||
: _peerSearchSelected));
|
||||
if (result->sponsored
|
||||
&& result->sponsored->button.text.isEmpty()) {
|
||||
fillRightButton(
|
||||
result->sponsored->button,
|
||||
tr::lng_search_sponsored_button(
|
||||
tr::now,
|
||||
Ui::Text::WithEntities),
|
||||
st::dialogsSponsoredButton);
|
||||
}
|
||||
|
||||
paintPeerSearchResult(p, result.get(), {
|
||||
.rightButton = (result->sponsored
|
||||
? &result->sponsored->button
|
||||
: nullptr),
|
||||
.st = &st::defaultDialogRow,
|
||||
.currentBg = currentBg(),
|
||||
.now = ms,
|
||||
|
@ -1307,36 +1334,47 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
void InnerWidget::fillRightButton(
|
||||
RightButton &button,
|
||||
const TextWithEntities &text,
|
||||
const style::DialogRightButton &st) {
|
||||
button.st = &st;
|
||||
button.text.setMarkedText(st.button.style, text);
|
||||
const auto size = QSize(
|
||||
button.text.maxWidth() + button.text.minHeight(),
|
||||
st.button.height);
|
||||
const auto generateBg = [&](const style::color &c) {
|
||||
auto bg = QImage(
|
||||
style::DevicePixelRatio() * size,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
bg.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
bg.fill(Qt::transparent);
|
||||
{
|
||||
auto p = QPainter(&bg);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(c);
|
||||
const auto r = size.height() / 2;
|
||||
p.drawRoundedRect(Rect(size), r, r);
|
||||
}
|
||||
return bg;
|
||||
};
|
||||
button.bg = generateBg(st.button.textBg);
|
||||
button.selectedBg = generateBg(st.button.textBgOver);
|
||||
button.activeBg = generateBg(st.button.textFg);
|
||||
}
|
||||
|
||||
[[nodiscard]] RightButton *InnerWidget::maybeCacheRightButton(Row *row) {
|
||||
if (const auto user = MaybeBotWithApp(row)) {
|
||||
const auto it = _rightButtons.find(user->id);
|
||||
if (it == _rightButtons.end()) {
|
||||
auto rightButton = RightButton();
|
||||
const auto text = tr::lng_profile_open_app_short(tr::now);
|
||||
rightButton.text.setText(st::dialogRowOpenBotTextStyle, text);
|
||||
const auto size = QSize(
|
||||
rightButton.text.maxWidth()
|
||||
+ rightButton.text.minHeight(),
|
||||
st::dialogRowOpenBotHeight);
|
||||
const auto generateBg = [&](const style::color &c) {
|
||||
auto bg = QImage(
|
||||
style::DevicePixelRatio() * size,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
bg.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
bg.fill(Qt::transparent);
|
||||
{
|
||||
auto p = QPainter(&bg);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(c);
|
||||
const auto r = size.height() / 2;
|
||||
p.drawRoundedRect(Rect(size), r, r);
|
||||
}
|
||||
return bg;
|
||||
};
|
||||
rightButton.bg = generateBg(st::activeButtonBg);
|
||||
rightButton.selectedBg = generateBg(st::activeButtonBgOver);
|
||||
rightButton.activeBg = generateBg(st::activeButtonFg);
|
||||
fillRightButton(
|
||||
rightButton,
|
||||
tr::lng_profile_open_app_short(
|
||||
tr::now,
|
||||
Ui::Text::WithEntities),
|
||||
st::dialogRowOpenBot);
|
||||
return &(_rightButtons.emplace(
|
||||
user->id,
|
||||
std::move(rightButton)).first->second);
|
||||
|
@ -1459,7 +1497,11 @@ void InnerWidget::paintPeerSearchResult(
|
|||
context.st->photoSize);
|
||||
|
||||
auto nameleft = context.st->nameLeft;
|
||||
auto namewidth = context.width - nameleft - context.st->padding.right();
|
||||
auto available = context.width - nameleft - context.st->padding.right();
|
||||
auto namewidth = available;
|
||||
if (const auto used = Ui::PaintRightButton(p, context)) {
|
||||
namewidth -= used - st::dialogsUnreadPadding;
|
||||
}
|
||||
QRect rectForName(nameleft, context.st->nameTop, namewidth, st::semiboldFont->height);
|
||||
|
||||
if (result->name.isEmpty()) {
|
||||
|
@ -1611,7 +1653,7 @@ void InnerWidget::clearIrrelevantState() {
|
|||
_filteredSelected = -1;
|
||||
setFilteredPressed(-1, false, false);
|
||||
_peerSearchSelected = -1;
|
||||
setPeerSearchPressed(-1);
|
||||
setPeerSearchPressed(-1, false);
|
||||
_previewSelected = -1;
|
||||
setPreviewPressed(-1);
|
||||
_searchedSelected = -1;
|
||||
|
@ -1630,20 +1672,28 @@ bool InnerWidget::lookupIsInBotAppButton(
|
|||
if (const auto user = MaybeBotWithApp(row)) {
|
||||
const auto it = _rightButtons.find(user->id);
|
||||
if (it != _rightButtons.end()) {
|
||||
const auto s = it->second.bg.size() / style::DevicePixelRatio();
|
||||
const auto r = QRect(
|
||||
width() - s.width() - st::dialogRowOpenBotRight,
|
||||
st::dialogRowOpenBotTop,
|
||||
s.width(),
|
||||
s.height());
|
||||
if (r.contains(localPosition)) {
|
||||
return true;
|
||||
}
|
||||
return lookupIsInRightButton(it->second, localPosition);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InnerWidget::lookupIsInRightButton(
|
||||
const RightButton &button,
|
||||
QPoint localPosition) {
|
||||
if (!button.st) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto s = button.bg.size() / style::DevicePixelRatio();
|
||||
const auto r = QRect(
|
||||
width() - s.width() - button.st->margin.right(),
|
||||
button.st->margin.top(),
|
||||
s.width(),
|
||||
s.height());
|
||||
return r.contains(localPosition);
|
||||
}
|
||||
|
||||
void InnerWidget::selectByMouse(QPoint globalPosition) {
|
||||
const auto local = mapFromGlobal(globalPosition);
|
||||
if (updateReorderPinned(local)) {
|
||||
|
@ -1687,16 +1737,16 @@ void InnerWidget::selectByMouse(QPoint globalPosition) {
|
|||
const auto mappedY = selected ? mouseY - offset - selected->top() : 0;
|
||||
const auto selectedTopicJump = selected
|
||||
&& selected->lookupIsInTopicJump(local.x(), mappedY);
|
||||
const auto selectedBotApp = selected
|
||||
const auto selectedRightButton = selected
|
||||
&& lookupIsInBotAppButton(selected, QPoint(local.x(), mappedY));
|
||||
if (_collapsedSelected != collapsedSelected
|
||||
|| _selected != selected
|
||||
|| _selectedTopicJump != selectedTopicJump
|
||||
|| _selectedBotApp != selectedBotApp) {
|
||||
|| _selectedRightButton != selectedRightButton) {
|
||||
updateSelectedRow();
|
||||
_selected = selected;
|
||||
_selectedTopicJump = selectedTopicJump;
|
||||
_selectedBotApp = selectedBotApp;
|
||||
_selectedRightButton = selectedRightButton;
|
||||
_collapsedSelected = collapsedSelected;
|
||||
updateSelectedRow();
|
||||
setCursor((_selected || _collapsedSelected >= 0)
|
||||
|
@ -1736,29 +1786,39 @@ void InnerWidget::selectByMouse(QPoint globalPosition) {
|
|||
&& _filterResults[filteredSelected].row->lookupIsInTopicJump(
|
||||
local.x(),
|
||||
mappedY);
|
||||
const auto selectedBotApp = (filteredSelected >= 0)
|
||||
const auto selectedRightButton = (filteredSelected >= 0)
|
||||
&& lookupIsInBotAppButton(
|
||||
_filterResults[filteredSelected].row,
|
||||
QPoint(local.x(), mappedY));
|
||||
if (_filteredSelected != filteredSelected
|
||||
|| _selectedTopicJump != selectedTopicJump
|
||||
|| _selectedBotApp != selectedBotApp) {
|
||||
|| _selectedRightButton != selectedRightButton) {
|
||||
updateSelectedRow();
|
||||
_filteredSelected = filteredSelected;
|
||||
_selectedTopicJump = selectedTopicJump;
|
||||
_selectedBotApp = selectedBotApp;
|
||||
_selectedRightButton = selectedRightButton;
|
||||
updateSelectedRow();
|
||||
}
|
||||
}
|
||||
if (!_peerSearchResults.empty()) {
|
||||
auto skip = peerSearchOffset();
|
||||
const auto skip = peerSearchOffset();
|
||||
auto peerSearchSelected = (mouseY >= skip) ? ((mouseY - skip) / st::dialogsRowHeight) : -1;
|
||||
if (peerSearchSelected < 0 || peerSearchSelected >= _peerSearchResults.size()) {
|
||||
peerSearchSelected = -1;
|
||||
}
|
||||
if (_peerSearchSelected != peerSearchSelected) {
|
||||
const auto mappedY = (peerSearchSelected >= 0)
|
||||
? mouseY - skip - (peerSearchSelected * st::dialogsRowHeight)
|
||||
: 0;
|
||||
const auto selectedRightButton = (peerSearchSelected >= 0)
|
||||
&& _peerSearchResults[peerSearchSelected]->sponsored
|
||||
&& lookupIsInRightButton(
|
||||
_peerSearchResults[peerSearchSelected]->sponsored->button,
|
||||
QPoint(local.x(), mappedY));
|
||||
if (_peerSearchSelected != peerSearchSelected
|
||||
|| _selectedRightButton != selectedRightButton) {
|
||||
updateSelectedRow();
|
||||
_peerSearchSelected = peerSearchSelected;
|
||||
_selectedRightButton = selectedRightButton;
|
||||
updateSelectedRow();
|
||||
}
|
||||
}
|
||||
|
@ -1845,12 +1905,15 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
|
|||
selectByMouse(e->globalPos());
|
||||
|
||||
_pressButton = e->button();
|
||||
setPressed(_selected, _selectedTopicJump, _selectedBotApp);
|
||||
setPressed(_selected, _selectedTopicJump, _selectedRightButton);
|
||||
setCollapsedPressed(_collapsedSelected);
|
||||
setHashtagPressed(_hashtagSelected);
|
||||
_hashtagDeletePressed = _hashtagDeleteSelected;
|
||||
setFilteredPressed(_filteredSelected, _selectedTopicJump, _selectedBotApp);
|
||||
setPeerSearchPressed(_peerSearchSelected);
|
||||
setFilteredPressed(
|
||||
_filteredSelected,
|
||||
_selectedTopicJump,
|
||||
_selectedRightButton);
|
||||
setPeerSearchPressed(_peerSearchSelected, _selectedRightButton);
|
||||
setPreviewPressed(_previewSelected);
|
||||
setSearchedPressed(_searchedSelected);
|
||||
_pressedMorePosts = _selectedMorePosts;
|
||||
|
@ -1881,7 +1944,7 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
|
|||
- QPoint(0, dialogsOffset() + _pressed->top());
|
||||
if ((_pressButton == Qt::MiddleButton)
|
||||
&& addQuickActionRipple(row, updateCallback)) {
|
||||
} else if (addBotAppRipple(origin, updateCallback)) {
|
||||
} else if (addRightButtonRipple(origin, updateCallback)) {
|
||||
} else if (_pressedTopicJump) {
|
||||
row->addTopicJumpRipple(
|
||||
origin,
|
||||
|
@ -1908,7 +1971,7 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
|
|||
const auto origin = e->pos()
|
||||
- QPoint(0, filteredOffset() + result.top);
|
||||
const auto updateCallback = [=] { repaintDialogRow(filterId, row); };
|
||||
if (addBotAppRipple(origin, updateCallback)) {
|
||||
if (addRightButtonRipple(origin, updateCallback)) {
|
||||
} else if (_pressedTopicJump) {
|
||||
row->addTopicJumpRipple(
|
||||
origin,
|
||||
|
@ -1923,11 +1986,19 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
|
|||
}
|
||||
} else if (base::in_range(_peerSearchPressed, 0, _peerSearchResults.size())) {
|
||||
auto &result = _peerSearchResults[_peerSearchPressed];
|
||||
auto row = &result->row;
|
||||
row->addRipple(
|
||||
e->pos() - QPoint(0, peerSearchOffset() + _peerSearchPressed * st::dialogsRowHeight),
|
||||
QSize(width(), st::dialogsRowHeight),
|
||||
[this, peer = result->peer] { updateSearchResult(peer); });
|
||||
const auto row = &result->row;
|
||||
const auto origin = e->pos()
|
||||
- QPoint(0, peerSearchOffset() + _peerSearchPressed * st::dialogsRowHeight);
|
||||
const auto updateCallback = [this, peer = result->peer] {
|
||||
updateSearchResult(peer);
|
||||
};
|
||||
if (addRightButtonRipple(origin, updateCallback)) {
|
||||
} else {
|
||||
row->addRipple(
|
||||
origin,
|
||||
QSize(width(), st::dialogsRowHeight),
|
||||
updateCallback);
|
||||
}
|
||||
} else if (base::in_range(_searchedPressed, 0, _searchResults.size())) {
|
||||
auto &row = _searchResults[_searchedPressed];
|
||||
row->addRipple(
|
||||
|
@ -1943,22 +2014,22 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
bool InnerWidget::addBotAppRipple(QPoint origin, Fn<void()> updateCallback) {
|
||||
if (!(_pressedBotApp && _pressedBotAppData)) {
|
||||
bool InnerWidget::addRightButtonRipple(QPoint origin, Fn<void()> updateCallback) {
|
||||
if (!(_pressedRightButton && _pressedRightButtonData)) {
|
||||
return false;
|
||||
}
|
||||
const auto size = _pressedBotAppData->bg.size()
|
||||
const auto size = _pressedRightButtonData->bg.size()
|
||||
/ style::DevicePixelRatio();
|
||||
if (!_pressedBotAppData->ripple) {
|
||||
_pressedBotAppData->ripple = std::make_unique<Ui::RippleAnimation>(
|
||||
st::defaultRippleAnimation,
|
||||
if (!_pressedRightButtonData->ripple) {
|
||||
_pressedRightButtonData->ripple = std::make_unique<Ui::RippleAnimation>(
|
||||
_pressedRightButtonData->st->button.ripple,
|
||||
Ui::RippleAnimation::RoundRectMask(size, size.height() / 2),
|
||||
std::move(updateCallback));
|
||||
}
|
||||
const auto shift = QPoint(
|
||||
width() - size.width() - st::dialogRowOpenBotRight,
|
||||
st::dialogRowOpenBotTop);
|
||||
_pressedBotAppData->ripple->add(origin - shift);
|
||||
width() - size.width() - _pressedRightButtonData->st->margin.right(),
|
||||
_pressedRightButtonData->st->margin.top());
|
||||
_pressedRightButtonData->ripple->add(origin - shift);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2051,7 +2122,7 @@ void InnerWidget::checkReorderPinnedStart(QPoint localPosition) {
|
|||
if (!_pressed
|
||||
|| _dragging
|
||||
|| (_state != WidgetState::Default)
|
||||
|| _pressedBotApp) {
|
||||
|| _pressedRightButtonData) {
|
||||
return;
|
||||
} else if (qAbs(localPosition.y() - _dragStart.y())
|
||||
< style::ConvertScale(kStartReorderThreshold)) {
|
||||
|
@ -2321,7 +2392,7 @@ void InnerWidget::mousePressReleased(
|
|||
setCollapsedPressed(-1);
|
||||
const auto pressedTopicRootId = _pressedTopicJumpRootId;
|
||||
const auto pressedTopicJump = _pressedTopicJump;
|
||||
const auto pressedBotApp = _pressedBotApp;
|
||||
const auto pressedRightButton = _pressedRightButton;
|
||||
auto pressed = _pressed;
|
||||
clearPressed();
|
||||
auto hashtagPressed = _hashtagPressed;
|
||||
|
@ -2331,7 +2402,7 @@ void InnerWidget::mousePressReleased(
|
|||
auto filteredPressed = _filteredPressed;
|
||||
setFilteredPressed(-1, false, false);
|
||||
auto peerSearchPressed = _peerSearchPressed;
|
||||
setPeerSearchPressed(-1);
|
||||
setPeerSearchPressed(-1, false);
|
||||
auto previewPressed = _previewPressed;
|
||||
setPreviewPressed(-1);
|
||||
auto searchedPressed = _searchedPressed;
|
||||
|
@ -2343,8 +2414,8 @@ void InnerWidget::mousePressReleased(
|
|||
if (wasDragging) {
|
||||
selectByMouse(globalPosition);
|
||||
}
|
||||
if (_pressedBotAppData && _pressedBotAppData->ripple) {
|
||||
_pressedBotAppData->ripple->lastStop();
|
||||
if (_pressedRightButtonData && _pressedRightButtonData->ripple) {
|
||||
_pressedRightButtonData->ripple->lastStop();
|
||||
}
|
||||
if (_activeQuickAction && pressed && !_activeQuickAction->data) {
|
||||
if (const auto history = pressed->history()) {
|
||||
|
@ -2372,13 +2443,14 @@ void InnerWidget::mousePressReleased(
|
|||
|| (pressed
|
||||
&& pressed == _selected
|
||||
&& pressedTopicJump == _selectedTopicJump
|
||||
&& pressedBotApp == _selectedBotApp)
|
||||
&& pressedRightButton == _selectedRightButton)
|
||||
|| (hashtagPressed >= 0
|
||||
&& hashtagPressed == _hashtagSelected
|
||||
&& hashtagDeletePressed == _hashtagDeleteSelected)
|
||||
|| (filteredPressed >= 0 && filteredPressed == _filteredSelected)
|
||||
|| (peerSearchPressed >= 0
|
||||
&& peerSearchPressed == _peerSearchSelected)
|
||||
&& peerSearchPressed == _peerSearchSelected
|
||||
&& pressedRightButton == _selectedRightButton)
|
||||
|| (previewPressed >= 0
|
||||
&& previewPressed == _previewSelected)
|
||||
|| (searchedPressed >= 0
|
||||
|
@ -2387,13 +2459,15 @@ void InnerWidget::mousePressReleased(
|
|||
&& pressedMorePosts == _selectedMorePosts)
|
||||
|| (pressedChatTypeFilter
|
||||
&& pressedChatTypeFilter == _selectedChatTypeFilter)) {
|
||||
if (pressedBotApp && (pressed || filteredPressed >= 0)) {
|
||||
if (pressedRightButton && (pressed || filteredPressed >= 0)) {
|
||||
const auto &row = pressed
|
||||
? pressed
|
||||
: _filterResults[filteredPressed].row.get();
|
||||
if (const auto user = MaybeBotWithApp(row)) {
|
||||
_openBotMainAppRequests.fire(peerToUser(user->id));
|
||||
}
|
||||
} else if (pressedRightButton && peerSearchPressed >= 0) {
|
||||
showSponsoredMenu(peerSearchPressed, globalPosition);
|
||||
} else {
|
||||
chooseRow(modifiers, pressedTopicRootId);
|
||||
}
|
||||
|
@ -2420,25 +2494,25 @@ void InnerWidget::setCollapsedPressed(int pressed) {
|
|||
void InnerWidget::setPressed(
|
||||
Row *pressed,
|
||||
bool pressedTopicJump,
|
||||
bool pressedBotApp) {
|
||||
bool pressedRightButton) {
|
||||
if ((_pressed != pressed)
|
||||
|| (pressed && _pressedTopicJump != pressedTopicJump)
|
||||
|| (pressed && _pressedBotApp != pressedBotApp)) {
|
||||
|| (pressed && _pressedRightButton != pressedRightButton)) {
|
||||
if (_pressed) {
|
||||
_pressed->stopLastRipple();
|
||||
}
|
||||
if (_pressedBotAppData && _pressedBotAppData->ripple) {
|
||||
_pressedBotAppData->ripple->lastStop();
|
||||
if (_pressedRightButtonData && _pressedRightButtonData->ripple) {
|
||||
_pressedRightButtonData->ripple->lastStop();
|
||||
}
|
||||
_pressed = pressed;
|
||||
if (pressed || !pressedTopicJump || !pressedBotApp) {
|
||||
if (pressed || !pressedTopicJump || !pressedRightButton) {
|
||||
_pressedTopicJump = pressedTopicJump;
|
||||
_pressedBotApp = pressedBotApp;
|
||||
if (pressedBotApp) {
|
||||
_pressedRightButton = pressedRightButton;
|
||||
if (pressedRightButton) {
|
||||
if (const auto user = MaybeBotWithApp(pressed)) {
|
||||
const auto it = _rightButtons.find(user->id);
|
||||
if (it != _rightButtons.end()) {
|
||||
_pressedBotAppData = &(it->second);
|
||||
_pressedRightButtonData = &(it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2465,26 +2539,26 @@ void InnerWidget::setHashtagPressed(int pressed) {
|
|||
void InnerWidget::setFilteredPressed(
|
||||
int pressed,
|
||||
bool pressedTopicJump,
|
||||
bool pressedBotApp) {
|
||||
bool pressedRightButton) {
|
||||
if (_filteredPressed != pressed
|
||||
|| (pressed >= 0 && _pressedTopicJump != pressedTopicJump)
|
||||
|| (pressed >= 0 && _pressedBotApp != pressedBotApp)) {
|
||||
|| (pressed >= 0 && _pressedRightButton != pressedRightButton)) {
|
||||
if (base::in_range(_filteredPressed, 0, _filterResults.size())) {
|
||||
_filterResults[_filteredPressed].row->stopLastRipple();
|
||||
}
|
||||
if (_pressedBotAppData && _pressedBotAppData->ripple) {
|
||||
_pressedBotAppData->ripple->lastStop();
|
||||
if (_pressedRightButtonData && _pressedRightButtonData->ripple) {
|
||||
_pressedRightButtonData->ripple->lastStop();
|
||||
}
|
||||
_filteredPressed = pressed;
|
||||
if (pressed >= 0 || !pressedTopicJump || !pressedBotApp) {
|
||||
if (pressed >= 0 || !pressedTopicJump || !pressedRightButton) {
|
||||
_pressedTopicJump = pressedTopicJump;
|
||||
_pressedBotApp = pressedBotApp;
|
||||
if (pressed >= 0 && pressedBotApp) {
|
||||
_pressedRightButton = pressedRightButton;
|
||||
if (pressed >= 0 && pressedRightButton) {
|
||||
const auto &row = _filterResults[pressed].row;
|
||||
if (const auto history = row->history()) {
|
||||
const auto it = _rightButtons.find(history->peer->id);
|
||||
if (it != _rightButtons.end()) {
|
||||
_pressedBotAppData = &(it->second);
|
||||
_pressedRightButtonData = &(it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2497,11 +2571,26 @@ void InnerWidget::setFilteredPressed(
|
|||
}
|
||||
}
|
||||
|
||||
void InnerWidget::setPeerSearchPressed(int pressed) {
|
||||
if (base::in_range(_peerSearchPressed, 0, _peerSearchResults.size())) {
|
||||
_peerSearchResults[_peerSearchPressed]->row.stopLastRipple();
|
||||
void InnerWidget::setPeerSearchPressed(int pressed, bool pressedRightButton) {
|
||||
if (_peerSearchPressed != pressed
|
||||
|| (pressed >= 0 && _pressedRightButton != pressedRightButton)) {
|
||||
if (base::in_range(_peerSearchPressed, 0, _peerSearchResults.size())) {
|
||||
_peerSearchResults[_peerSearchPressed]->row.stopLastRipple();
|
||||
}
|
||||
if (_pressedRightButtonData && _pressedRightButtonData->ripple) {
|
||||
_pressedRightButtonData->ripple->lastStop();
|
||||
}
|
||||
_peerSearchPressed = pressed;
|
||||
if (pressed >= 0 || !pressedRightButton) {
|
||||
_pressedRightButton = pressedRightButton;
|
||||
if (pressed >= 0 && pressedRightButton) {
|
||||
const auto &entry = _peerSearchResults[pressed];
|
||||
if (entry->sponsored) {
|
||||
_pressedRightButtonData = &entry->sponsored->button;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_peerSearchPressed = pressed;
|
||||
}
|
||||
|
||||
void InnerWidget::setPreviewPressed(int pressed) {
|
||||
|
@ -2564,7 +2653,7 @@ void InnerWidget::dialogRowReplaced(
|
|||
_selected = newRow;
|
||||
}
|
||||
if (_pressed == oldRow) {
|
||||
setPressed(newRow, _pressedTopicJump, _pressedBotApp);
|
||||
setPressed(newRow, _pressedTopicJump, _pressedRightButton);
|
||||
}
|
||||
if (_dragging == oldRow) {
|
||||
if (newRow) {
|
||||
|
@ -3081,6 +3170,62 @@ void InnerWidget::contextMenuEvent(QContextMenuEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
void InnerWidget::showSponsoredMenu(int peerSearchIndex, QPoint globalPos) {
|
||||
_menu = nullptr;
|
||||
|
||||
const auto count = int(_peerSearchResults.size());
|
||||
const auto entry = (peerSearchIndex >= 0 && peerSearchIndex < count)
|
||||
? _peerSearchResults[peerSearchIndex].get()
|
||||
: nullptr;
|
||||
if (!entry || !entry->sponsored) {
|
||||
return;
|
||||
}
|
||||
|
||||
_peerSearchMenu = peerSearchIndex;
|
||||
_menu = base::make_unique_q<Ui::PopupMenu>(
|
||||
this,
|
||||
st::popupMenuExpandedSeparator);
|
||||
const auto peer = entry->peer;
|
||||
const auto remove = crl::guard(this, [=] {
|
||||
_sponsoredRemoved.emplace(peer);
|
||||
_peerSearchResults.erase(
|
||||
ranges::remove(
|
||||
_peerSearchResults,
|
||||
peer,
|
||||
&PeerSearchResult::peer),
|
||||
end(_peerSearchResults));
|
||||
refresh();
|
||||
});
|
||||
Menu::FillSponsored(
|
||||
this,
|
||||
Ui::Menu::CreateAddActionCallback(_menu),
|
||||
_controller->uiShow(),
|
||||
Menu::SponsoredPhrases::Search,
|
||||
session().sponsoredMessages().lookupDetails(entry->sponsored->data),
|
||||
session().sponsoredMessages().createReportCallback(
|
||||
entry->sponsored->data.randomId,
|
||||
remove),
|
||||
false,
|
||||
false);
|
||||
QObject::connect(_menu.get(), &QObject::destroyed, [=] {
|
||||
if (_peerSearchMenu >= 0
|
||||
&& _peerSearchMenu < _peerSearchResults.size()) {
|
||||
const auto index = std::exchange(_peerSearchMenu, -1);
|
||||
updateSearchResult(_peerSearchResults[index]->peer);
|
||||
}
|
||||
const auto globalPosition = QCursor::pos();
|
||||
if (rect().contains(mapFromGlobal(globalPosition))) {
|
||||
setMouseTracking(true);
|
||||
selectByMouse(globalPosition);
|
||||
}
|
||||
});
|
||||
if (_menu->empty()) {
|
||||
_menu = nullptr;
|
||||
} else {
|
||||
_menu->popup(globalPos);
|
||||
}
|
||||
}
|
||||
|
||||
void InnerWidget::parentGeometryChanged() {
|
||||
const auto globalPosition = QCursor::pos();
|
||||
if (rect().contains(mapFromGlobal(globalPosition))) {
|
||||
|
@ -3362,14 +3507,23 @@ InnerWidget::~InnerWidget() {
|
|||
clearSearchResults();
|
||||
}
|
||||
|
||||
void InnerWidget::clearSearchResults(bool clearPeerSearchResults) {
|
||||
if (clearPeerSearchResults) {
|
||||
_peerSearchResults.clear();
|
||||
void InnerWidget::clearSearchResults(bool alsoPeerSearchResults) {
|
||||
if (alsoPeerSearchResults) {
|
||||
clearPeerSearchResults();
|
||||
}
|
||||
_searchResults.clear();
|
||||
_searchedCount = _searchedMigratedCount = 0;
|
||||
}
|
||||
|
||||
void InnerWidget::clearPeerSearchResults() {
|
||||
_peerSearchResults.clear();
|
||||
if (_pressedRightButtonSponsored) {
|
||||
_pressedRightButtonData = nullptr;
|
||||
_pressedRightButtonSponsored = false;
|
||||
_pressedRightButton = false;
|
||||
}
|
||||
}
|
||||
|
||||
void InnerWidget::clearPreviewResults() {
|
||||
_previewResults.clear();
|
||||
_previewCount = 0;
|
||||
|
@ -3691,7 +3845,7 @@ void InnerWidget::peerSearchReceived(Api::PeerSearchResult result) {
|
|||
}
|
||||
|
||||
_peerSearchQuery = result.query.toLower().trimmed();
|
||||
_peerSearchResults.clear();
|
||||
clearPeerSearchResults();
|
||||
_peerSearchResults.reserve(result.peers.size()
|
||||
+ result.sponsored.size());
|
||||
for (const auto &peer : result.my) {
|
||||
|
@ -3706,14 +3860,17 @@ void InnerWidget::peerSearchReceived(Api::PeerSearchResult result) {
|
|||
};
|
||||
auto added = base::flat_set<not_null<PeerData*>>();
|
||||
for (const auto &sponsored : result.sponsored) {
|
||||
if (inlist(sponsored.peer)) {
|
||||
const auto peer = sponsored.peer;
|
||||
if (inlist(peer) || _sponsoredRemoved.contains(peer)) {
|
||||
continue;
|
||||
}
|
||||
_peerSearchResults.push_back(
|
||||
std::make_unique<PeerSearchResult>(sponsored.peer));
|
||||
std::make_unique<PeerSearchResult>(peer));
|
||||
_peerSearchResults.back()->sponsored
|
||||
= std::make_unique<Api::SponsoredSearchResult>(sponsored);
|
||||
added.emplace(sponsored.peer);
|
||||
= std::make_unique<SponsoredSearchResult>(SponsoredSearchResult{
|
||||
.data = sponsored,
|
||||
});
|
||||
added.emplace(peer);
|
||||
}
|
||||
for (const auto &peer : result.peers) {
|
||||
if (added.contains(peer) || inlist(peer)) {
|
||||
|
@ -4054,7 +4211,7 @@ void InnerWidget::clearFilter() {
|
|||
_hashtagResults.clear();
|
||||
_filterResults.clear();
|
||||
_filterResultsGlobal.clear();
|
||||
_peerSearchResults.clear();
|
||||
clearPeerSearchResults();
|
||||
_searchResults.clear();
|
||||
_previewResults.clear();
|
||||
_trackedHistories.clear();
|
||||
|
@ -4515,7 +4672,7 @@ ChosenRow InnerWidget::computeChosenRow() const {
|
|||
.key = session().data().history(row->peer),
|
||||
.message = Data::UnreadMessagePosition,
|
||||
.sponsoredRandomId = (row->sponsored
|
||||
? row->sponsored->randomId
|
||||
? row->sponsored->data.randomId
|
||||
: QByteArray()),
|
||||
};
|
||||
} else if (base::in_range(_previewSelected, 0, _previewResults.size())) {
|
||||
|
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace style {
|
||||
struct DialogRow;
|
||||
struct DialogRightButton;
|
||||
} // namespace style
|
||||
|
||||
namespace Api {
|
||||
|
@ -242,6 +243,7 @@ protected:
|
|||
private:
|
||||
struct CollapsedRow;
|
||||
struct HashtagResult;
|
||||
struct SponsoredSearchResult;
|
||||
struct PeerSearchResult;
|
||||
struct TagCache;
|
||||
|
||||
|
@ -299,6 +301,7 @@ private:
|
|||
void repaintDialogRow(RowDescriptor row);
|
||||
void refreshDialogRow(RowDescriptor row);
|
||||
bool updateEntryHeight(not_null<Entry*> entry);
|
||||
void showSponsoredMenu(int peerSearchIndex, QPoint globalPos);
|
||||
|
||||
void clearMouseSelection(bool clearSelection = false);
|
||||
void mousePressReleased(
|
||||
|
@ -312,14 +315,17 @@ private:
|
|||
void scrollToItem(int top, int height);
|
||||
void scrollToDefaultSelected();
|
||||
void setCollapsedPressed(int pressed);
|
||||
void setPressed(Row *pressed, bool pressedTopicJump, bool pressedBotApp);
|
||||
void setPressed(
|
||||
Row *pressed,
|
||||
bool pressedTopicJump,
|
||||
bool pressedRightButton);
|
||||
void clearPressed();
|
||||
void setHashtagPressed(int pressed);
|
||||
void setFilteredPressed(
|
||||
int pressed,
|
||||
bool pressedTopicJump,
|
||||
bool pressedBotApp);
|
||||
void setPeerSearchPressed(int pressed);
|
||||
bool pressedRightButton);
|
||||
void setPeerSearchPressed(int pressed, bool pressedRightButton);
|
||||
void setPreviewPressed(int pressed);
|
||||
void setSearchedPressed(int pressed);
|
||||
bool isPressed() const {
|
||||
|
@ -357,6 +363,8 @@ private:
|
|||
bool addBotAppRipple(QPoint origin, Fn<void()> updateCallback);
|
||||
bool addQuickActionRipple(not_null<Row*> row, Fn<void()> updateCallback);
|
||||
|
||||
bool addRightButtonRipple(QPoint origin, Fn<void()> updateCallback);
|
||||
|
||||
void setupShortcuts();
|
||||
RowDescriptor computeJump(
|
||||
const RowDescriptor &to,
|
||||
|
@ -459,7 +467,8 @@ private:
|
|||
Ui::VideoUserpic *validateVideoUserpic(not_null<History*> history);
|
||||
|
||||
Row *shownRowByKey(Key key);
|
||||
void clearSearchResults(bool clearPeerSearchResults = true);
|
||||
void clearSearchResults(bool alsoPeerSearchResults = true);
|
||||
void clearPeerSearchResults();
|
||||
void clearPreviewResults();
|
||||
void updateSelectedRow(Key key = Key());
|
||||
void trackResultsHistory(not_null<History*> history);
|
||||
|
@ -493,7 +502,14 @@ private:
|
|||
[[nodiscard]] bool lookupIsInBotAppButton(
|
||||
Row *row,
|
||||
QPoint localPosition);
|
||||
[[nodiscard]] bool lookupIsInRightButton(
|
||||
const RightButton &button,
|
||||
QPoint localPosition);
|
||||
[[nodiscard]] RightButton *maybeCacheRightButton(Row *row);
|
||||
void fillRightButton(
|
||||
RightButton &button,
|
||||
const TextWithEntities &text,
|
||||
const style::DialogRightButton &st);
|
||||
|
||||
[[nodiscard]] QImage *cacheChatsFilterTag(
|
||||
const Data::ChatFilter &filter,
|
||||
|
@ -529,9 +545,10 @@ private:
|
|||
bool _selectedTopicJump = false;
|
||||
bool _pressedTopicJump = false;
|
||||
|
||||
RightButton *_pressedBotAppData = nullptr;
|
||||
bool _selectedBotApp = false;
|
||||
bool _pressedBotApp = false;
|
||||
RightButton *_pressedRightButtonData = nullptr;
|
||||
bool _pressedRightButtonSponsored = false;
|
||||
bool _selectedRightButton = false;
|
||||
bool _pressedRightButton = false;
|
||||
|
||||
Row *_dragging = nullptr;
|
||||
int _draggingIndex = -1;
|
||||
|
@ -566,9 +583,11 @@ private:
|
|||
rpl::lifetime _trackedLifetime;
|
||||
|
||||
QString _peerSearchQuery;
|
||||
base::flat_set<not_null<PeerData*>> _sponsoredRemoved;
|
||||
std::vector<std::unique_ptr<PeerSearchResult>> _peerSearchResults;
|
||||
int _peerSearchSelected = -1;
|
||||
int _peerSearchPressed = -1;
|
||||
int _peerSearchMenu = -1;
|
||||
|
||||
std::vector<std::unique_ptr<FakeRow>> _previewResults;
|
||||
int _previewCount = 0;
|
||||
|
|
|
@ -835,7 +835,10 @@ void Widget::setupSwipeBack() {
|
|||
void Widget::chosenRow(const ChosenRow &row) {
|
||||
storiesToggleExplicitExpand(false);
|
||||
|
||||
if (!_searchState.query.isEmpty()) {
|
||||
if (!row.sponsoredRandomId.isEmpty()) {
|
||||
auto &messages = session().sponsoredMessages();
|
||||
messages.clicked(row.sponsoredRandomId, false, false);
|
||||
} else if (!_searchState.query.isEmpty()) {
|
||||
if (const auto history = row.key.history()) {
|
||||
session().recentPeers().bump(history->peer);
|
||||
}
|
||||
|
@ -846,11 +849,6 @@ void Widget::chosenRow(const ChosenRow &row) {
|
|||
? history->peer->forumTopicFor(row.message.fullId.msg)
|
||||
: nullptr;
|
||||
|
||||
if (!row.sponsoredRandomId.isEmpty()) {
|
||||
auto &messages = session().sponsoredMessages();
|
||||
messages.clicked(row.sponsoredRandomId, false, false);
|
||||
}
|
||||
|
||||
if (topicJump) {
|
||||
if (controller()->shownForum().current() == topicJump->forum()) {
|
||||
controller()->closeForum();
|
||||
|
|
|
@ -125,16 +125,18 @@ void PaintRowTopRight(
|
|||
text);
|
||||
}
|
||||
|
||||
int PaintRightButton(QPainter &p, const PaintContext &context) {
|
||||
int PaintRightButtonImpl(QPainter &p, const PaintContext &context) {
|
||||
if (context.width < st::columnMinimalWidthLeft) {
|
||||
return 0;
|
||||
}
|
||||
if (const auto rightButton = context.rightButton) {
|
||||
Assert(rightButton->st != nullptr);
|
||||
|
||||
const auto size = rightButton->bg.size() / style::DevicePixelRatio();
|
||||
const auto left = context.width
|
||||
- size.width()
|
||||
- st::dialogRowOpenBotRight;
|
||||
const auto top = st::dialogRowOpenBotTop;
|
||||
- rightButton->st->margin.right();
|
||||
const auto top = rightButton->st->margin.top();
|
||||
p.drawImage(
|
||||
left,
|
||||
top,
|
||||
|
@ -149,22 +151,22 @@ int PaintRightButton(QPainter &p, const PaintContext &context) {
|
|||
left,
|
||||
top,
|
||||
size.width() - size.height() / 2,
|
||||
context.active
|
||||
(context.active
|
||||
? &st::universalRippleAnimation.color->c
|
||||
: &st::activeButtonBgRipple->c);
|
||||
: &rightButton->st->button.ripple.color->c));
|
||||
if (rightButton->ripple->empty()) {
|
||||
rightButton->ripple.reset();
|
||||
}
|
||||
}
|
||||
p.setPen(context.active
|
||||
? st::activeButtonBg
|
||||
? rightButton->st->button.textBg
|
||||
: context.selected
|
||||
? st::activeButtonFgOver
|
||||
: st::activeButtonFg);
|
||||
? rightButton->st->button.textFgOver
|
||||
: rightButton->st->button.textFg);
|
||||
rightButton->text.draw(p, {
|
||||
.position = QPoint(
|
||||
left + size.height() / 2,
|
||||
top + (st::dialogRowOpenBotHeight - rightButton->text.minHeight()) / 2),
|
||||
top + rightButton->st->button.textTop),
|
||||
.outerWidth = size.width() - size.height() / 2,
|
||||
.availableWidth = size.width() - size.height() / 2,
|
||||
.elisionLines = 1,
|
||||
|
@ -1285,4 +1287,8 @@ void PaintCollapsedRow(
|
|||
}
|
||||
}
|
||||
|
||||
int PaintRightButton(QPainter &p, const PaintContext &context) {
|
||||
return PaintRightButtonImpl(p, context);
|
||||
}
|
||||
|
||||
} // namespace Dialogs::Ui
|
||||
|
|
|
@ -110,4 +110,6 @@ void PaintCollapsedRow(
|
|||
int unread,
|
||||
const PaintContext &context);
|
||||
|
||||
int PaintRightButton(QPainter &p, const PaintContext &context);
|
||||
|
||||
} // namespace Dialogs::Ui
|
||||
|
|
|
@ -204,7 +204,7 @@ RecentRow::RecentRow(not_null<PeerData*> peer)
|
|||
if (const auto user = peer->asUser()) {
|
||||
if (user->botInfo && user->botInfo->hasMainApp) {
|
||||
return std::make_unique<Ui::Text::String>(
|
||||
st::dialogRowOpenBotTextStyle,
|
||||
st::dialogRowOpenBotRecent.button.style,
|
||||
tr::lng_profile_open_app_short(tr::now));
|
||||
}
|
||||
}
|
||||
|
@ -275,20 +275,15 @@ QSize RecentRow::rightActionSize() const {
|
|||
if (_mainAppText && _badgeSize.isEmpty()) {
|
||||
return QSize(
|
||||
_mainAppText->maxWidth() + _mainAppText->minHeight(),
|
||||
st::dialogRowOpenBotHeight);
|
||||
st::dialogRowOpenBotRecent.button.height);
|
||||
}
|
||||
return _badgeSize;
|
||||
}
|
||||
|
||||
QMargins RecentRow::rightActionMargins() const {
|
||||
if (_mainAppText && _badgeSize.isEmpty()) {
|
||||
return QMargins(
|
||||
0,
|
||||
st::dialogRowOpenBotRecentTop,
|
||||
st::dialogRowOpenBotRight,
|
||||
0);
|
||||
}
|
||||
if (_badgeSize.isEmpty()) {
|
||||
return st::dialogRowOpenBotRecent.margin;
|
||||
} else if (_badgeSize.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
const auto x = st::recentPeersItem.photoPosition.x();
|
||||
|
@ -321,8 +316,7 @@ void RecentRow::rightActionPaint(
|
|||
p.setPen(actionSelected
|
||||
? st::activeButtonFgOver
|
||||
: st::activeButtonFg);
|
||||
const auto top = 0
|
||||
+ (st::dialogRowOpenBotHeight - _mainAppText->minHeight()) / 2;
|
||||
const auto top = st::dialogRowOpenBotRecent.button.textTop;
|
||||
_mainAppText->draw(p, {
|
||||
.position = QPoint(x + size.height() / 2, y + top),
|
||||
.outerWidth = outerWidth,
|
||||
|
|
|
@ -699,7 +699,8 @@ ClickHandlerPtr HideSponsoredClickHandler() {
|
|||
if (session.premium()) {
|
||||
using Result = Data::SponsoredReportResult;
|
||||
session.sponsoredMessages().createReportCallback(
|
||||
my.itemId)(Result::Id("-1"), [](const auto &) {});
|
||||
my.itemId
|
||||
).callback(Result::Id("-1"), [](const auto &) {});
|
||||
} else {
|
||||
ShowPremiumPreviewBox(controller, PremiumFeature::NoAds);
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ channelEarnFadeDuration: 60;
|
|||
|
||||
channelEarnLearnDescription: FlatLabel(defaultFlatLabel) {
|
||||
maxHeight: 0px;
|
||||
minWidth: 280px;
|
||||
minWidth: 264px;
|
||||
align: align(top);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,15 +42,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Menu {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] SponsoredPhrases PhrasesForMessage(FullMsgId fullId) {
|
||||
return peerIsChannel(fullId.peer)
|
||||
? SponsoredPhrases::Channel
|
||||
: SponsoredPhrases::Bot;
|
||||
}
|
||||
|
||||
void AboutBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const FullMsgId &fullId) {
|
||||
SponsoredPhrases phrases,
|
||||
const Data::SponsoredMessages::Details &details,
|
||||
Data::SponsoredReportAction report) {
|
||||
constexpr auto kUrl = "https://promote.telegram.org"_cs;
|
||||
|
||||
box->setNoContentMargin(true);
|
||||
box->setWidth(st::boxWideWidth);
|
||||
|
||||
const auto isChannel = peerIsChannel(fullId.peer);
|
||||
const auto isChannel = (phrases == SponsoredPhrases::Channel);
|
||||
const auto isSearch = (phrases == SponsoredPhrases::Search);
|
||||
const auto session = &show->session();
|
||||
|
||||
const auto content = box->verticalLayout().get();
|
||||
|
@ -138,20 +147,24 @@ void AboutBox(
|
|||
tr::lng_sponsored_revenued_info1_title(),
|
||||
(isChannel
|
||||
? tr::lng_sponsored_revenued_info1_description
|
||||
: isSearch
|
||||
? tr::lng_sponsored_revenued_info1_search_description
|
||||
: tr::lng_sponsored_revenued_info1_bot_description)(
|
||||
Ui::Text::RichLangValue),
|
||||
st::sponsoredAboutPrivacyIcon);
|
||||
Ui::AddSkip(content);
|
||||
Ui::AddSkip(content);
|
||||
addEntry(
|
||||
(isChannel
|
||||
? tr::lng_sponsored_revenued_info2_title
|
||||
: tr::lng_sponsored_revenued_info2_bot_title)(),
|
||||
(isChannel
|
||||
? tr::lng_sponsored_revenued_info2_description
|
||||
: tr::lng_sponsored_revenued_info2_bot_description)(
|
||||
Ui::Text::RichLangValue),
|
||||
st::sponsoredAboutSplitIcon);
|
||||
if (!isSearch) {
|
||||
Ui::AddSkip(content);
|
||||
Ui::AddSkip(content);
|
||||
addEntry(
|
||||
(isChannel
|
||||
? tr::lng_sponsored_revenued_info2_title
|
||||
: tr::lng_sponsored_revenued_info2_bot_title)(),
|
||||
(isChannel
|
||||
? tr::lng_sponsored_revenued_info2_description
|
||||
: tr::lng_sponsored_revenued_info2_bot_description)(
|
||||
Ui::Text::RichLangValue),
|
||||
st::sponsoredAboutSplitIcon);
|
||||
}
|
||||
Ui::AddSkip(content);
|
||||
Ui::AddSkip(content);
|
||||
auto link = tr::lng_settings_privacy_premium_link(
|
||||
|
@ -160,17 +173,32 @@ void AboutBox(
|
|||
});
|
||||
addEntry(
|
||||
tr::lng_sponsored_revenued_info3_title(),
|
||||
isChannel
|
||||
(isChannel
|
||||
? tr::lng_sponsored_revenued_info3_description(
|
||||
lt_count,
|
||||
rpl::single(float64(levels)),
|
||||
lt_link,
|
||||
std::move(link),
|
||||
Ui::Text::RichLangValue)
|
||||
: isSearch
|
||||
? tr::lng_sponsored_revenued_info3_search_description(
|
||||
lt_link,
|
||||
tr::lng_sponsored_revenued_info3_search_link(
|
||||
lt_arrow,
|
||||
rpl::single(
|
||||
Ui::Text::IconEmoji(&st::textMoreIconEmoji)),
|
||||
Ui::Text::WithEntities
|
||||
) | rpl::map([](TextWithEntities &&link) {
|
||||
return Ui::Text::Wrapped(
|
||||
std::move(link),
|
||||
EntityType::CustomUrl,
|
||||
u"internal:"_q);
|
||||
}),
|
||||
Ui::Text::RichLangValue)
|
||||
: tr::lng_sponsored_revenued_info3_bot_description(
|
||||
lt_link,
|
||||
std::move(link),
|
||||
Ui::Text::RichLangValue),
|
||||
Ui::Text::RichLangValue)),
|
||||
st::sponsoredAboutRemoveIcon)->setClickHandlerFilter([=](
|
||||
const auto &...) {
|
||||
ShowPremiumPreviewBox(show, PremiumFeature::NoAds);
|
||||
|
@ -200,6 +228,8 @@ void AboutBox(
|
|||
content,
|
||||
(isChannel
|
||||
? tr::lng_sponsored_revenued_footer_description
|
||||
: isSearch
|
||||
? tr::lng_sponsored_revenued_footer_search_description
|
||||
: tr::lng_sponsored_revenued_footer_bot_description)(
|
||||
lt_link,
|
||||
tr::lng_channel_earn_about_link(
|
||||
|
@ -256,7 +286,9 @@ void AboutBox(
|
|||
top,
|
||||
Ui::Menu::CreateAddActionCallback(menu->get()),
|
||||
show,
|
||||
fullId,
|
||||
phrases,
|
||||
details,
|
||||
report,
|
||||
false,
|
||||
true);
|
||||
const auto global = top->mapToGlobal(
|
||||
|
@ -269,14 +301,11 @@ void AboutBox(
|
|||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ShowReportSponsoredBox(
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const FullMsgId &fullId) {
|
||||
auto &sponsoredMessages = show->session().sponsoredMessages();
|
||||
const auto report = sponsoredMessages.createReportCallback(fullId);
|
||||
Data::SponsoredReportAction report) {
|
||||
const auto guideLink = Ui::Text::Link(
|
||||
tr::lng_report_sponsored_reported_link(tr::now),
|
||||
u"https://promote.telegram.org/guidelines"_q);
|
||||
|
@ -284,7 +313,7 @@ void ShowReportSponsoredBox(
|
|||
auto performRequest = [=](
|
||||
const auto &repeatRequest,
|
||||
Data::SponsoredReportResult::Id id) -> void {
|
||||
report(id, [=](const Data::SponsoredReportResult &result) {
|
||||
report.callback(id, [=](const Data::SponsoredReportResult &result) {
|
||||
if (!result.error.isEmpty()) {
|
||||
show->showToast(result.error);
|
||||
}
|
||||
|
@ -360,11 +389,12 @@ void FillSponsored(
|
|||
not_null<Ui::RpWidget*> parent,
|
||||
const Ui::Menu::MenuCallback &addAction,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const FullMsgId &fullId,
|
||||
SponsoredPhrases phrases,
|
||||
const Data::SponsoredMessages::Details &details,
|
||||
Data::SponsoredReportAction report,
|
||||
bool mediaViewer,
|
||||
bool skipAbout) {
|
||||
const auto session = &show->session();
|
||||
const auto details = session->sponsoredMessages().lookupDetails(fullId);
|
||||
const auto &info = details.info;
|
||||
|
||||
if (!mediaViewer && !info.empty()) {
|
||||
|
@ -408,12 +438,12 @@ void FillSponsored(
|
|||
if (details.canReport) {
|
||||
if (!skipAbout) {
|
||||
addAction(tr::lng_sponsored_menu_revenued_about(tr::now), [=] {
|
||||
show->show(Box(AboutBox, show, fullId));
|
||||
show->show(Box(AboutBox, show, phrases, details, report));
|
||||
}, (mediaViewer ? &st::mediaMenuIconInfo : &st::menuIconInfo));
|
||||
}
|
||||
|
||||
addAction(tr::lng_sponsored_menu_revenued_report(tr::now), [=] {
|
||||
ShowReportSponsoredBox(show, fullId);
|
||||
ShowReportSponsoredBox(show, report);
|
||||
}, (mediaViewer ? &st::mediaMenuIconBlock : &st::menuIconBlock));
|
||||
|
||||
addAction({
|
||||
|
@ -426,14 +456,32 @@ void FillSponsored(
|
|||
addAction(tr::lng_sponsored_hide_ads(tr::now), [=] {
|
||||
if (session->premium()) {
|
||||
using Result = Data::SponsoredReportResult;
|
||||
session->sponsoredMessages().createReportCallback(
|
||||
fullId)(Result::Id("-1"), [](const auto &) {});
|
||||
report.callback(Result::Id("-1"), [](const auto &) {});
|
||||
} else {
|
||||
ShowPremiumPreviewBox(show, PremiumFeature::NoAds);
|
||||
}
|
||||
}, (mediaViewer ? &st::mediaMenuIconCancel : &st::menuIconCancel));
|
||||
}
|
||||
|
||||
void FillSponsored(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
const Ui::Menu::MenuCallback &addAction,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const FullMsgId &fullId,
|
||||
bool mediaViewer,
|
||||
bool skipAbout) {
|
||||
const auto session = &show->session();
|
||||
FillSponsored(
|
||||
parent,
|
||||
addAction,
|
||||
show,
|
||||
PhrasesForMessage(fullId),
|
||||
session->sponsoredMessages().lookupDetails(fullId),
|
||||
session->sponsoredMessages().createReportCallback(fullId),
|
||||
mediaViewer,
|
||||
skipAbout);
|
||||
}
|
||||
|
||||
void ShowSponsored(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
|
@ -455,8 +503,14 @@ void ShowSponsored(
|
|||
void ShowSponsoredAbout(
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const FullMsgId &fullId) {
|
||||
const auto session = &show->session();
|
||||
show->showBox(Box([=](not_null<Ui::GenericBox*> box) {
|
||||
AboutBox(box, show, fullId);
|
||||
AboutBox(
|
||||
box,
|
||||
show,
|
||||
PhrasesForMessage(fullId),
|
||||
session->sponsoredMessages().lookupDetails(fullId),
|
||||
session->sponsoredMessages().createReportCallback(fullId));
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@ namespace ChatHelpers {
|
|||
class Show;
|
||||
} // namespace ChatHelpers
|
||||
|
||||
namespace Data {
|
||||
struct SponsoredMessageDetails;
|
||||
struct SponsoredReportAction;
|
||||
} // namespace Data
|
||||
|
||||
namespace Ui {
|
||||
class RpWidget;
|
||||
namespace Menu {
|
||||
|
@ -22,6 +27,22 @@ class HistoryItem;
|
|||
|
||||
namespace Menu {
|
||||
|
||||
enum class SponsoredPhrases {
|
||||
Channel,
|
||||
Bot,
|
||||
Search,
|
||||
};
|
||||
|
||||
void FillSponsored(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
const Ui::Menu::MenuCallback &addAction,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
SponsoredPhrases phrases,
|
||||
const Data::SponsoredMessageDetails &details,
|
||||
Data::SponsoredReportAction report,
|
||||
bool mediaViewer,
|
||||
bool skipAbout);
|
||||
|
||||
void FillSponsored(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
const Ui::Menu::MenuCallback &addAction,
|
||||
|
|
Loading…
Add table
Reference in a new issue