mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support entities in star gift messages.
This commit is contained in:
parent
8b11d2d5e7
commit
9ace04d2c9
11 changed files with 191 additions and 79 deletions
|
@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "api/api_premium.h"
|
#include "api/api_premium.h"
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
#include "boxes/send_credits_box.h"
|
#include "boxes/send_credits_box.h"
|
||||||
|
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||||
|
#include "chat_helpers/message_field.h"
|
||||||
#include "chat_helpers/stickers_gift_box_pack.h"
|
#include "chat_helpers/stickers_gift_box_pack.h"
|
||||||
#include "chat_helpers/stickers_lottie.h"
|
#include "chat_helpers/stickers_lottie.h"
|
||||||
#include "core/ui_integration.h"
|
#include "core/ui_integration.h"
|
||||||
|
@ -65,7 +67,7 @@ namespace {
|
||||||
|
|
||||||
constexpr auto kPriceTabAll = 0;
|
constexpr auto kPriceTabAll = 0;
|
||||||
constexpr auto kPriceTabLimited = -1;
|
constexpr auto kPriceTabLimited = -1;
|
||||||
constexpr auto kGiftMessageLimit = 256;
|
constexpr auto kGiftMessageLimit = 255;
|
||||||
constexpr auto kSentToastDuration = 3 * crl::time(1000);
|
constexpr auto kSentToastDuration = 3 * crl::time(1000);
|
||||||
|
|
||||||
using namespace HistoryView;
|
using namespace HistoryView;
|
||||||
|
@ -83,7 +85,7 @@ struct GiftsDescriptor {
|
||||||
|
|
||||||
struct GiftDetails {
|
struct GiftDetails {
|
||||||
GiftDescriptor descriptor;
|
GiftDescriptor descriptor;
|
||||||
QString text;
|
TextWithEntities text;
|
||||||
bool anonymous = false;
|
bool anonymous = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -160,14 +162,16 @@ auto GenerateGiftMedia(
|
||||||
auto pushText = [&](
|
auto pushText = [&](
|
||||||
TextWithEntities text,
|
TextWithEntities text,
|
||||||
QMargins margins = {},
|
QMargins margins = {},
|
||||||
const base::flat_map<uint16, ClickHandlerPtr> &links = {}) {
|
const base::flat_map<uint16, ClickHandlerPtr> &links = {},
|
||||||
|
const std::any &context = {}) {
|
||||||
if (text.empty()) {
|
if (text.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
push(std::make_unique<MediaGenericTextPart>(
|
push(std::make_unique<MediaGenericTextPart>(
|
||||||
std::move(text),
|
std::move(text),
|
||||||
margins,
|
margins,
|
||||||
links));
|
links,
|
||||||
|
context));
|
||||||
};
|
};
|
||||||
const auto sticker = [=] {
|
const auto sticker = [=] {
|
||||||
using Tag = ChatHelpers::StickerLottieSize;
|
using Tag = ChatHelpers::StickerLottieSize;
|
||||||
|
@ -202,11 +206,18 @@ auto GenerateGiftMedia(
|
||||||
lt_count,
|
lt_count,
|
||||||
v::get<GiftTypeStars>(descriptor).convertStars,
|
v::get<GiftTypeStars>(descriptor).convertStars,
|
||||||
Ui::Text::RichLangValue);
|
Ui::Text::RichLangValue);
|
||||||
auto description = data.text.isEmpty()
|
auto description = data.text.empty()
|
||||||
? std::move(textFallback)
|
? std::move(textFallback)
|
||||||
: TextWithEntities{ data.text };
|
: data.text;
|
||||||
pushText(Ui::Text::Bold(title), st::giftBoxPreviewTitlePadding);
|
pushText(Ui::Text::Bold(title), st::giftBoxPreviewTitlePadding);
|
||||||
pushText(std::move(description), st::giftBoxPreviewTextPadding);
|
pushText(
|
||||||
|
std::move(description),
|
||||||
|
st::giftBoxPreviewTextPadding,
|
||||||
|
{},
|
||||||
|
Core::MarkedTextContext{
|
||||||
|
.session = &parent->data()->history()->session(),
|
||||||
|
.customEmojiRepaint = [parent] { parent->repaint(); },
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,10 +743,6 @@ void SendGiftBox(
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto session = &window->session();
|
const auto session = &window->session();
|
||||||
const auto context = Core::MarkedTextContext{
|
|
||||||
.session = session,
|
|
||||||
.customEmojiRepaint = [] {},
|
|
||||||
};
|
|
||||||
auto cost = rpl::single([&] {
|
auto cost = rpl::single([&] {
|
||||||
return v::match(descriptor, [&](const GiftTypePremium &data) {
|
return v::match(descriptor, [&](const GiftTypePremium &data) {
|
||||||
if (data.currency == Ui::kCreditsCurrency) {
|
if (data.currency == Ui::kCreditsCurrency) {
|
||||||
|
@ -777,10 +784,40 @@ void SendGiftBox(
|
||||||
kGiftMessageLimit);
|
kGiftMessageLimit);
|
||||||
text->changes() | rpl::start_with_next([=] {
|
text->changes() | rpl::start_with_next([=] {
|
||||||
auto now = state->details.current();
|
auto now = state->details.current();
|
||||||
now.text = text->getLastText();
|
auto textWithTags = text->getTextWithAppliedMarkdown();
|
||||||
|
now.text = TextWithEntities{
|
||||||
|
std::move(textWithTags.text),
|
||||||
|
TextUtilities::ConvertTextTagsToEntities(textWithTags.tags)
|
||||||
|
};
|
||||||
state->details = std::move(now);
|
state->details = std::move(now);
|
||||||
}, text->lifetime());
|
}, text->lifetime());
|
||||||
|
|
||||||
|
const auto allow = [=](not_null<DocumentData*> emoji) {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
InitMessageFieldHandlers({
|
||||||
|
.session = &window->session(),
|
||||||
|
.show = window->uiShow(),
|
||||||
|
.field = text,
|
||||||
|
.customEmojiPaused = [=] {
|
||||||
|
using namespace Window;
|
||||||
|
return window->isGifPausedAtLeastFor(GifPauseReason::Layer);
|
||||||
|
},
|
||||||
|
.allowPremiumEmoji = allow,
|
||||||
|
.allowMarkdownTags = {
|
||||||
|
Ui::InputField::kTagBold,
|
||||||
|
Ui::InputField::kTagItalic,
|
||||||
|
Ui::InputField::kTagUnderline,
|
||||||
|
Ui::InputField::kTagStrikeOut,
|
||||||
|
Ui::InputField::kTagSpoiler,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ui::Emoji::SuggestionsController::Init(
|
||||||
|
box->getDelegate()->outerContainer(),
|
||||||
|
text,
|
||||||
|
&window->session(),
|
||||||
|
{ .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow });
|
||||||
|
|
||||||
AddDivider(container);
|
AddDivider(container);
|
||||||
AddSkip(container);
|
AddSkip(container);
|
||||||
container->add(
|
container->add(
|
||||||
|
@ -825,7 +862,7 @@ void SendGiftBox(
|
||||||
Payments::CheckoutProcess::Start(Payments::InvoiceStarGift{
|
Payments::CheckoutProcess::Start(Payments::InvoiceStarGift{
|
||||||
.giftId = gift.id,
|
.giftId = gift.id,
|
||||||
.randomId = state->randomId,
|
.randomId = state->randomId,
|
||||||
.message = { details.text },
|
.message = details.text,
|
||||||
.user = peer->asUser(),
|
.user = peer->asUser(),
|
||||||
.anonymous = details.anonymous,
|
.anonymous = details.anonymous,
|
||||||
}, done, Payments::ProcessNonPanelPaymentFormFactory(window, done));
|
}, done, Payments::ProcessNonPanelPaymentFormFactory(window, done));
|
||||||
|
|
|
@ -1267,13 +1267,16 @@ void SendFilesBox::setupCaption() {
|
||||||
: (_limits & SendFilesAllow::EmojiWithoutPremium);
|
: (_limits & SendFilesAllow::EmojiWithoutPremium);
|
||||||
};
|
};
|
||||||
const auto show = _show;
|
const auto show = _show;
|
||||||
InitMessageFieldHandlers(
|
InitMessageFieldHandlers({
|
||||||
&show->session(),
|
.session = &show->session(),
|
||||||
show,
|
.show = show,
|
||||||
_caption.data(),
|
.field = _caption.data(),
|
||||||
[=] { return show->paused(Window::GifPauseReason::Layer); },
|
.customEmojiPaused = [=] {
|
||||||
allow,
|
return show->paused(Window::GifPauseReason::Layer);
|
||||||
&_st.files.caption);
|
},
|
||||||
|
.allowPremiumEmoji = allow,
|
||||||
|
.fieldStyle = &_st.files.caption,
|
||||||
|
});
|
||||||
setupCaptionAutocomplete();
|
setupCaptionAutocomplete();
|
||||||
Ui::Emoji::SuggestionsController::Init(
|
Ui::Emoji::SuggestionsController::Init(
|
||||||
getDelegate()->outerContainer(),
|
getDelegate()->outerContainer(),
|
||||||
|
|
|
@ -240,13 +240,12 @@ void ShareBox::prepareCommentField() {
|
||||||
}, field->lifetime());
|
}, field->lifetime());
|
||||||
|
|
||||||
if (const auto show = uiShow(); show->valid()) {
|
if (const auto show = uiShow(); show->valid()) {
|
||||||
InitMessageFieldHandlers(
|
InitMessageFieldHandlers({
|
||||||
_descriptor.session,
|
.session = _descriptor.session,
|
||||||
Main::MakeSessionShow(show, _descriptor.session),
|
.show = Main::MakeSessionShow(show, _descriptor.session),
|
||||||
field,
|
.field = field,
|
||||||
nullptr,
|
.fieldStyle = _descriptor.stLabel,
|
||||||
nullptr,
|
});
|
||||||
_descriptor.stLabel);
|
|
||||||
}
|
}
|
||||||
field->setSubmitSettings(Core::App().settings().sendSubmitWay());
|
field->setSubmitSettings(Core::App().settings().sendSubmitWay());
|
||||||
|
|
||||||
|
|
|
@ -423,18 +423,14 @@ Fn<void(QString now, Fn<void(QString)> save)> DefaultEditLanguageCallback(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitMessageFieldHandlers(
|
void InitMessageFieldHandlers(MessageFieldHandlersArgs &&args) {
|
||||||
not_null<Main::Session*> session,
|
const auto paused = [passed = args.customEmojiPaused] {
|
||||||
std::shared_ptr<Main::SessionShow> show,
|
return passed && passed();
|
||||||
not_null<Ui::InputField*> field,
|
|
||||||
Fn<bool()> customEmojiPaused,
|
|
||||||
Fn<bool(not_null<DocumentData*>)> allowPremiumEmoji,
|
|
||||||
const style::InputField *fieldStyle) {
|
|
||||||
const auto paused = [customEmojiPaused] {
|
|
||||||
return customEmojiPaused && customEmojiPaused();
|
|
||||||
};
|
};
|
||||||
|
const auto field = args.field;
|
||||||
|
const auto session = args.session;
|
||||||
field->setTagMimeProcessor(
|
field->setTagMimeProcessor(
|
||||||
FieldTagMimeProcessor(session, allowPremiumEmoji));
|
FieldTagMimeProcessor(session, args.allowPremiumEmoji));
|
||||||
field->setCustomTextContext([=](Fn<void()> repaint) {
|
field->setCustomTextContext([=](Fn<void()> repaint) {
|
||||||
return std::any(Core::MarkedTextContext{
|
return std::any(Core::MarkedTextContext{
|
||||||
.session = session,
|
.session = session,
|
||||||
|
@ -448,12 +444,14 @@ void InitMessageFieldHandlers(
|
||||||
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||||
field->setInstantReplacesEnabled(
|
field->setInstantReplacesEnabled(
|
||||||
Core::App().settings().replaceEmojiValue());
|
Core::App().settings().replaceEmojiValue());
|
||||||
field->setMarkdownReplacesEnabled(true);
|
field->setMarkdownReplacesEnabled(rpl::single(Ui::MarkdownEnabledState{
|
||||||
if (show) {
|
Ui::MarkdownEnabled{ std::move(args.allowMarkdownTags) }
|
||||||
|
}));
|
||||||
|
if (const auto &show = args.show) {
|
||||||
field->setEditLinkCallback(
|
field->setEditLinkCallback(
|
||||||
DefaultEditLinkCallback(show, field, fieldStyle));
|
DefaultEditLinkCallback(show, field, args.fieldStyle));
|
||||||
field->setEditLanguageCallback(DefaultEditLanguageCallback(show));
|
field->setEditLanguageCallback(DefaultEditLanguageCallback(show));
|
||||||
InitSpellchecker(show, field, fieldStyle != nullptr);
|
InitSpellchecker(show, field, args.fieldStyle != nullptr);
|
||||||
}
|
}
|
||||||
const auto style = field->lifetime().make_state<Ui::ChatStyle>(
|
const auto style = field->lifetime().make_state<Ui::ChatStyle>(
|
||||||
session->colorIndicesValue());
|
session->colorIndicesValue());
|
||||||
|
@ -553,12 +551,15 @@ void InitMessageFieldHandlers(
|
||||||
not_null<Ui::InputField*> field,
|
not_null<Ui::InputField*> field,
|
||||||
ChatHelpers::PauseReason pauseReasonLevel,
|
ChatHelpers::PauseReason pauseReasonLevel,
|
||||||
Fn<bool(not_null<DocumentData*>)> allowPremiumEmoji) {
|
Fn<bool(not_null<DocumentData*>)> allowPremiumEmoji) {
|
||||||
InitMessageFieldHandlers(
|
InitMessageFieldHandlers({
|
||||||
&controller->session(),
|
.session = &controller->session(),
|
||||||
controller->uiShow(),
|
.show = controller->uiShow(),
|
||||||
field,
|
.field = field,
|
||||||
[=] { return controller->isGifPausedAtLeastFor(pauseReasonLevel); },
|
.customEmojiPaused = [=] {
|
||||||
allowPremiumEmoji);
|
return controller->isGifPausedAtLeastFor(pauseReasonLevel);
|
||||||
|
},
|
||||||
|
.allowPremiumEmoji = std::move(allowPremiumEmoji),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitMessageFieldGeometry(not_null<Ui::InputField*> field) {
|
void InitMessageFieldGeometry(not_null<Ui::InputField*> field) {
|
||||||
|
@ -574,12 +575,15 @@ void InitMessageField(
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
not_null<Ui::InputField*> field,
|
not_null<Ui::InputField*> field,
|
||||||
Fn<bool(not_null<DocumentData*>)> allowPremiumEmoji) {
|
Fn<bool(not_null<DocumentData*>)> allowPremiumEmoji) {
|
||||||
InitMessageFieldHandlers(
|
InitMessageFieldHandlers({
|
||||||
&show->session(),
|
.session = &show->session(),
|
||||||
show,
|
.show = show,
|
||||||
field,
|
.field = field,
|
||||||
[=] { return show->paused(ChatHelpers::PauseReason::Any); },
|
.customEmojiPaused = [=] {
|
||||||
std::move(allowPremiumEmoji));
|
return show->paused(ChatHelpers::PauseReason::Any);
|
||||||
|
},
|
||||||
|
.allowPremiumEmoji = std::move(allowPremiumEmoji),
|
||||||
|
});
|
||||||
InitMessageFieldGeometry(field);
|
InitMessageFieldGeometry(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,13 +54,18 @@ Fn<bool(
|
||||||
const style::InputField *fieldStyle = nullptr);
|
const style::InputField *fieldStyle = nullptr);
|
||||||
Fn<void(QString now, Fn<void(QString)> save)> DefaultEditLanguageCallback(
|
Fn<void(QString now, Fn<void(QString)> save)> DefaultEditLanguageCallback(
|
||||||
std::shared_ptr<Ui::Show> show);
|
std::shared_ptr<Ui::Show> show);
|
||||||
void InitMessageFieldHandlers(
|
|
||||||
not_null<Main::Session*> session,
|
struct MessageFieldHandlersArgs {
|
||||||
std::shared_ptr<Main::SessionShow> show, // may be null
|
not_null<Main::Session*> session;
|
||||||
not_null<Ui::InputField*> field,
|
std::shared_ptr<Main::SessionShow> show; // may be null
|
||||||
Fn<bool()> customEmojiPaused,
|
not_null<Ui::InputField*> field;
|
||||||
Fn<bool(not_null<DocumentData*>)> allowPremiumEmoji = nullptr,
|
Fn<bool()> customEmojiPaused;
|
||||||
const style::InputField *fieldStyle = nullptr);
|
Fn<bool(not_null<DocumentData*>)> allowPremiumEmoji;
|
||||||
|
const style::InputField *fieldStyle = nullptr;
|
||||||
|
base::flat_set<QString> allowMarkdownTags;
|
||||||
|
};
|
||||||
|
void InitMessageFieldHandlers(MessageFieldHandlersArgs &&args);
|
||||||
|
|
||||||
void InitMessageFieldHandlers(
|
void InitMessageFieldHandlers(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<Ui::InputField*> field,
|
not_null<Ui::InputField*> field,
|
||||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/dynamic_image.h"
|
#include "ui/dynamic_image.h"
|
||||||
#include "ui/dynamic_thumbnails.h"
|
#include "ui/dynamic_thumbnails.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
|
#include "ui/power_saving.h"
|
||||||
#include "ui/rect.h"
|
#include "ui/rect.h"
|
||||||
#include "ui/round_rect.h"
|
#include "ui/round_rect.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
@ -222,10 +223,15 @@ QMargins MediaGeneric::inBubblePadding() const {
|
||||||
MediaGenericTextPart::MediaGenericTextPart(
|
MediaGenericTextPart::MediaGenericTextPart(
|
||||||
TextWithEntities text,
|
TextWithEntities text,
|
||||||
QMargins margins,
|
QMargins margins,
|
||||||
const base::flat_map<uint16, ClickHandlerPtr> &links)
|
const base::flat_map<uint16, ClickHandlerPtr> &links,
|
||||||
|
const std::any &context)
|
||||||
: _text(st::msgMinWidth)
|
: _text(st::msgMinWidth)
|
||||||
, _margins(margins) {
|
, _margins(margins) {
|
||||||
_text.setMarkedText(st::defaultTextStyle, text);
|
_text.setMarkedText(
|
||||||
|
st::defaultTextStyle,
|
||||||
|
text,
|
||||||
|
kMarkupTextOptions,
|
||||||
|
context);
|
||||||
for (const auto &[index, link] : links) {
|
for (const auto &[index, link] : links) {
|
||||||
_text.setLink(index, link);
|
_text.setLink(index, link);
|
||||||
}
|
}
|
||||||
|
@ -248,7 +254,10 @@ void MediaGenericTextPart::draw(
|
||||||
.palette = &(service
|
.palette = &(service
|
||||||
? context.st->serviceTextPalette()
|
? context.st->serviceTextPalette()
|
||||||
: context.messageStyle()->textPalette),
|
: context.messageStyle()->textPalette),
|
||||||
|
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||||
.now = context.now,
|
.now = context.now,
|
||||||
|
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
|
||||||
|
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,8 @@ public:
|
||||||
MediaGenericTextPart(
|
MediaGenericTextPart(
|
||||||
TextWithEntities text,
|
TextWithEntities text,
|
||||||
QMargins margins,
|
QMargins margins,
|
||||||
const base::flat_map<uint16, ClickHandlerPtr> &links = {});
|
const base::flat_map<uint16, ClickHandlerPtr> &links = {},
|
||||||
|
const std::any &context = {});
|
||||||
|
|
||||||
void draw(
|
void draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
|
|
@ -6,14 +6,20 @@ For license and copyright information please follow this link:
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "history/view/media/history_view_service_box.h"
|
#include "history/view/media/history_view_service_box.h"
|
||||||
//
|
|
||||||
#include "history/view/history_view_cursor_state.h"
|
#include "core/ui_integration.h"
|
||||||
#include "history/view/media/history_view_sticker_player_abstract.h"
|
#include "history/view/media/history_view_sticker_player_abstract.h"
|
||||||
|
#include "history/view/history_view_cursor_state.h"
|
||||||
|
#include "history/view/history_view_element.h"
|
||||||
|
#include "history/view/history_view_text_helper.h"
|
||||||
|
#include "history/history.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "ui/chat/chat_style.h"
|
#include "ui/chat/chat_style.h"
|
||||||
|
#include "ui/effects/animation_value.h"
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
|
#include "ui/power_saving.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
#include "styles/style_premium.h"
|
#include "styles/style_premium.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
|
@ -48,9 +54,15 @@ ServiceBox::ServiceBox(
|
||||||
EntityType::StrikeOut,
|
EntityType::StrikeOut,
|
||||||
EntityType::Underline,
|
EntityType::Underline,
|
||||||
EntityType::Italic,
|
EntityType::Italic,
|
||||||
|
EntityType::Spoiler,
|
||||||
|
EntityType::CustomEmoji,
|
||||||
}),
|
}),
|
||||||
kMarkupTextOptions,
|
kMarkupTextOptions,
|
||||||
_maxWidth)
|
_maxWidth,
|
||||||
|
Core::MarkedTextContext{
|
||||||
|
.session = &parent->history()->session(),
|
||||||
|
.customEmojiRepaint = [parent] { parent->customEmojiRepaint(); },
|
||||||
|
})
|
||||||
, _size(
|
, _size(
|
||||||
_content->width(),
|
_content->width(),
|
||||||
(st::msgServiceGiftBoxTopSkip
|
(st::msgServiceGiftBoxTopSkip
|
||||||
|
@ -67,6 +79,7 @@ ServiceBox::ServiceBox(
|
||||||
: (_content->buttonSkip() + st::msgServiceGiftBoxButtonHeight))
|
: (_content->buttonSkip() + st::msgServiceGiftBoxButtonHeight))
|
||||||
+ st::msgServiceGiftBoxButtonMargins.bottom()))
|
+ st::msgServiceGiftBoxButtonMargins.bottom()))
|
||||||
, _innerSize(_size - QSize(0, st::msgServiceGiftBoxTopSkip)) {
|
, _innerSize(_size - QSize(0, st::msgServiceGiftBoxTopSkip)) {
|
||||||
|
InitElementTextPart(_parent, _subtitle);
|
||||||
if (auto text = _content->button()) {
|
if (auto text = _content->button()) {
|
||||||
_button.repaint = [=] { repaint(); };
|
_button.repaint = [=] { repaint(); };
|
||||||
std::move(text) | rpl::start_with_next([=](QString value) {
|
std::move(text) | rpl::start_with_next([=](QString value) {
|
||||||
|
@ -116,7 +129,17 @@ void ServiceBox::draw(Painter &p, const PaintContext &context) const {
|
||||||
_title.draw(p, st::msgPadding.left(), top, _maxWidth, style::al_top);
|
_title.draw(p, st::msgPadding.left(), top, _maxWidth, style::al_top);
|
||||||
top += _title.countHeight(_maxWidth) + padding.bottom();
|
top += _title.countHeight(_maxWidth) + padding.bottom();
|
||||||
}
|
}
|
||||||
_subtitle.draw(p, st::msgPadding.left(), top, _maxWidth, style::al_top);
|
_parent->prepareCustomEmojiPaint(p, context, _subtitle);
|
||||||
|
_subtitle.draw(p, {
|
||||||
|
.position = QPoint(st::msgPadding.left(), top),
|
||||||
|
.availableWidth = _maxWidth,
|
||||||
|
.align = style::al_top,
|
||||||
|
.palette = &context.st->serviceTextPalette(),
|
||||||
|
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||||
|
.now = context.now,
|
||||||
|
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
|
||||||
|
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
|
||||||
|
});
|
||||||
top += _subtitle.countHeight(_maxWidth) + padding.bottom();
|
top += _subtitle.countHeight(_maxWidth) + padding.bottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,8 +203,30 @@ void ServiceBox::draw(Painter &p, const PaintContext &context) const {
|
||||||
|
|
||||||
TextState ServiceBox::textState(QPoint point, StateRequest request) const {
|
TextState ServiceBox::textState(QPoint point, StateRequest request) const {
|
||||||
auto result = TextState(_parent);
|
auto result = TextState(_parent);
|
||||||
|
const auto content = contentRect();
|
||||||
|
const auto lookupSubtitleLink = [&] {
|
||||||
|
auto top = st::msgServiceGiftBoxTopSkip
|
||||||
|
+ content.top()
|
||||||
|
+ content.height();
|
||||||
|
const auto &padding = st::msgServiceGiftBoxTitlePadding;
|
||||||
|
top += padding.top();
|
||||||
|
if (!_title.isEmpty()) {
|
||||||
|
top += _title.countHeight(_maxWidth) + padding.bottom();
|
||||||
|
}
|
||||||
|
auto subtitleRequest = request.forText();
|
||||||
|
subtitleRequest.align = style::al_top;
|
||||||
|
const auto state = _subtitle.getState(
|
||||||
|
point - QPoint(st::msgPadding.left(), top),
|
||||||
|
_maxWidth,
|
||||||
|
subtitleRequest);
|
||||||
|
if (state.link) {
|
||||||
|
result.link = state.link;
|
||||||
|
}
|
||||||
|
};
|
||||||
if (_button.empty()) {
|
if (_button.empty()) {
|
||||||
if (QRect(QPoint(), _innerSize).contains(point)) {
|
if (!_button.link) {
|
||||||
|
lookupSubtitleLink();
|
||||||
|
} else if (QRect(QPoint(), _innerSize).contains(point)) {
|
||||||
result.link = _button.link;
|
result.link = _button.link;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -189,11 +234,13 @@ TextState ServiceBox::textState(QPoint point, StateRequest request) const {
|
||||||
if (rect.contains(point)) {
|
if (rect.contains(point)) {
|
||||||
result.link = _button.link;
|
result.link = _button.link;
|
||||||
_button.lastPoint = point - rect.topLeft();
|
_button.lastPoint = point - rect.topLeft();
|
||||||
} else if (contentRect().contains(point)) {
|
} else if (content.contains(point)) {
|
||||||
if (!_contentLink) {
|
if (!_contentLink) {
|
||||||
_contentLink = _content->createViewLink();
|
_contentLink = _content->createViewLink();
|
||||||
}
|
}
|
||||||
result.link = _contentLink;
|
result.link = _contentLink;
|
||||||
|
} else {
|
||||||
|
lookupSubtitleLink();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -238,6 +285,10 @@ bool ServiceBox::customInfoLayout() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServiceBox::hideSpoilers() {
|
||||||
|
_subtitle.setSpoilerRevealed(false, anim::type::instant);
|
||||||
|
}
|
||||||
|
|
||||||
bool ServiceBox::hasHeavyPart() const {
|
bool ServiceBox::hasHeavyPart() const {
|
||||||
return _content->hasHeavyPart();
|
return _content->hasHeavyPart();
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@ public:
|
||||||
[[nodiscard]] bool hideServiceText() const override {
|
[[nodiscard]] bool hideServiceText() const override {
|
||||||
return _content->hideServiceText();
|
return _content->hideServiceText();
|
||||||
}
|
}
|
||||||
|
void hideSpoilers() override;
|
||||||
|
|
||||||
bool hasHeavyPart() const override;
|
bool hasHeavyPart() const override;
|
||||||
void unloadHeavyPart() override;
|
void unloadHeavyPart() override;
|
||||||
|
|
|
@ -1091,11 +1091,10 @@ void Notification::showReplyField() {
|
||||||
_replyArea->setFocus();
|
_replyArea->setFocus();
|
||||||
_replyArea->setMaxLength(MaxMessageSize);
|
_replyArea->setMaxLength(MaxMessageSize);
|
||||||
_replyArea->setSubmitSettings(Ui::InputField::SubmitSettings::Both);
|
_replyArea->setSubmitSettings(Ui::InputField::SubmitSettings::Both);
|
||||||
InitMessageFieldHandlers(
|
InitMessageFieldHandlers({
|
||||||
&_item->history()->session(),
|
.session = &_item->history()->session(),
|
||||||
nullptr,
|
.field = _replyArea.data(),
|
||||||
_replyArea.data(),
|
});
|
||||||
nullptr);
|
|
||||||
|
|
||||||
// Catch mouse press event to activate the window.
|
// Catch mouse press event to activate the window.
|
||||||
QCoreApplication::instance()->installEventFilter(this);
|
QCoreApplication::instance()->installEventFilter(this);
|
||||||
|
|
|
@ -2215,11 +2215,14 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
|
||||||
|
|
||||||
field->submits(
|
field->submits(
|
||||||
) | rpl::start_with_next([=] { submit({}); }, field->lifetime());
|
) | rpl::start_with_next([=] { submit({}); }, field->lifetime());
|
||||||
InitMessageFieldHandlers(
|
InitMessageFieldHandlers({
|
||||||
session,
|
.session = session,
|
||||||
show,
|
.show = show,
|
||||||
field,
|
.field = field,
|
||||||
[=] { return show->paused(GifPauseReason::Layer); });
|
.customEmojiPaused = [=] {
|
||||||
|
return show->paused(GifPauseReason::Layer);
|
||||||
|
},
|
||||||
|
});
|
||||||
field->setSubmitSettings(Core::App().settings().sendSubmitWay());
|
field->setSubmitSettings(Core::App().settings().sendSubmitWay());
|
||||||
|
|
||||||
Ui::SendPendingMoveResizeEvents(comment);
|
Ui::SendPendingMoveResizeEvents(comment);
|
||||||
|
|
Loading…
Add table
Reference in a new issue