Make all custom emoji in messages clickable.

This commit is contained in:
John Preston
2026-02-05 23:11:56 +04:00
parent 27db7eee26
commit 737ea42698
4 changed files with 94 additions and 8 deletions
+61 -5
View File
@@ -56,6 +56,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
#include "ui/widgets/popup_menu.h"
#include "ui/widgets/scroll_area.h"
#include "window/window_session_controller.h"
#include "styles/style_layers.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_info.h"
@@ -288,6 +289,7 @@ public:
[[nodiscard]] uint64 setId() const;
void install();
void showPreviewForDocument(DocumentId documentId);
[[nodiscard]] rpl::producer<uint64> setInstalled() const;
[[nodiscard]] rpl::producer<uint64> setArchived() const;
[[nodiscard]] rpl::producer<> updateControls() const;
@@ -466,6 +468,8 @@ private:
base::Timer _previewTimer;
int _previewShown = -1;
DocumentId _previewDocumentId = 0;
bool _previewLocked = false;
base::unique_qptr<Ui::PopupMenu> _menu;
@@ -480,11 +484,13 @@ StickerSetBox::StickerSetBox(
QWidget *parent,
std::shared_ptr<ChatHelpers::Show> show,
const StickerSetIdentifier &set,
Data::StickersType type)
Data::StickersType type,
DocumentId previewDocumentId)
: _show(std::move(show))
, _session(&_show->session())
, _set(set)
, _type(type) {
, _type(type)
, _previewDocumentId(previewDocumentId) {
}
StickerSetBox::StickerSetBox(
@@ -496,13 +502,15 @@ StickerSetBox::StickerSetBox(
base::weak_qptr<Ui::BoxContent> StickerSetBox::Show(
std::shared_ptr<ChatHelpers::Show> show,
not_null<DocumentData*> document) {
not_null<DocumentData*> document,
DocumentId previewDocumentId) {
if (const auto sticker = document->sticker()) {
if (sticker->set) {
auto box = Box<StickerSetBox>(
show,
sticker->set,
sticker->setType);
sticker->setType,
previewDocumentId);
const auto result = base::make_weak(box.data());
show->showBox(std::move(box));
return result;
@@ -517,6 +525,9 @@ void StickerSetBox::prepare() {
_inner = setInnerWidget(
object_ptr<Inner>(this, _show, _set, _type),
st::stickersScroll);
if (const auto previewId = base::take(_previewDocumentId)) {
_inner->showPreviewForDocument(previewId);
}
_session->data().stickers().updated(
_type
) | rpl::on_next([=] {
@@ -587,6 +598,13 @@ void StickerSetBox::prepare() {
closeBox();
}, lifetime());
boxClosing(
) | rpl::on_next([show = _show] {
if (const auto window = show->resolveWindow()) {
window->widget()->hideMediaPreview();
}
}, lifetime());
}
void StickerSetBox::addStickers() {
@@ -1021,6 +1039,9 @@ void StickerSetBox::Inner::applySet(const TLStickerSet &set) {
_padding.top() + _rowsCount * _singleSize.height() + _padding.bottom());
_loaded = true;
if (const auto previewId = base::take(_previewDocumentId)) {
showPreviewForDocument(previewId);
}
updateSelected();
_updateControls.fire({});
}
@@ -1137,6 +1158,14 @@ void StickerSetBox::Inner::installDone(
}
void StickerSetBox::Inner::mousePressEvent(QMouseEvent *e) {
if (_previewLocked) {
_previewLocked = false;
_previewShown = -1;
if (const auto window = _show->resolveWindow()) {
window->widget()->hideMediaPreview();
}
return;
}
if (e->button() != Qt::LeftButton) {
return;
}
@@ -1238,7 +1267,7 @@ void StickerSetBox::Inner::mouseMoveEvent(QMouseEvent *e) {
}
update();
}
if (_previewShown >= 0) {
if (_previewShown >= 0 && !_previewLocked) {
showPreviewAt(e->globalPos());
}
}
@@ -1255,6 +1284,27 @@ void StickerSetBox::Inner::showPreviewAt(QPoint globalPos) {
}
}
void StickerSetBox::Inner::showPreviewForDocument(DocumentId documentId) {
if (!_loaded) {
_previewDocumentId = documentId;
return;
}
const auto it = ranges::find(
_pack,
documentId,
&DocumentData::id);
if (it != _pack.end()) {
const auto index = int(it - _pack.begin());
if (index != _previewShown) {
_previewShown = index;
_previewLocked = true;
_show->showMediaPreview(
Data::FileOriginStickerSet(_setId, _setAccessHash),
_pack[index]);
}
}
}
void StickerSetBox::Inner::leaveEventHook(QEvent *e) {
setSelected(-1);
}
@@ -1340,6 +1390,12 @@ void StickerSetBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
kStickerMoveDuration);
}
if (_previewShown >= 0) {
if (_previewLocked) {
_previewLocked = false;
if (const auto window = _show->resolveWindow()) {
window->widget()->hideMediaPreview();
}
}
_previewShown = -1;
return;
}
+5 -2
View File
@@ -64,7 +64,8 @@ public:
QWidget*,
std::shared_ptr<ChatHelpers::Show> show,
const StickerSetIdentifier &set,
Data::StickersType type);
Data::StickersType type,
DocumentId previewDocumentId = 0);
StickerSetBox(
QWidget*,
std::shared_ptr<ChatHelpers::Show> show,
@@ -72,7 +73,8 @@ public:
static base::weak_qptr<Ui::BoxContent> Show(
std::shared_ptr<ChatHelpers::Show> show,
not_null<DocumentData*> document);
not_null<DocumentData*> document,
DocumentId previewDocumentId = 0);
protected:
void prepare() override;
@@ -97,5 +99,6 @@ private:
class Inner;
QPointer<Inner> _inner;
DocumentId _previewDocumentId = 0;
};
@@ -7,10 +7,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "history/view/history_view_text_helper.h"
#include "boxes/sticker_set_box.h"
#include "core/click_handler_types.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "data/stickers/data_custom_emoji.h"
#include "history/view/history_view_element.h"
#include "history/history.h"
#include "main/main_session.h"
#include "window/window_session_controller.h"
#include "base/weak_ptr.h"
namespace HistoryView {
@@ -36,6 +41,28 @@ void InitElementTextPart(not_null<Element*> view, Ui::Text::String &text) {
}
});
}
if (text.hasCustomEmoji()) {
text.setCustomEmojiClickHandler(
[](QStringView entityData) {
return Data::ParseCustomEmojiData(entityData) != 0;
},
[weak = base::make_weak(view)](
QStringView entityData,
ClickContext context) {
const auto view = weak.get();
if (!view) {
return;
}
const auto my = context.other.value<ClickHandlerContext>();
if (const auto controller = my.sessionWindow.get()) {
const auto documentId = Data::ParseCustomEmojiData(entityData);
if (documentId) {
const auto document = controller->session().data().document(documentId);
StickerSetBox::Show(controller->uiShow(), document, documentId);
}
}
});
}
}
} // namespace HistoryView