mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-13 04:37:11 +02:00
Implement required paywalls in tags.
This commit is contained in:
parent
46579ac84d
commit
11cf0486cb
16 changed files with 242 additions and 60 deletions
BIN
Telegram/Resources/icons/dialogs/tags_arrow.png
Normal file
BIN
Telegram/Resources/icons/dialogs/tags_arrow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
Telegram/Resources/icons/dialogs/tags_arrow@2x.png
Normal file
BIN
Telegram/Resources/icons/dialogs/tags_arrow@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 196 B |
BIN
Telegram/Resources/icons/dialogs/tags_arrow@3x.png
Normal file
BIN
Telegram/Resources/icons/dialogs/tags_arrow@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 244 B |
|
@ -2814,8 +2814,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_context_read_hidden" = "read";
|
||||
"lng_context_read_show" = "show when";
|
||||
|
||||
"lng_add_tag_about" = "Tag this message with an emoji for quick search.";
|
||||
"lng_subscribe_tag_about" = "Organize your Saved Messages with tags. {link}";
|
||||
"lng_subscribe_tag_link" = "Learn More...";
|
||||
"lng_edit_tag_about" = "You can label your emoji tag with a text name.";
|
||||
"lng_edit_tag_name" = "Name";
|
||||
"lng_add_tag_button" = "Add tags";
|
||||
"lng_add_tag_phrase" = "to messages {arrow}";
|
||||
"lng_add_tag_phrase_long" = "to your Saved Messages {arrow}";
|
||||
"lng_unlock_tags" = "Unlock";
|
||||
|
||||
"lng_context_animated_emoji" = "This message contains emoji from **{name} pack**.";
|
||||
"lng_context_animated_emoji_many#one" = "This message contains emoji from **{count} pack**.";
|
||||
|
@ -4471,6 +4478,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_stories_channel_archive_done_many#one" = "{count} story is hidden from the channel page.";
|
||||
"lng_stories_channel_archive_done_many#other" = "{count} stories are hidden from the channel page.";
|
||||
"lng_stories_save_promo" = "Subscribe to {link} to download other people's unprotected stories to disk.";
|
||||
"lng_stories_reaction_as_message" = "Send reaction as a private message";
|
||||
|
||||
"lng_stealth_mode_menu_item" = "Stealth Mode";
|
||||
"lng_stealth_mode_title" = "Stealth Mode";
|
||||
|
|
|
@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/boxes/confirm_box.h"
|
||||
#include "boxes/share_box.h"
|
||||
#include "boxes/connection_box.h"
|
||||
#include "boxes/premium_preview_box.h"
|
||||
#include "boxes/sticker_set_box.h"
|
||||
#include "boxes/sessions_box.h"
|
||||
#include "boxes/language_box.h"
|
||||
|
@ -657,6 +658,17 @@ bool CopyPeerId(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ShowSearchTagsPromo(
|
||||
Window::SessionController *controller,
|
||||
const Match &match,
|
||||
const QVariant &context) {
|
||||
if (!controller) {
|
||||
return false;
|
||||
}
|
||||
ShowPremiumPreviewBox(controller, PremiumPreview::TagsForMessages);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExportTestChatTheme(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<const Data::CloudTheme*> theme) {
|
||||
|
@ -1020,6 +1032,10 @@ const std::vector<LocalUrlHandler> &InternalUrlHandlers() {
|
|||
{
|
||||
u"^copy:(.+)$"_q,
|
||||
CopyPeerId
|
||||
},
|
||||
{
|
||||
u"about_tags"_q,
|
||||
ShowSearchTagsPromo
|
||||
}
|
||||
};
|
||||
return Result;
|
||||
|
|
|
@ -626,3 +626,7 @@ searchedBarPosition: point(17px, 7px);
|
|||
|
||||
dialogsSearchTagSkip: point(8px, 4px);
|
||||
dialogsSearchTagBottom: 10px;
|
||||
dialogsSearchTagLocked: icon{{ "emoji/premium_lock", lightButtonFgOver }};
|
||||
dialogsSearchTagPromo: defaultTextStyle;
|
||||
dialogsSearchTagArrow: icon{{ "dialogs/tags_arrow", windowSubTextFg }};
|
||||
dialogsSearchTagArrowPadding: margins(0px, 3px, 0px, 0px);
|
||||
|
|
|
@ -18,8 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "dialogs/dialogs_search_tags.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "core/shortcuts.h"
|
||||
#include "core/application.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "core/shortcuts.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
|
@ -1783,7 +1784,11 @@ void InnerWidget::mousePressReleased(
|
|||
}
|
||||
}
|
||||
if (auto activated = ClickHandler::unpressed()) {
|
||||
ActivateClickHandler(window(), activated, ClickContext{ button });
|
||||
ActivateClickHandler(window(), activated, ClickContext{
|
||||
button,
|
||||
QVariant::fromValue(ClickHandlerContext{
|
||||
.sessionWindow = _controller,
|
||||
}) });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3002,8 +3007,8 @@ void InnerWidget::searchInChat(
|
|||
update(0, searchInChatOffset(), width(), height);
|
||||
}, _searchTags->lifetime());
|
||||
|
||||
_searchTags->heightValue() | rpl::filter(
|
||||
rpl::mappers::_1 > 0
|
||||
_searchTags->heightValue() | rpl::skip(
|
||||
1
|
||||
) | rpl::start_with_next([=] {
|
||||
refresh();
|
||||
moveCancelSearchButtons();
|
||||
|
|
|
@ -8,13 +8,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "dialogs/dialogs_search_tags.h"
|
||||
|
||||
#include "base/qt/qt_key_modifiers.h"
|
||||
#include "boxes/premium_preview_box.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "core/ui_integration.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_message_reactions.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_session.h"
|
||||
#include "history/view/reactions/history_view_reactions.h"
|
||||
#include "main/main_session.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/effects/animation_value.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/power_saving.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
|
||||
|
@ -32,6 +41,45 @@ namespace {
|
|||
return TextUtilities::SingleLine(result);
|
||||
}
|
||||
|
||||
[[nodiscard]] ClickHandlerPtr MakePromoLink() {
|
||||
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
|
||||
const auto my = context.other.value<ClickHandlerContext>();
|
||||
if (const auto controller = my.sessionWindow.get()) {
|
||||
ShowPremiumPreviewBox(
|
||||
controller,
|
||||
PremiumPreview::TagsForMessages);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] Ui::Text::String FillAdditionalText(
|
||||
not_null<Data::Session*> owner,
|
||||
int width) {
|
||||
auto emoji = Ui::Text::SingleCustomEmoji(
|
||||
owner->customEmojiManager().registerInternalEmoji(
|
||||
st::dialogsSearchTagArrow,
|
||||
st::dialogsSearchTagArrowPadding));
|
||||
auto result = Ui::Text::String();
|
||||
const auto context = Core::MarkedTextContext{
|
||||
.session = &owner->session(),
|
||||
.customEmojiRepaint = [] {},
|
||||
.customEmojiLoopLimit = 1,
|
||||
};
|
||||
const auto attempt = [&](const auto &phrase) {
|
||||
result.setMarkedText(
|
||||
st::dialogsSearchTagPromo,
|
||||
phrase(tr::now, lt_arrow, emoji, Ui::Text::WithEntities),
|
||||
kMarkupTextOptions,
|
||||
context);
|
||||
return result.maxWidth() < width;
|
||||
};
|
||||
if (attempt(tr::lng_add_tag_phrase_long)
|
||||
|| attempt(tr::lng_add_tag_phrase)) {
|
||||
return result;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
struct SearchTags::Tag {
|
||||
|
@ -43,6 +91,7 @@ struct SearchTags::Tag {
|
|||
QRect geometry;
|
||||
ClickHandlerPtr link;
|
||||
bool selected = false;
|
||||
bool promo = false;
|
||||
};
|
||||
|
||||
SearchTags::SearchTags(
|
||||
|
@ -51,10 +100,13 @@ SearchTags::SearchTags(
|
|||
std::vector<Data::ReactionId> selected)
|
||||
: _owner(owner)
|
||||
, _added(selected) {
|
||||
std::move(
|
||||
tags
|
||||
) | rpl::start_with_next([=](const std::vector<Data::Reaction> &list) {
|
||||
fill(list);
|
||||
rpl::combine(
|
||||
std::move(tags),
|
||||
Data::AmPremiumValue(&owner->session())
|
||||
) | rpl::start_with_next([=](
|
||||
const std::vector<Data::Reaction> &list,
|
||||
bool premium) {
|
||||
fill(list, premium);
|
||||
}, _lifetime);
|
||||
|
||||
// Mark the `selected` reactions as selected in `_tags`.
|
||||
|
@ -73,12 +125,19 @@ SearchTags::SearchTags(
|
|||
|
||||
SearchTags::~SearchTags() = default;
|
||||
|
||||
void SearchTags::fill(const std::vector<Data::Reaction> &list) {
|
||||
void SearchTags::fill(
|
||||
const std::vector<Data::Reaction> &list,
|
||||
bool premium) {
|
||||
const auto selected = collectSelected();
|
||||
_tags.clear();
|
||||
_tags.reserve(list.size());
|
||||
const auto link = [&](Data::ReactionId id) {
|
||||
return std::make_shared<LambdaClickHandler>(crl::guard(this, [=] {
|
||||
return std::make_shared<LambdaClickHandler>(crl::guard(this, [=](
|
||||
ClickContext context) {
|
||||
if (!premium) {
|
||||
MakePromoLink()->onClick(context);
|
||||
return;
|
||||
}
|
||||
const auto i = ranges::find(_tags, id, &Tag::id);
|
||||
if (i != end(_tags)) {
|
||||
if (!i->selected && !base::IsShiftPressed()) {
|
||||
|
@ -109,6 +168,18 @@ void SearchTags::fill(const std::vector<Data::Reaction> &list) {
|
|||
_owner->reactions().preloadImageFor(id);
|
||||
}
|
||||
};
|
||||
if (!premium) {
|
||||
const auto text = (list.empty() && _added.empty())
|
||||
? tr::lng_add_tag_button(tr::now)
|
||||
: tr::lng_unlock_tags(tr::now);
|
||||
_tags.push_back({
|
||||
.id = Data::ReactionId(),
|
||||
.text = text,
|
||||
.textWidth = st::reactionInlineTagFont->width(text),
|
||||
.link = MakePromoLink(),
|
||||
.promo = true,
|
||||
});
|
||||
}
|
||||
for (const auto &reaction : list) {
|
||||
if (reaction.count > 0
|
||||
|| ranges::contains(_added, reaction.id)
|
||||
|
@ -131,10 +202,11 @@ void SearchTags::layout() {
|
|||
Expects(_width > 0);
|
||||
|
||||
if (_tags.empty()) {
|
||||
_additionalText = {};
|
||||
_height = 0;
|
||||
return;
|
||||
}
|
||||
const auto &bg = validateBg(false);
|
||||
const auto &bg = validateBg(false, false);
|
||||
const auto skip = st::dialogsSearchTagSkip;
|
||||
const auto size = bg.size() / bg.devicePixelRatio();
|
||||
const auto xbase = size.width();
|
||||
|
@ -147,10 +219,17 @@ void SearchTags::layout() {
|
|||
x = 0;
|
||||
y += ybase + skip.y();
|
||||
}
|
||||
tag.geometry = QRect(x, y, width, xbase);
|
||||
tag.geometry = QRect(x, y, width, ybase);
|
||||
x += width + skip.x();
|
||||
}
|
||||
_height = y + ybase + st::dialogsSearchTagBottom;
|
||||
if (_tags.size() == 1 && _tags.front().promo) {
|
||||
_additionalLeft = x;
|
||||
const auto additionalWidth = _width - _additionalLeft;
|
||||
_additionalText = FillAdditionalText(_owner, additionalWidth);
|
||||
} else {
|
||||
_additionalText = {};
|
||||
}
|
||||
}
|
||||
|
||||
void SearchTags::resizeToWidth(int width) {
|
||||
|
@ -177,6 +256,14 @@ ClickHandlerPtr SearchTags::lookupHandler(QPoint point) const {
|
|||
for (const auto &tag : _tags) {
|
||||
if (tag.geometry.contains(point.x(), point.y())) {
|
||||
return tag.link;
|
||||
} else if (tag.promo
|
||||
&& !_additionalText.isEmpty()
|
||||
&& tag.geometry.united(QRect(
|
||||
_additionalLeft,
|
||||
tag.geometry.y(),
|
||||
_additionalText.maxWidth(),
|
||||
tag.geometry.height())).contains(point.x(), point.y())) {
|
||||
return tag.link;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -227,7 +314,7 @@ void SearchTags::paintCustomFrame(
|
|||
}
|
||||
|
||||
void SearchTags::paint(
|
||||
QPainter &p,
|
||||
Painter &p,
|
||||
QPoint position,
|
||||
crl::time now,
|
||||
bool paused) const {
|
||||
|
@ -236,9 +323,9 @@ void SearchTags::paint(
|
|||
const auto padding = st::reactionInlinePadding;
|
||||
for (const auto &tag : _tags) {
|
||||
const auto geometry = tag.geometry.translated(position);
|
||||
paintBackground(p, geometry, tag.selected);
|
||||
paintBackground(p, geometry, tag);
|
||||
paintText(p, geometry, tag);
|
||||
if (!tag.custom && tag.image.isNull()) {
|
||||
if (!tag.custom && !tag.promo && tag.image.isNull()) {
|
||||
tag.image = _owner->reactions().resolveImageFor(
|
||||
tag.id,
|
||||
::Data::Reactions::ImageSize::InlineList);
|
||||
|
@ -247,7 +334,9 @@ void SearchTags::paint(
|
|||
const auto image = QRect(
|
||||
inner.topLeft() + QPoint(skip, skip),
|
||||
QSize(st::reactionInlineImage, st::reactionInlineImage));
|
||||
if (const auto custom = tag.custom.get()) {
|
||||
if (tag.promo) {
|
||||
st::dialogsSearchTagLocked.paintInCenter(p, image);
|
||||
} else if (const auto custom = tag.custom.get()) {
|
||||
const auto textFg = tag.selected
|
||||
? st::dialogsNameFgActive->c
|
||||
: st::dialogsNameFgOver->c;
|
||||
|
@ -262,13 +351,26 @@ void SearchTags::paint(
|
|||
p.drawImage(image.topLeft(), tag.image);
|
||||
}
|
||||
}
|
||||
paintAdditionalText(p, position);
|
||||
}
|
||||
|
||||
void SearchTags::paintAdditionalText(Painter &p, QPoint position) const {
|
||||
if (_additionalText.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
const auto x = position.x() + _additionalLeft;
|
||||
const auto tag = _tags.front().geometry;
|
||||
const auto height = st::dialogsSearchTagPromo.font->height;
|
||||
const auto y = position.y() + tag.y() + (tag.height() - height) / 2;
|
||||
p.setPen(st::windowSubTextFg);
|
||||
_additionalText.drawLeft(p, x, y, _width - x, _width);
|
||||
}
|
||||
|
||||
void SearchTags::paintBackground(
|
||||
QPainter &p,
|
||||
QRect geometry,
|
||||
bool selected) const {
|
||||
const auto &image = validateBg(selected);
|
||||
const Tag &tag) const {
|
||||
const auto &image = validateBg(tag.selected, tag.promo);
|
||||
const auto ratio = int(image.devicePixelRatio());
|
||||
const auto size = image.size() / ratio;
|
||||
if (const auto fill = geometry.width() - size.width(); fill > 0) {
|
||||
|
@ -282,7 +384,7 @@ void SearchTags::paintBackground(
|
|||
QRect(QPoint(), QSize(left, size.height()) * ratio));
|
||||
p.fillRect(
|
||||
QRect(x + left, y, fill, size.height()),
|
||||
bgColor(selected));
|
||||
bgColor(tag.selected, tag.promo));
|
||||
p.drawImage(
|
||||
QRect(x + left + fill, y, right, size.height()),
|
||||
image,
|
||||
|
@ -292,30 +394,39 @@ void SearchTags::paintBackground(
|
|||
}
|
||||
}
|
||||
|
||||
void SearchTags::paintText(QPainter &p, QRect geometry, const Tag &tag) const {
|
||||
void SearchTags::paintText(
|
||||
QPainter &p,
|
||||
QRect geometry,
|
||||
const Tag &tag) const {
|
||||
using namespace HistoryView::Reactions;
|
||||
|
||||
if (tag.text.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
p.setPen(tag.selected ? st::dialogsTextFgActive : st::windowSubTextFg);
|
||||
p.setPen(tag.promo
|
||||
? st::lightButtonFgOver
|
||||
: tag.selected
|
||||
? st::dialogsTextFgActive
|
||||
: st::windowSubTextFg);
|
||||
p.setFont(st::reactionInlineTagFont);
|
||||
const auto x = geometry.x() + st::reactionInlineTagNamePosition.x();
|
||||
const auto y = geometry.y() + st::reactionInlineTagNamePosition.y();
|
||||
p.drawText(x, y + st::reactionInlineTagFont->ascent, tag.text);
|
||||
}
|
||||
|
||||
QColor SearchTags::bgColor(bool selected) const {
|
||||
return selected
|
||||
QColor SearchTags::bgColor(bool selected, bool promo) const {
|
||||
return promo
|
||||
? st::lightButtonBgOver->c
|
||||
: selected
|
||||
? st::dialogsBgActive->c
|
||||
: st::dialogsBgOver->c;
|
||||
}
|
||||
|
||||
const QImage &SearchTags::validateBg(bool selected) const {
|
||||
const QImage &SearchTags::validateBg(bool selected, bool promo) const {
|
||||
using namespace HistoryView::Reactions;
|
||||
auto &image = selected ? _selectedBg : _normalBg;
|
||||
auto &image = promo ? _promoBg : selected ? _selectedBg : _normalBg;
|
||||
if (image.isNull()) {
|
||||
const auto tagBg = bgColor(selected);
|
||||
const auto tagBg = bgColor(selected, promo);
|
||||
const auto dotBg = st::transparent->c;
|
||||
image = InlineList::PrepareTagBg(tagBg, dotBg);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "base/weak_ptr.h"
|
||||
|
||||
class Painter;
|
||||
|
||||
namespace Data {
|
||||
class Session;
|
||||
struct Reaction;
|
||||
|
@ -39,7 +41,7 @@ public:
|
|||
-> rpl::producer<std::vector<Data::ReactionId>>;
|
||||
|
||||
void paint(
|
||||
QPainter &p,
|
||||
Painter &p,
|
||||
QPoint position,
|
||||
crl::time now,
|
||||
bool paused) const;
|
||||
|
@ -49,7 +51,7 @@ public:
|
|||
private:
|
||||
struct Tag;
|
||||
|
||||
void fill(const std::vector<Data::Reaction> &list);
|
||||
void fill(const std::vector<Data::Reaction> &list, bool premium);
|
||||
void paintCustomFrame(
|
||||
QPainter &p,
|
||||
not_null<Ui::Text::CustomEmoji*> emoji,
|
||||
|
@ -59,25 +61,26 @@ private:
|
|||
const QColor &textColor) const;
|
||||
void layout();
|
||||
[[nodiscard]] std::vector<Data::ReactionId> collectSelected() const;
|
||||
[[nodiscard]] QColor bgColor(bool selected) const;
|
||||
[[nodiscard]] const QImage &validateBg(bool selected) const;
|
||||
void paintBackground(
|
||||
QPainter &p,
|
||||
QRect geometry,
|
||||
bool selected) const;
|
||||
[[nodiscard]] QColor bgColor(bool selected, bool promo) const;
|
||||
[[nodiscard]] const QImage &validateBg(bool selected, bool promo) const;
|
||||
void paintAdditionalText(Painter &p, QPoint position) const;
|
||||
void paintBackground(QPainter &p, QRect geometry, const Tag &tag) const;
|
||||
void paintText(QPainter &p, QRect geometry, const Tag &tag) const;
|
||||
|
||||
const not_null<Data::Session*> _owner;
|
||||
std::vector<Data::ReactionId> _added;
|
||||
std::vector<Tag> _tags;
|
||||
Ui::Text::String _additionalText;
|
||||
rpl::event_stream<> _selectedChanges;
|
||||
rpl::event_stream<> _repaintRequests;
|
||||
mutable QImage _normalBg;
|
||||
mutable QImage _selectedBg;
|
||||
mutable QImage _promoBg;
|
||||
mutable QImage _customCache;
|
||||
mutable int _customSkip = 0;
|
||||
rpl::variable<int> _height;
|
||||
int _width = 0;
|
||||
int _additionalLeft = 0;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
|
|
|
@ -2636,9 +2636,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
desiredPosition,
|
||||
reactItem,
|
||||
[=](ChosenReaction reaction) { reactionChosen(reaction); },
|
||||
(reactItem->reactionsAreTags()
|
||||
? TextWithEntities{ u"Organize your Saved Messages with tags. Learn More..."_q }
|
||||
: TextWithEntities()),
|
||||
ItemReactionsAbout(reactItem),
|
||||
_controller->cachedReactionIconFactory().createMethod())
|
||||
: AttachSelectorResult::Skipped;
|
||||
if (attached == AttachSelectorResult::Failed) {
|
||||
|
|
|
@ -2633,7 +2633,7 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
desiredPosition,
|
||||
reactItem,
|
||||
[=](ChosenReaction reaction) { reactionChosen(reaction); },
|
||||
TextWithEntities(),
|
||||
ItemReactionsAbout(reactItem),
|
||||
_controller->cachedReactionIconFactory().createMethod())
|
||||
: AttachSelectorResult::Skipped;
|
||||
if (attached == AttachSelectorResult::Failed) {
|
||||
|
|
|
@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/view/history_view_reply.h"
|
||||
#include "history/view/history_view_view_button.h" // ViewButton.
|
||||
#include "history/history.h"
|
||||
#include "boxes/premium_preview_box.h"
|
||||
#include "boxes/share_box.h"
|
||||
#include "ui/effects/glare.h"
|
||||
#include "ui/effects/reaction_fly_animation.h"
|
||||
|
@ -49,13 +50,13 @@ namespace {
|
|||
constexpr auto kPlayStatusLimit = 2;
|
||||
const auto kPsaTooltipPrefix = "cloud_lng_tooltip_psa_";
|
||||
|
||||
[[nodiscard]] std::optional<Window::SessionController*> ExtractController(
|
||||
[[nodiscard]] Window::SessionController *ExtractController(
|
||||
const ClickContext &context) {
|
||||
const auto my = context.other.value<ClickHandlerContext>();
|
||||
if (const auto controller = my.sessionWindow.get()) {
|
||||
return controller;
|
||||
}
|
||||
return std::nullopt;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
class KeyboardStyle : public ReplyKeyboard::Style {
|
||||
|
@ -2288,11 +2289,8 @@ ClickHandlerPtr Message::createGoToCommentsLink() const {
|
|||
const auto fullId = data()->fullId();
|
||||
const auto sessionId = data()->history()->session().uniqueId();
|
||||
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
|
||||
const auto controller = ExtractController(context).value_or(nullptr);
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
if (controller->session().uniqueId() != sessionId) {
|
||||
const auto controller = ExtractController(context);
|
||||
if (!controller || controller->session().uniqueId() != sessionId) {
|
||||
return;
|
||||
}
|
||||
if (const auto item = controller->session().data().message(fullId)) {
|
||||
|
@ -2984,12 +2982,20 @@ void Message::refreshReactions() {
|
|||
return std::make_shared<LambdaClickHandler>([=](
|
||||
ClickContext context) {
|
||||
if (const auto strong = weak.get()) {
|
||||
if (strong->data()->reactionsAreTags()) {
|
||||
const auto tag = Data::SearchTagToQuery(id);
|
||||
HashtagClickHandler(tag).onClick(context);
|
||||
const auto item = strong->data();
|
||||
if (item->reactionsAreTags()) {
|
||||
if (item->history()->session().premium()) {
|
||||
const auto tag = Data::SearchTagToQuery(id);
|
||||
HashtagClickHandler(tag).onClick(context);
|
||||
} else if (const auto controller
|
||||
= ExtractController(context)) {
|
||||
ShowPremiumPreviewBox(
|
||||
controller,
|
||||
PremiumPreview::TagsForMessages);
|
||||
}
|
||||
return;
|
||||
}
|
||||
strong->data()->toggleReaction(
|
||||
item->toggleReaction(
|
||||
id,
|
||||
HistoryItem::ReactionSource::Existing);
|
||||
if (const auto now = weak.get()) {
|
||||
|
@ -3586,11 +3592,8 @@ ClickHandlerPtr Message::prepareRightActionLink() const {
|
|||
};
|
||||
return std::make_shared<LambdaClickHandler>([=](
|
||||
ClickContext context) {
|
||||
const auto controller = ExtractController(context).value_or(nullptr);
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
if (controller->session().uniqueId() != sessionId) {
|
||||
const auto controller = ExtractController(context);
|
||||
if (!controller || controller->session().uniqueId() != sessionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,13 +12,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/text/text_custom_emoji.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/platform/ui_platform_utility.h"
|
||||
#include "ui/painter.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "chat_helpers/emoji_list_widget.h"
|
||||
#include "chat_helpers/stickers_list_footer.h"
|
||||
|
@ -277,6 +280,13 @@ Selector::Selector(
|
|||
, _skipy((st::reactStripHeight - st::reactStripSize) / 2) {
|
||||
setMouseTracking(true);
|
||||
|
||||
if (_about) {
|
||||
_about->setClickHandlerFilter([=](const auto &...) {
|
||||
_escapes.fire({});
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
_useTransparency = child || Ui::Platform::TranslucentWindowsSupported();
|
||||
}
|
||||
|
||||
|
@ -1173,6 +1183,10 @@ AttachSelectorResult AttachSelectorToMenu(
|
|||
chosen(std::move(reaction));
|
||||
}, selector->lifetime());
|
||||
|
||||
selector->escapes() | rpl::start_with_next([=] {
|
||||
menu->hideMenu();
|
||||
}, selector->lifetime());
|
||||
|
||||
const auto weak = base::make_weak(controller);
|
||||
controller->enableGifPauseReason(
|
||||
Window::GifPauseReason::MediaPreview);
|
||||
|
@ -1249,4 +1263,18 @@ auto AttachSelectorToMenu(
|
|||
return selector;
|
||||
}
|
||||
|
||||
TextWithEntities ItemReactionsAbout(not_null<HistoryItem*> item) {
|
||||
return !item->reactionsAreTags()
|
||||
? TextWithEntities()
|
||||
: item->history()->session().premium()
|
||||
? TextWithEntities{ tr::lng_add_tag_about(tr::now) }
|
||||
: tr::lng_subscribe_tag_about(
|
||||
tr::now,
|
||||
lt_link,
|
||||
Ui::Text::Link(
|
||||
tr::lng_subscribe_tag_link(tr::now),
|
||||
u"internal:about_tags"_q),
|
||||
Ui::Text::WithEntities);
|
||||
}
|
||||
|
||||
} // namespace HistoryView::Reactions
|
||||
|
|
|
@ -265,4 +265,7 @@ AttachSelectorResult AttachSelectorToMenu(
|
|||
IconFactory iconFactory
|
||||
) -> base::expected<not_null<Selector*>, AttachSelectorResult>;
|
||||
|
||||
[[nodiscard]] TextWithEntities ItemReactionsAbout(
|
||||
not_null<HistoryItem*> item);
|
||||
|
||||
} // namespace HistoryView::Reactions
|
||||
|
|
|
@ -27,7 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history.h"
|
||||
#include "main/main_session.h"
|
||||
#include "media/stories/media_stories_controller.h"
|
||||
#include "lang/lang_tag.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/effects/emoji_fly_animation.h"
|
||||
#include "ui/effects/path_shift_gradient.h"
|
||||
|
@ -676,7 +676,7 @@ void Reactions::Panel::create() {
|
|||
_controller->uiShow(),
|
||||
std::move(reactions),
|
||||
TextWithEntities{ (mode == Mode::Message
|
||||
? u"Send reaction as a private message"_q
|
||||
? tr::lng_stories_reaction_as_message(tr::now)
|
||||
: QString()) },
|
||||
_controller->cachedReactionIconFactory().createMethod(),
|
||||
[=](bool fast) { hide(mode); });
|
||||
|
|
|
@ -525,13 +525,16 @@ bool ShowReactPremiumError(
|
|||
not_null<SessionController*> controller,
|
||||
not_null<HistoryItem*> item,
|
||||
const Data::ReactionId &id) {
|
||||
if (controller->session().premium()
|
||||
if (item->reactionsAreTags()) {
|
||||
if (controller->session().premium()) {
|
||||
return false;
|
||||
}
|
||||
ShowPremiumPreviewBox(controller, PremiumPreview::TagsForMessages);
|
||||
return true;
|
||||
} else if (controller->session().premium()
|
||||
|| ranges::contains(item->chosenReactions(), id)
|
||||
|| item->history()->peer->isBroadcast()) {
|
||||
return false;
|
||||
} else if (item->reactionsAreTags()) {
|
||||
ShowPremiumPreviewBox(controller, PremiumPreview::TagsForMessages);
|
||||
return true;
|
||||
} else if (!id.custom()) {
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue