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