mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Display custom emoji reactions under messages.
This commit is contained in:
parent
14f937cb02
commit
ba83836922
17 changed files with 178 additions and 47 deletions
|
@ -592,8 +592,13 @@ bool WhoReadExists(not_null<HistoryItem*> item) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WhoReactedExists(not_null<HistoryItem*> item) {
|
bool WhoReactedExists(
|
||||||
return item->canViewReactions() || WhoReadExists(item);
|
not_null<HistoryItem*> item,
|
||||||
|
WhoReactedList list) {
|
||||||
|
if (item->canViewReactions() || WhoReadExists(item)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return (list == WhoReactedList::One) && item->history()->peer->isUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<Ui::WhoReadContent> WhoReacted(
|
rpl::producer<Ui::WhoReadContent> WhoReacted(
|
||||||
|
|
|
@ -24,8 +24,15 @@ struct ReactionId;
|
||||||
|
|
||||||
namespace Api {
|
namespace Api {
|
||||||
|
|
||||||
|
enum class WhoReactedList {
|
||||||
|
All,
|
||||||
|
One,
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] bool WhoReadExists(not_null<HistoryItem*> item);
|
[[nodiscard]] bool WhoReadExists(not_null<HistoryItem*> item);
|
||||||
[[nodiscard]] bool WhoReactedExists(not_null<HistoryItem*> item);
|
[[nodiscard]] bool WhoReactedExists(
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
WhoReactedList list);
|
||||||
|
|
||||||
struct WhoReadList {
|
struct WhoReadList {
|
||||||
std::vector<PeerId> list;
|
std::vector<PeerId> list;
|
||||||
|
|
|
@ -77,11 +77,12 @@ constexpr auto kTopReactionsLimit = 10;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
PossibleItemReactions LookupPossibleReactions(not_null<HistoryItem*> item) {
|
PossibleItemReactionsRef LookupPossibleReactions(
|
||||||
|
not_null<HistoryItem*> item) {
|
||||||
if (!item->canReact()) {
|
if (!item->canReact()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
auto result = PossibleItemReactions();
|
auto result = PossibleItemReactionsRef();
|
||||||
const auto peer = item->history()->peer;
|
const auto peer = item->history()->peer;
|
||||||
const auto session = &peer->session();
|
const auto session = &peer->session();
|
||||||
const auto reactions = &session->data().reactions();
|
const auto reactions = &session->data().reactions();
|
||||||
|
@ -157,6 +158,15 @@ PossibleItemReactions LookupPossibleReactions(not_null<HistoryItem*> item) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PossibleItemReactions::PossibleItemReactions(
|
||||||
|
const PossibleItemReactionsRef &other)
|
||||||
|
: recent(other.recent | ranges::views::transform([](const auto &value) {
|
||||||
|
return *value;
|
||||||
|
}) | ranges::to_vector)
|
||||||
|
, morePremiumAvailable(other.morePremiumAvailable)
|
||||||
|
, customAllowed(other.customAllowed) {
|
||||||
|
}
|
||||||
|
|
||||||
Reactions::Reactions(not_null<Session*> owner)
|
Reactions::Reactions(not_null<Session*> owner)
|
||||||
: _owner(owner)
|
: _owner(owner)
|
||||||
, _topRefreshTimer([=] { refreshTop(); })
|
, _topRefreshTimer([=] { refreshTop(); })
|
||||||
|
@ -194,6 +204,10 @@ Reactions::Reactions(not_null<Session*> owner)
|
||||||
|
|
||||||
Reactions::~Reactions() = default;
|
Reactions::~Reactions() = default;
|
||||||
|
|
||||||
|
Main::Session &Reactions::session() const {
|
||||||
|
return _owner->session();
|
||||||
|
}
|
||||||
|
|
||||||
void Reactions::refreshTop() {
|
void Reactions::refreshTop() {
|
||||||
requestTop();
|
requestTop();
|
||||||
}
|
}
|
||||||
|
@ -868,7 +882,7 @@ void MessageReactions::add(const ReactionId &id, bool addToRecent) {
|
||||||
}
|
}
|
||||||
return removed;
|
return removed;
|
||||||
}), end(_list));
|
}), end(_list));
|
||||||
if (_item->canViewReactions()) {
|
if (_item->canViewReactions() || history->peer->isUser()) {
|
||||||
auto &list = _recent[id];
|
auto &list = _recent[id];
|
||||||
list.insert(begin(list), RecentReaction{ self });
|
list.insert(begin(list), RecentReaction{ self });
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,13 +38,22 @@ struct Reaction {
|
||||||
bool premium = false;
|
bool premium = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PossibleItemReactions {
|
struct PossibleItemReactionsRef {
|
||||||
std::vector<not_null<const Reaction*>> recent;
|
std::vector<not_null<const Reaction*>> recent;
|
||||||
bool morePremiumAvailable = false;
|
bool morePremiumAvailable = false;
|
||||||
bool customAllowed = false;
|
bool customAllowed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] PossibleItemReactions LookupPossibleReactions(
|
struct PossibleItemReactions {
|
||||||
|
PossibleItemReactions() = default;
|
||||||
|
explicit PossibleItemReactions(const PossibleItemReactionsRef &other);
|
||||||
|
|
||||||
|
std::vector<Reaction> recent;
|
||||||
|
bool morePremiumAvailable = false;
|
||||||
|
bool customAllowed = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] PossibleItemReactionsRef LookupPossibleReactions(
|
||||||
not_null<HistoryItem*> item);
|
not_null<HistoryItem*> item);
|
||||||
|
|
||||||
class Reactions final : private CustomEmojiManager::Listener {
|
class Reactions final : private CustomEmojiManager::Listener {
|
||||||
|
@ -52,6 +61,11 @@ public:
|
||||||
explicit Reactions(not_null<Session*> owner);
|
explicit Reactions(not_null<Session*> owner);
|
||||||
~Reactions();
|
~Reactions();
|
||||||
|
|
||||||
|
[[nodiscard]] Session &owner() const {
|
||||||
|
return *_owner;
|
||||||
|
}
|
||||||
|
[[nodiscard]] Main::Session &session() const;
|
||||||
|
|
||||||
void refreshTop();
|
void refreshTop();
|
||||||
void refreshRecent();
|
void refreshRecent();
|
||||||
void refreshRecentDelayed();
|
void refreshRecentDelayed();
|
||||||
|
|
|
@ -2011,13 +2011,15 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto hasWhoReactedItem = _dragStateItem
|
const auto hasWhoReactedItem = _dragStateItem
|
||||||
&& Api::WhoReactedExists(_dragStateItem);
|
&& Api::WhoReactedExists(_dragStateItem, Api::WhoReactedList::All);
|
||||||
const auto clickedReaction = link
|
const auto clickedReaction = link
|
||||||
? link->property(
|
? link->property(
|
||||||
kReactionsCountEmojiProperty).value<Data::ReactionId>()
|
kReactionsCountEmojiProperty).value<Data::ReactionId>()
|
||||||
: Data::ReactionId();
|
: Data::ReactionId();
|
||||||
_whoReactedMenuLifetime.destroy();
|
_whoReactedMenuLifetime.destroy();
|
||||||
if (hasWhoReactedItem && !clickedReaction.empty()) {
|
if (!clickedReaction.empty()
|
||||||
|
&& _dragStateItem
|
||||||
|
&& Api::WhoReactedExists(_dragStateItem, Api::WhoReactedList::One)) {
|
||||||
HistoryView::ShowWhoReactedMenu(
|
HistoryView::ShowWhoReactedMenu(
|
||||||
&_menu,
|
&_menu,
|
||||||
e->globalPos(),
|
e->globalPos(),
|
||||||
|
|
|
@ -948,7 +948,8 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto hasSelection = !request.selectedItems.empty()
|
const auto hasSelection = !request.selectedItems.empty()
|
||||||
|| !request.selectedText.empty();
|
|| !request.selectedText.empty();
|
||||||
const auto hasWhoReactedItem = item && Api::WhoReactedExists(item);
|
const auto hasWhoReactedItem = item
|
||||||
|
&& Api::WhoReactedExists(item, Api::WhoReactedList::All);
|
||||||
|
|
||||||
auto result = base::make_unique_q<Ui::PopupMenu>(
|
auto result = base::make_unique_q<Ui::PopupMenu>(
|
||||||
list,
|
list,
|
||||||
|
|
|
@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/media/history_view_custom_emoji.h"
|
#include "history/view/media/history_view_custom_emoji.h"
|
||||||
#include "history/view/reactions/history_view_reactions_animation.h"
|
#include "history/view/reactions/history_view_reactions_animation.h"
|
||||||
#include "history/view/reactions/history_view_reactions_button.h"
|
#include "history/view/reactions/history_view_reactions_button.h"
|
||||||
|
#include "history/view/reactions/history_view_reactions.h"
|
||||||
#include "history/view/history_view_cursor_state.h"
|
#include "history/view/history_view_cursor_state.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
|
@ -430,6 +431,20 @@ void Element::prepareCustomEmojiPaint(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Element::prepareCustomEmojiPaint(
|
||||||
|
Painter &p,
|
||||||
|
const Reactions::InlineList &reactions) const {
|
||||||
|
if (!reactions.hasCustomEmoji()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearCustomEmojiRepaint();
|
||||||
|
p.setInactive(delegate()->elementIsGifPaused());
|
||||||
|
if (!_heavyCustomEmoji) {
|
||||||
|
_heavyCustomEmoji = true;
|
||||||
|
history()->owner().registerHeavyViewPart(const_cast<Element*>(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//void Element::externalLottieProgressing(bool external) const {
|
//void Element::externalLottieProgressing(bool external) const {
|
||||||
// if (const auto media = _media.get()) {
|
// if (const auto media = _media.get()) {
|
||||||
// media->externalLottieProgressing(external);
|
// media->externalLottieProgressing(external);
|
||||||
|
|
|
@ -49,6 +49,7 @@ using PaintContext = Ui::ChatPaintContext;
|
||||||
namespace Reactions {
|
namespace Reactions {
|
||||||
struct ButtonParameters;
|
struct ButtonParameters;
|
||||||
class Animation;
|
class Animation;
|
||||||
|
class InlineList;
|
||||||
} // namespace Reactions
|
} // namespace Reactions
|
||||||
|
|
||||||
enum class Context : char {
|
enum class Context : char {
|
||||||
|
@ -421,6 +422,9 @@ public:
|
||||||
void prepareCustomEmojiPaint(
|
void prepareCustomEmojiPaint(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const Ui::Text::String &text) const;
|
const Ui::Text::String &text) const;
|
||||||
|
void prepareCustomEmojiPaint(
|
||||||
|
Painter &p,
|
||||||
|
const Reactions::InlineList &reactions) const;
|
||||||
void clearCustomEmojiRepaint() const;
|
void clearCustomEmojiRepaint() const;
|
||||||
|
|
||||||
[[nodiscard]] ClickHandlerPtr fromPhotoLink() const {
|
[[nodiscard]] ClickHandlerPtr fromPhotoLink() const {
|
||||||
|
|
|
@ -2210,13 +2210,15 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
? _overElement->data().get()
|
? _overElement->data().get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto hasWhoReactedItem = overItem
|
const auto hasWhoReactedItem = overItem
|
||||||
&& Api::WhoReactedExists(overItem);
|
&& Api::WhoReactedExists(overItem, Api::WhoReactedList::All);
|
||||||
const auto clickedReaction = link
|
const auto clickedReaction = link
|
||||||
? link->property(
|
? link->property(
|
||||||
kReactionsCountEmojiProperty).value<Data::ReactionId>()
|
kReactionsCountEmojiProperty).value<Data::ReactionId>()
|
||||||
: Data::ReactionId();
|
: Data::ReactionId();
|
||||||
_whoReactedMenuLifetime.destroy();
|
_whoReactedMenuLifetime.destroy();
|
||||||
if (hasWhoReactedItem && !clickedReaction.empty()) {
|
if (!clickedReaction.empty()
|
||||||
|
&& overItem
|
||||||
|
&& Api::WhoReactedExists(overItem, Api::WhoReactedList::One)) {
|
||||||
HistoryView::ShowWhoReactedMenu(
|
HistoryView::ShowWhoReactedMenu(
|
||||||
&_menu,
|
&_menu,
|
||||||
e->globalPos(),
|
e->globalPos(),
|
||||||
|
|
|
@ -739,6 +739,7 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
||||||
g.setHeight(g.height() - reactionsHeight);
|
g.setHeight(g.height() - reactionsHeight);
|
||||||
const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
|
const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
|
||||||
p.translate(reactionsPosition);
|
p.translate(reactionsPosition);
|
||||||
|
prepareCustomEmojiPaint(p, *_reactions);
|
||||||
_reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition));
|
_reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition));
|
||||||
if (context.reactionInfo) {
|
if (context.reactionInfo) {
|
||||||
context.reactionInfo->position = reactionsPosition;
|
context.reactionInfo->position = reactionsPosition;
|
||||||
|
@ -794,6 +795,7 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
||||||
trect.setHeight(trect.height() - reactionsHeight);
|
trect.setHeight(trect.height() - reactionsHeight);
|
||||||
const auto reactionsPosition = QPoint(trect.left(), trect.top() + trect.height() + reactionsTop);
|
const auto reactionsPosition = QPoint(trect.left(), trect.top() + trect.height() + reactionsTop);
|
||||||
p.translate(reactionsPosition);
|
p.translate(reactionsPosition);
|
||||||
|
prepareCustomEmojiPaint(p, *_reactions);
|
||||||
_reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition));
|
_reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition));
|
||||||
if (context.reactionInfo) {
|
if (context.reactionInfo) {
|
||||||
context.reactionInfo->position = reactionsPosition;
|
context.reactionInfo->position = reactionsPosition;
|
||||||
|
@ -1385,6 +1387,9 @@ bool Message::hasHeavyPart() const {
|
||||||
|
|
||||||
void Message::unloadHeavyPart() {
|
void Message::unloadHeavyPart() {
|
||||||
Element::unloadHeavyPart();
|
Element::unloadHeavyPart();
|
||||||
|
if (_reactions) {
|
||||||
|
_reactions->unloadCustomEmoji();
|
||||||
|
}
|
||||||
_comments = nullptr;
|
_comments = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2232,6 +2237,7 @@ void Message::refreshReactions() {
|
||||||
_reactions = std::make_unique<InlineList>(
|
_reactions = std::make_unique<InlineList>(
|
||||||
&item->history()->owner().reactions(),
|
&item->history()->owner().reactions(),
|
||||||
handlerFactory,
|
handlerFactory,
|
||||||
|
[=] { customEmojiRepaint(); },
|
||||||
std::move(reactionsData));
|
std::move(reactionsData));
|
||||||
} else {
|
} else {
|
||||||
_reactions->update(std::move(reactionsData), width());
|
_reactions->update(std::move(reactionsData), width());
|
||||||
|
|
|
@ -14,9 +14,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/history_view_cursor_state.h"
|
#include "history/view/history_view_cursor_state.h"
|
||||||
#include "history/view/history_view_group_call_bar.h"
|
#include "history/view/history_view_group_call_bar.h"
|
||||||
#include "core/click_handler_types.h"
|
#include "core/click_handler_types.h"
|
||||||
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
#include "data/data_message_reactions.h"
|
#include "data/data_message_reactions.h"
|
||||||
#include "data/data_peer.h"
|
#include "data/data_peer.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
#include "lang/lang_tag.h"
|
#include "lang/lang_tag.h"
|
||||||
|
#include "ui/text/text_block.h"
|
||||||
#include "ui/chat/chat_style.h"
|
#include "ui/chat/chat_style.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
|
@ -40,6 +43,7 @@ struct InlineList::Button {
|
||||||
mutable std::unique_ptr<Animation> animation;
|
mutable std::unique_ptr<Animation> animation;
|
||||||
mutable QImage image;
|
mutable QImage image;
|
||||||
mutable ClickHandlerPtr link;
|
mutable ClickHandlerPtr link;
|
||||||
|
mutable std::unique_ptr<Ui::Text::CustomEmoji> custom;
|
||||||
std::unique_ptr<Userpics> userpics;
|
std::unique_ptr<Userpics> userpics;
|
||||||
ReactionId id;
|
ReactionId id;
|
||||||
QString countText;
|
QString countText;
|
||||||
|
@ -51,9 +55,11 @@ struct InlineList::Button {
|
||||||
InlineList::InlineList(
|
InlineList::InlineList(
|
||||||
not_null<::Data::Reactions*> owner,
|
not_null<::Data::Reactions*> owner,
|
||||||
Fn<ClickHandlerPtr(ReactionId)> handlerFactory,
|
Fn<ClickHandlerPtr(ReactionId)> handlerFactory,
|
||||||
|
Fn<void()> customEmojiRepaint,
|
||||||
Data &&data)
|
Data &&data)
|
||||||
: _owner(owner)
|
: _owner(owner)
|
||||||
, _handlerFactory(std::move(handlerFactory))
|
, _handlerFactory(std::move(handlerFactory))
|
||||||
|
, _customEmojiRepaint(std::move(customEmojiRepaint))
|
||||||
, _data(std::move(data)) {
|
, _data(std::move(data)) {
|
||||||
layout();
|
layout();
|
||||||
}
|
}
|
||||||
|
@ -76,6 +82,21 @@ void InlineList::removeSkipBlock() {
|
||||||
_skipBlock = {};
|
_skipBlock = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InlineList::hasCustomEmoji() const {
|
||||||
|
return _hasCustomEmoji;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InlineList::unloadCustomEmoji() {
|
||||||
|
if (!hasCustomEmoji()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto &button : _buttons) {
|
||||||
|
if (const auto custom = button.custom.get()) {
|
||||||
|
custom->unload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void InlineList::layout() {
|
void InlineList::layout() {
|
||||||
layoutButtons();
|
layoutButtons();
|
||||||
initDimensions();
|
initDimensions();
|
||||||
|
@ -106,6 +127,7 @@ void InlineList::layoutButtons() {
|
||||||
< ranges::find(list, b->id, &::Data::Reaction::id);
|
< ranges::find(list, b->id, &::Data::Reaction::id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_hasCustomEmoji = false;
|
||||||
auto buttons = std::vector<Button>();
|
auto buttons = std::vector<Button>();
|
||||||
buttons.reserve(sorted.size());
|
buttons.reserve(sorted.size());
|
||||||
for (const auto &reaction : sorted) {
|
for (const auto &reaction : sorted) {
|
||||||
|
@ -121,13 +143,22 @@ void InlineList::layoutButtons() {
|
||||||
setButtonCount(buttons.back(), reaction->count);
|
setButtonCount(buttons.back(), reaction->count);
|
||||||
}
|
}
|
||||||
buttons.back().chosen = reaction->my;
|
buttons.back().chosen = reaction->my;
|
||||||
|
if (id.custom()) {
|
||||||
|
_hasCustomEmoji = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_buttons = std::move(buttons);
|
_buttons = std::move(buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
InlineList::Button InlineList::prepareButtonWithId(const ReactionId &id) {
|
InlineList::Button InlineList::prepareButtonWithId(const ReactionId &id) {
|
||||||
auto result = Button{ .id = id };
|
auto result = Button{ .id = id };
|
||||||
_owner->preloadImageFor(id);
|
if (const auto customId = id.custom()) {
|
||||||
|
result.custom = _owner->owner().customEmojiManager().create(
|
||||||
|
customId,
|
||||||
|
_customEmojiRepaint);
|
||||||
|
} else {
|
||||||
|
_owner->preloadImageFor(id);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,16 +384,44 @@ void InlineList::paint(
|
||||||
p.setOpacity(bubbleProgress);
|
p.setOpacity(bubbleProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (button.image.isNull()) {
|
if (!button.custom && button.image.isNull()) {
|
||||||
button.image = _owner->resolveImageFor(
|
button.image = _owner->resolveImageFor(
|
||||||
button.id,
|
button.id,
|
||||||
::Data::Reactions::ImageSize::InlineList);
|
::Data::Reactions::ImageSize::InlineList);
|
||||||
}
|
}
|
||||||
|
const auto textFg = !inbubble
|
||||||
|
? (chosen
|
||||||
|
? QPen(AdaptChosenServiceFg(st->msgServiceBg()->c))
|
||||||
|
: st->msgServiceFg())
|
||||||
|
: !chosen
|
||||||
|
? stm->msgServiceFg
|
||||||
|
: context.outbg
|
||||||
|
? (context.selected()
|
||||||
|
? st->historyFileOutIconFgSelected()
|
||||||
|
: st->historyFileOutIconFg())
|
||||||
|
: (context.selected()
|
||||||
|
? st->historyFileInIconFgSelected()
|
||||||
|
: st->historyFileInIconFg());
|
||||||
const auto image = QRect(
|
const auto image = QRect(
|
||||||
inner.topLeft() + QPoint(skip, skip),
|
inner.topLeft() + QPoint(skip, skip),
|
||||||
QSize(st::reactionInlineImage, st::reactionInlineImage));
|
QSize(st::reactionInlineImage, st::reactionInlineImage));
|
||||||
if (!button.image.isNull() && !skipImage) {
|
if (!skipImage) {
|
||||||
p.drawImage(image.topLeft(), button.image);
|
if (button.custom) {
|
||||||
|
if (!_customSkip) {
|
||||||
|
using namespace Ui::Text;
|
||||||
|
const auto size = st::emojiSize;
|
||||||
|
_customSkip = (size - AdjustCustomEmojiSize(size)) / 2;
|
||||||
|
}
|
||||||
|
button.custom->paint(p, {
|
||||||
|
.preview = textFg.color(),
|
||||||
|
.now = context.now,
|
||||||
|
.position = (inner.topLeft()
|
||||||
|
+ QPoint(_customSkip, _customSkip)),
|
||||||
|
.paused = p.inactive(),
|
||||||
|
});
|
||||||
|
} else if (!button.image.isNull()) {
|
||||||
|
p.drawImage(image.topLeft(), button.image);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (animating) {
|
if (animating) {
|
||||||
animations.push_back({
|
animations.push_back({
|
||||||
|
@ -381,19 +440,7 @@ void InlineList::paint(
|
||||||
geometry.y() + st::reactionInlineUserpicsPadding.top(),
|
geometry.y() + st::reactionInlineUserpicsPadding.top(),
|
||||||
button.userpics->image);
|
button.userpics->image);
|
||||||
} else {
|
} else {
|
||||||
p.setPen(!inbubble
|
p.setPen(textFg);
|
||||||
? (chosen
|
|
||||||
? QPen(AdaptChosenServiceFg(st->msgServiceBg()->c))
|
|
||||||
: st->msgServiceFg())
|
|
||||||
: !chosen
|
|
||||||
? stm->msgServiceFg
|
|
||||||
: context.outbg
|
|
||||||
? (context.selected()
|
|
||||||
? st->historyFileOutIconFgSelected()
|
|
||||||
: st->historyFileOutIconFg())
|
|
||||||
: (context.selected()
|
|
||||||
? st->historyFileInIconFgSelected()
|
|
||||||
: st->historyFileInIconFg()));
|
|
||||||
const auto textTop = geometry.y()
|
const auto textTop = geometry.y()
|
||||||
+ ((geometry.height() - st::semiboldFont->height) / 2);
|
+ ((geometry.height() - st::semiboldFont->height) / 2);
|
||||||
p.drawText(
|
p.drawText(
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
InlineList(
|
InlineList(
|
||||||
not_null<::Data::Reactions*> owner,
|
not_null<::Data::Reactions*> owner,
|
||||||
Fn<ClickHandlerPtr(ReactionId)> handlerFactory,
|
Fn<ClickHandlerPtr(ReactionId)> handlerFactory,
|
||||||
|
Fn<void()> customEmojiRepaint,
|
||||||
Data &&data);
|
Data &&data);
|
||||||
~InlineList();
|
~InlineList();
|
||||||
|
|
||||||
|
@ -65,6 +66,9 @@ public:
|
||||||
void updateSkipBlock(int width, int height);
|
void updateSkipBlock(int width, int height);
|
||||||
void removeSkipBlock();
|
void removeSkipBlock();
|
||||||
|
|
||||||
|
[[nodiscard]] bool hasCustomEmoji() const;
|
||||||
|
void unloadCustomEmoji();
|
||||||
|
|
||||||
void paint(
|
void paint(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const PaintContext &context,
|
const PaintContext &context,
|
||||||
|
@ -105,9 +109,12 @@ private:
|
||||||
|
|
||||||
const not_null<::Data::Reactions*> _owner;
|
const not_null<::Data::Reactions*> _owner;
|
||||||
const Fn<ClickHandlerPtr(ReactionId)> _handlerFactory;
|
const Fn<ClickHandlerPtr(ReactionId)> _handlerFactory;
|
||||||
|
const Fn<void()> _customEmojiRepaint;
|
||||||
Data _data;
|
Data _data;
|
||||||
std::vector<Button> _buttons;
|
std::vector<Button> _buttons;
|
||||||
QSize _skipBlock;
|
QSize _skipBlock;
|
||||||
|
mutable int _customSkip = 0;
|
||||||
|
bool _hasCustomEmoji = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -441,7 +441,7 @@ void Manager::showButtonDelayed() {
|
||||||
[=]{ updateButton({}); });
|
[=]{ updateButton({}); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::applyList(Data::PossibleItemReactions &&reactions) {
|
void Manager::applyList(const Data::PossibleItemReactionsRef &reactions) {
|
||||||
using Button = Strip::AddedButton;
|
using Button = Strip::AddedButton;
|
||||||
_strip.applyList(
|
_strip.applyList(
|
||||||
reactions.recent,
|
reactions.recent,
|
||||||
|
|
|
@ -23,7 +23,7 @@ class PopupMenu;
|
||||||
namespace Data {
|
namespace Data {
|
||||||
struct ReactionId;
|
struct ReactionId;
|
||||||
struct Reaction;
|
struct Reaction;
|
||||||
struct PossibleItemReactions;
|
struct PossibleItemReactionsRef;
|
||||||
class DocumentMedia;
|
class DocumentMedia;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ public:
|
||||||
|
|
||||||
using ReactionId = ::Data::ReactionId;
|
using ReactionId = ::Data::ReactionId;
|
||||||
|
|
||||||
void applyList(Data::PossibleItemReactions &&reactions);
|
void applyList(const Data::PossibleItemReactionsRef &reactions);
|
||||||
|
|
||||||
void updateButton(ButtonParameters parameters);
|
void updateButton(ButtonParameters parameters);
|
||||||
void paint(Painter &p, const PaintContext &context);
|
void paint(Painter &p, const PaintContext &context);
|
||||||
|
|
|
@ -144,12 +144,12 @@ bool StripEmoji::ready() {
|
||||||
Selector::Selector(
|
Selector::Selector(
|
||||||
not_null<QWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::SessionController*> parentController,
|
not_null<Window::SessionController*> parentController,
|
||||||
Data::PossibleItemReactions &&reactions,
|
const Data::PossibleItemReactionsRef &reactions,
|
||||||
IconFactory iconFactory,
|
IconFactory iconFactory,
|
||||||
Fn<void(bool fast)> close)
|
Fn<void(bool fast)> close)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _parentController(parentController.get())
|
, _parentController(parentController.get())
|
||||||
, _reactions(std::move(reactions))
|
, _reactions(reactions)
|
||||||
, _jumpedToPremium([=] { close(false); })
|
, _jumpedToPremium([=] { close(false); })
|
||||||
, _cachedRound(
|
, _cachedRound(
|
||||||
QSize(2 * st::reactStripSkip + st::reactStripSize, st::reactStripHeight),
|
QSize(2 * st::reactStripSkip + st::reactStripSize, st::reactStripHeight),
|
||||||
|
@ -198,14 +198,21 @@ int Selector::countWidth(int desiredWidth, int maxWidth) {
|
||||||
: _reactions.morePremiumAvailable
|
: _reactions.morePremiumAvailable
|
||||||
? Strip::AddedButton::Premium
|
? Strip::AddedButton::Premium
|
||||||
: Strip::AddedButton::None;
|
: Strip::AddedButton::None;
|
||||||
|
const auto &real = _reactions.recent;
|
||||||
|
auto list = std::vector<not_null<const Data::Reaction*>>();
|
||||||
|
list.reserve(_columns);
|
||||||
if (const auto cut = max - _columns) {
|
if (const auto cut = max - _columns) {
|
||||||
_strip.applyList(ranges::make_subrange(
|
const auto from = begin(real);
|
||||||
begin(_reactions.recent),
|
const auto till = end(real) - (cut + (addedToMax ? 0 : 1));
|
||||||
end(_reactions.recent) - (cut + (addedToMax ? 0 : 1))
|
for (auto i = from; i != till; ++i) {
|
||||||
) | ranges::to_vector, added);
|
list.push_back(&*i);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_strip.applyList(_reactions.recent, added);
|
for (const auto &reaction : real) {
|
||||||
|
list.push_back(&reaction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_strip.applyList(list, added);
|
||||||
_strip.clearAppearAnimations(false);
|
_strip.clearAppearAnimations(false);
|
||||||
return std::max(2 * _skipx + _columns * _size, desiredWidth);
|
return std::max(2 * _skipx + _columns * _size, desiredWidth);
|
||||||
}
|
}
|
||||||
|
@ -583,11 +590,11 @@ void Selector::createList(not_null<Window::SessionController*> controller) {
|
||||||
auto index = 0;
|
auto index = 0;
|
||||||
const auto inStrip = _strip.count();
|
const auto inStrip = _strip.count();
|
||||||
for (const auto &reaction : _reactions.recent) {
|
for (const auto &reaction : _reactions.recent) {
|
||||||
if (const auto id = reaction->id.custom()) {
|
if (const auto id = reaction.id.custom()) {
|
||||||
recent.push_back(id);
|
recent.push_back(id);
|
||||||
} else {
|
} else {
|
||||||
recent.push_back(reaction->selectAnimation->id);
|
recent.push_back(reaction.selectAnimation->id);
|
||||||
defaultReactionIds.emplace(recent.back(), reaction->id.emoji());
|
defaultReactionIds.emplace(recent.back(), reaction.id.emoji());
|
||||||
}
|
}
|
||||||
if (index + 1 < inStrip) {
|
if (index + 1 < inStrip) {
|
||||||
_defaultReactionInStripMap.emplace(recent.back(), index++);
|
_defaultReactionInStripMap.emplace(recent.back(), index++);
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
Selector(
|
Selector(
|
||||||
not_null<QWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::SessionController*> parentController,
|
not_null<Window::SessionController*> parentController,
|
||||||
Data::PossibleItemReactions &&reactions,
|
const Data::PossibleItemReactionsRef &reactions,
|
||||||
IconFactory iconFactory,
|
IconFactory iconFactory,
|
||||||
Fn<void(bool fast)> close);
|
Fn<void(bool fast)> close);
|
||||||
|
|
||||||
|
|
|
@ -1027,14 +1027,14 @@ sendAsButton: SendAsButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
reactionInlinePadding: margins(5px, 2px, 7px, 2px);
|
reactionInlinePadding: margins(5px, 2px, 7px, 2px);
|
||||||
reactionInlineSize: 16px;
|
reactionInlineSize: 18px;
|
||||||
reactionInlineImage: 28px;
|
reactionInlineImage: 32px;
|
||||||
reactionInlineSkip: 3px;
|
reactionInlineSkip: 3px;
|
||||||
reactionInlineBetween: 4px;
|
reactionInlineBetween: 4px;
|
||||||
reactionInlineInBubbleLeft: -3px;
|
reactionInlineInBubbleLeft: -3px;
|
||||||
reactionInlineUserpicsPadding: margins(1px, 1px, 1px, 1px);
|
reactionInlineUserpicsPadding: margins(1px, 1px, 1px, 1px);
|
||||||
reactionInlineUserpics: GroupCallUserpics {
|
reactionInlineUserpics: GroupCallUserpics {
|
||||||
size: 18px;
|
size: 20px;
|
||||||
shift: 7px;
|
shift: 7px;
|
||||||
stroke: 1px;
|
stroke: 1px;
|
||||||
align: align(left);
|
align: align(left);
|
||||||
|
|
Loading…
Add table
Reference in a new issue