mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Show external reply media preview.
This commit is contained in:
parent
4e0490494e
commit
537c656ee1
8 changed files with 96 additions and 36 deletions
|
@ -86,9 +86,16 @@ struct FileReferenceAccumulator {
|
||||||
}, [](const auto &data) {
|
}, [](const auto &data) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
void push(const MTPMessageReplyHeader &data) {
|
||||||
|
data.match([&](const MTPDmessageReplyHeader &data) {
|
||||||
|
push(data.vreply_media());
|
||||||
|
}, [](const MTPDmessageReplyStoryHeader &data) {
|
||||||
|
});
|
||||||
|
}
|
||||||
void push(const MTPMessage &data) {
|
void push(const MTPMessage &data) {
|
||||||
data.match([&](const MTPDmessage &data) {
|
data.match([&](const MTPDmessage &data) {
|
||||||
push(data.vmedia());
|
push(data.vmedia());
|
||||||
|
push(data.vreply_to());
|
||||||
}, [&](const MTPDmessageService &data) {
|
}, [&](const MTPDmessageService &data) {
|
||||||
data.vaction().match(
|
data.vaction().match(
|
||||||
[&](const MTPDmessageActionChatEditPhoto &data) {
|
[&](const MTPDmessageActionChatEditPhoto &data) {
|
||||||
|
@ -99,6 +106,7 @@ struct FileReferenceAccumulator {
|
||||||
push(data.vwallpaper());
|
push(data.vwallpaper());
|
||||||
}, [](const auto &data) {
|
}, [](const auto &data) {
|
||||||
});
|
});
|
||||||
|
push(data.vreply_to());
|
||||||
}, [](const MTPDmessageEmpty &data) {
|
}, [](const MTPDmessageEmpty &data) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -705,7 +705,7 @@ ItemPreview MediaPhoto::toPreview(ToPreviewOptions options) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto type = tr::lng_in_dlg_photo(tr::now);
|
const auto type = tr::lng_in_dlg_photo(tr::now);
|
||||||
const auto caption = options.hideCaption
|
const auto caption = (options.hideCaption || options.ignoreMessageText)
|
||||||
? TextWithEntities()
|
? TextWithEntities()
|
||||||
: options.translated
|
: options.translated
|
||||||
? parent()->translatedText()
|
? parent()->translatedText()
|
||||||
|
@ -951,7 +951,7 @@ ItemPreview MediaFile::toPreview(ToPreviewOptions options) const {
|
||||||
}
|
}
|
||||||
return tr::lng_in_dlg_file(tr::now);
|
return tr::lng_in_dlg_file(tr::now);
|
||||||
}();
|
}();
|
||||||
const auto caption = options.hideCaption
|
const auto caption = (options.hideCaption || options.ignoreMessageText)
|
||||||
? TextWithEntities()
|
? TextWithEntities()
|
||||||
: options.translated
|
: options.translated
|
||||||
? parent()->translatedText()
|
? parent()->translatedText()
|
||||||
|
@ -1500,7 +1500,9 @@ bool MediaWebPage::replyPreviewLoaded() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemPreview MediaWebPage::toPreview(ToPreviewOptions options) const {
|
ItemPreview MediaWebPage::toPreview(ToPreviewOptions options) const {
|
||||||
auto text = options.translated
|
auto text = options.ignoreMessageText
|
||||||
|
? TextWithEntities()
|
||||||
|
: options.translated
|
||||||
? parent()->translatedText()
|
? parent()->translatedText()
|
||||||
: parent()->originalText();
|
: parent()->originalText();
|
||||||
if (text.empty()) {
|
if (text.empty()) {
|
||||||
|
@ -2038,28 +2040,23 @@ MediaStory::MediaStory(
|
||||||
owner->registerStoryItem(storyId, parent);
|
owner->registerStoryItem(storyId, parent);
|
||||||
|
|
||||||
const auto stories = &owner->stories();
|
const auto stories = &owner->stories();
|
||||||
if (const auto maybeStory = stories->lookup(storyId)) {
|
const auto maybeStory = stories->lookup(storyId);
|
||||||
if (!_mention) {
|
if (!maybeStory && maybeStory.error() == NoStory::Unknown) {
|
||||||
parent->setText((*maybeStory)->caption());
|
stories->resolve(storyId, crl::guard(this, [=] {
|
||||||
}
|
if (const auto maybeStory = stories->lookup(storyId)) {
|
||||||
} else {
|
if (!_mention && _viewMayExist) {
|
||||||
if (maybeStory.error() == NoStory::Unknown) {
|
parent->setText((*maybeStory)->caption());
|
||||||
stories->resolve(storyId, crl::guard(this, [=] {
|
|
||||||
if (const auto maybeStory = stories->lookup(storyId)) {
|
|
||||||
if (!_mention) {
|
|
||||||
parent->setText((*maybeStory)->caption());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_expired = true;
|
|
||||||
}
|
}
|
||||||
if (_mention) {
|
} else {
|
||||||
parent->updateStoryMentionText();
|
_expired = true;
|
||||||
}
|
}
|
||||||
parent->history()->owner().requestItemViewRefresh(parent);
|
if (_mention) {
|
||||||
}));
|
parent->updateStoryMentionText();
|
||||||
} else {
|
}
|
||||||
_expired = true;
|
parent->history()->owner().requestItemViewRefresh(parent);
|
||||||
}
|
}));
|
||||||
|
} else if (!maybeStory) {
|
||||||
|
_expired = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2154,6 +2151,7 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
|
||||||
if (_mention) {
|
if (_mention) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
_viewMayExist = true;
|
||||||
return std::make_unique<HistoryView::Photo>(
|
return std::make_unique<HistoryView::Photo>(
|
||||||
message,
|
message,
|
||||||
realParent,
|
realParent,
|
||||||
|
@ -2161,6 +2159,7 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
|
||||||
spoiler);
|
spoiler);
|
||||||
}
|
}
|
||||||
_expired = false;
|
_expired = false;
|
||||||
|
_viewMayExist = true;
|
||||||
const auto story = *maybeStory;
|
const auto story = *maybeStory;
|
||||||
if (_mention) {
|
if (_mention) {
|
||||||
return std::make_unique<HistoryView::ServiceBox>(
|
return std::make_unique<HistoryView::ServiceBox>(
|
||||||
|
|
|
@ -623,6 +623,7 @@ public:
|
||||||
private:
|
private:
|
||||||
const FullStoryId _storyId;
|
const FullStoryId _storyId;
|
||||||
const bool _mention = false;
|
const bool _mention = false;
|
||||||
|
bool _viewMayExist = false;
|
||||||
bool _expired = false;
|
bool _expired = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -451,7 +451,7 @@ HistoryItem::HistoryItem(
|
||||||
config.reply.topicPost = (topicRootId != 0);
|
config.reply.topicPost = (topicRootId != 0);
|
||||||
if (const auto originalReply = original->Get<HistoryMessageReply>()) {
|
if (const auto originalReply = original->Get<HistoryMessageReply>()) {
|
||||||
if (originalReply->external()) {
|
if (originalReply->external()) {
|
||||||
config.reply = originalReply->fields();
|
config.reply = originalReply->fields().clone(this);
|
||||||
if (!config.reply.externalPeerId) {
|
if (!config.reply.externalPeerId) {
|
||||||
config.reply.messageId = 0;
|
config.reply.messageId = 0;
|
||||||
}
|
}
|
||||||
|
@ -3133,7 +3133,7 @@ void HistoryItem::createComponents(CreateConfig &&config) {
|
||||||
UpdateComponents(mask);
|
UpdateComponents(mask);
|
||||||
|
|
||||||
if (const auto reply = Get<HistoryMessageReply>()) {
|
if (const auto reply = Get<HistoryMessageReply>()) {
|
||||||
reply->set(config.reply);
|
reply->set(std::move(config.reply));
|
||||||
if (!reply->updateData(this)) {
|
if (!reply->updateData(this)) {
|
||||||
if (const auto messageId = reply->messageId()) {
|
if (const auto messageId = reply->messageId()) {
|
||||||
RequestDependentMessageItem(
|
RequestDependentMessageItem(
|
||||||
|
@ -3456,7 +3456,7 @@ void HistoryItem::createComponents(const MTPDmessage &data) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (const auto reply = data.vreply_to()) {
|
if (const auto reply = data.vreply_to()) {
|
||||||
config.reply = ReplyFieldsFromMTP(history(), *reply);
|
config.reply = ReplyFieldsFromMTP(this, *reply);
|
||||||
}
|
}
|
||||||
config.viaBotId = data.vvia_bot_id().value_or_empty();
|
config.viaBotId = data.vvia_bot_id().value_or_empty();
|
||||||
config.viewsCount = data.vviews().value_or(-1);
|
config.viewsCount = data.vviews().value_or(-1);
|
||||||
|
|
|
@ -270,15 +270,33 @@ void HistoryMessageForwarded::create(const HistoryMessageVia *via) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReplyFields ReplyFields::clone(not_null<HistoryItem*> parent) const {
|
||||||
|
return {
|
||||||
|
.quote = quote,
|
||||||
|
.externalMedia = (externalMedia
|
||||||
|
? externalMedia->clone(parent)
|
||||||
|
: nullptr),
|
||||||
|
.externalSenderId = externalSenderId,
|
||||||
|
.externalSenderName = externalSenderName,
|
||||||
|
.externalPostAuthor = externalPostAuthor,
|
||||||
|
.externalPeerId = externalPeerId,
|
||||||
|
.messageId = messageId,
|
||||||
|
.topMessageId = topMessageId,
|
||||||
|
.storyId = storyId,
|
||||||
|
.topicPost = topicPost,
|
||||||
|
.manualQuote = manualQuote,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
ReplyFields ReplyFieldsFromMTP(
|
ReplyFields ReplyFieldsFromMTP(
|
||||||
not_null<History*> history,
|
not_null<HistoryItem*> item,
|
||||||
const MTPMessageReplyHeader &reply) {
|
const MTPMessageReplyHeader &reply) {
|
||||||
return reply.match([&](const MTPDmessageReplyHeader &data) {
|
return reply.match([&](const MTPDmessageReplyHeader &data) {
|
||||||
auto result = ReplyFields();
|
auto result = ReplyFields();
|
||||||
if (const auto peer = data.vreply_to_peer_id()) {
|
if (const auto peer = data.vreply_to_peer_id()) {
|
||||||
result.externalPeerId = peerFromMTP(*peer);
|
result.externalPeerId = peerFromMTP(*peer);
|
||||||
}
|
}
|
||||||
const auto owner = &history->owner();
|
const auto owner = &item->history()->owner();
|
||||||
if (const auto id = data.vreply_to_msg_id().value_or_empty()) {
|
if (const auto id = data.vreply_to_msg_id().value_or_empty()) {
|
||||||
result.messageId = data.is_reply_to_scheduled()
|
result.messageId = data.is_reply_to_scheduled()
|
||||||
? owner->scheduledMessages().localMessageId(id)
|
? owner->scheduledMessages().localMessageId(id)
|
||||||
|
@ -297,6 +315,9 @@ ReplyFields ReplyFieldsFromMTP(
|
||||||
result.externalSenderName
|
result.externalSenderName
|
||||||
= qs(data.vfrom_name().value_or_empty());
|
= qs(data.vfrom_name().value_or_empty());
|
||||||
}
|
}
|
||||||
|
if (const auto media = data.vreply_media()) {
|
||||||
|
result.externalMedia = HistoryItem::CreateMedia(item, *media);
|
||||||
|
}
|
||||||
result.quote = TextWithEntities{
|
result.quote = TextWithEntities{
|
||||||
qs(data.vquote_text().value_or_empty()),
|
qs(data.vquote_text().value_or_empty()),
|
||||||
Api::EntitiesFromMTP(
|
Api::EntitiesFromMTP(
|
||||||
|
@ -357,6 +378,7 @@ HistoryMessageReply &HistoryMessageReply::operator=(
|
||||||
HistoryMessageReply::~HistoryMessageReply() {
|
HistoryMessageReply::~HistoryMessageReply() {
|
||||||
// clearData() should be called by holder.
|
// clearData() should be called by holder.
|
||||||
Expects(resolvedMessage.empty());
|
Expects(resolvedMessage.empty());
|
||||||
|
_fields.externalMedia = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryMessageReply::updateData(
|
bool HistoryMessageReply::updateData(
|
||||||
|
@ -407,7 +429,8 @@ bool HistoryMessageReply::updateData(
|
||||||
|
|
||||||
const auto displaying = resolvedMessage
|
const auto displaying = resolvedMessage
|
||||||
|| resolvedStory
|
|| resolvedStory
|
||||||
|| (!_fields.quote.empty() && (!_fields.messageId || force));
|
|| ((!_fields.quote.empty() || _fields.externalMedia)
|
||||||
|
&& (!_fields.messageId || force));
|
||||||
_displaying = displaying ? 1 : 0;
|
_displaying = displaying ? 1 : 0;
|
||||||
|
|
||||||
const auto unavailable = !resolvedMessage
|
const auto unavailable = !resolvedMessage
|
||||||
|
|
|
@ -233,7 +233,10 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ReplyFields {
|
struct ReplyFields {
|
||||||
|
ReplyFields clone(not_null<HistoryItem*> parent) const;
|
||||||
|
|
||||||
TextWithEntities quote;
|
TextWithEntities quote;
|
||||||
|
std::unique_ptr<Data::Media> externalMedia;
|
||||||
PeerId externalSenderId = 0;
|
PeerId externalSenderId = 0;
|
||||||
QString externalSenderName;
|
QString externalSenderName;
|
||||||
QString externalPostAuthor;
|
QString externalPostAuthor;
|
||||||
|
@ -246,7 +249,7 @@ struct ReplyFields {
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] ReplyFields ReplyFieldsFromMTP(
|
[[nodiscard]] ReplyFields ReplyFieldsFromMTP(
|
||||||
not_null<History*> history,
|
not_null<HistoryItem*> item,
|
||||||
const MTPMessageReplyHeader &reply);
|
const MTPMessageReplyHeader &reply);
|
||||||
|
|
||||||
[[nodiscard]] FullReplyTo ReplyToFromMTP(
|
[[nodiscard]] FullReplyTo ReplyToFromMTP(
|
||||||
|
|
|
@ -40,6 +40,7 @@ struct ToPreviewOptions {
|
||||||
const std::vector<ItemPreviewImage> *existing = nullptr;
|
const std::vector<ItemPreviewImage> *existing = nullptr;
|
||||||
bool hideSender = false;
|
bool hideSender = false;
|
||||||
bool hideCaption = false;
|
bool hideCaption = false;
|
||||||
|
bool ignoreMessageText = false;
|
||||||
bool generateImages = true;
|
bool generateImages = true;
|
||||||
bool ignoreGroup = false;
|
bool ignoreGroup = false;
|
||||||
bool ignoreTopic = true;
|
bool ignoreTopic = true;
|
||||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_story.h"
|
#include "data/data_story.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
|
#include "history/view/history_view_item_preview.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "history/history_item_components.h"
|
#include "history/history_item_components.h"
|
||||||
|
@ -176,6 +177,7 @@ void Reply::update(
|
||||||
const auto &fields = data->fields();
|
const auto &fields = data->fields();
|
||||||
const auto message = data->resolvedMessage.get();
|
const auto message = data->resolvedMessage.get();
|
||||||
const auto story = data->resolvedStory.get();
|
const auto story = data->resolvedStory.get();
|
||||||
|
const auto externalMedia = fields.externalMedia.get();
|
||||||
if (!_externalSender) {
|
if (!_externalSender) {
|
||||||
if (const auto id = fields.externalSenderId) {
|
if (const auto id = fields.externalSenderId) {
|
||||||
_externalSender = view->history()->owner().peer(id);
|
_externalSender = view->history()->owner().peer(id);
|
||||||
|
@ -195,7 +197,8 @@ void Reply::update(
|
||||||
const auto hasPreview = (story && story->hasReplyPreview())
|
const auto hasPreview = (story && story->hasReplyPreview())
|
||||||
|| (message
|
|| (message
|
||||||
&& message->media()
|
&& message->media()
|
||||||
&& message->media()->hasReplyPreview());
|
&& message->media()->hasReplyPreview())
|
||||||
|
|| (externalMedia && externalMedia->hasReplyPreview());
|
||||||
_hasPreview = hasPreview ? 1 : 0;
|
_hasPreview = hasPreview ? 1 : 0;
|
||||||
_displaying = data->displaying() ? 1 : 0;
|
_displaying = data->displaying() ? 1 : 0;
|
||||||
_multiline = data->multiline() ? 1 : 0;
|
_multiline = data->multiline() ? 1 : 0;
|
||||||
|
@ -213,6 +216,15 @@ void Reply::update(
|
||||||
? message->inReplyText()
|
? message->inReplyText()
|
||||||
: story
|
: story
|
||||||
? story->inReplyText()
|
? story->inReplyText()
|
||||||
|
: externalMedia
|
||||||
|
? externalMedia->toPreview({
|
||||||
|
.hideSender = true,
|
||||||
|
.hideCaption = true,
|
||||||
|
.ignoreMessageText = true,
|
||||||
|
.generateImages = false,
|
||||||
|
.ignoreGroup = true,
|
||||||
|
.ignoreTopic = true,
|
||||||
|
}).text
|
||||||
: TextWithEntities();
|
: TextWithEntities();
|
||||||
const auto repaint = [=] { item->customEmojiRepaint(); };
|
const auto repaint = [=] { item->customEmojiRepaint(); };
|
||||||
const auto context = Core::MarkedTextContext{
|
const auto context = Core::MarkedTextContext{
|
||||||
|
@ -222,7 +234,7 @@ void Reply::update(
|
||||||
_text.setMarkedText(
|
_text.setMarkedText(
|
||||||
st::defaultTextStyle,
|
st::defaultTextStyle,
|
||||||
text,
|
text,
|
||||||
Ui::DialogTextOptions(),
|
_multiline ? Ui::ItemTextDefaultOptions() : Ui::DialogTextOptions(),
|
||||||
context);
|
context);
|
||||||
|
|
||||||
updateName(view, data);
|
updateName(view, data);
|
||||||
|
@ -388,7 +400,9 @@ void Reply::updateName(
|
||||||
const auto externalPeer = fields.externalPeerId
|
const auto externalPeer = fields.externalPeerId
|
||||||
? view->history()->owner().peer(fields.externalPeerId).get()
|
? view->history()->owner().peer(fields.externalPeerId).get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto groupNameAdded = (externalPeer && externalPeer != sender);
|
const auto groupNameAdded = externalPeer
|
||||||
|
&& (externalPeer != sender)
|
||||||
|
&& (externalPeer->isChat() || externalPeer->isMegagroup());
|
||||||
const auto shorten = !viaBotUsername.isEmpty() || groupNameAdded;
|
const auto shorten = !viaBotUsername.isEmpty() || groupNameAdded;
|
||||||
const auto name = sender
|
const auto name = sender
|
||||||
? senderName(sender, shorten)
|
? senderName(sender, shorten)
|
||||||
|
@ -508,10 +522,16 @@ int Reply::resizeToWidth(int width) const {
|
||||||
auto elided = false;
|
auto elided = false;
|
||||||
const auto texth = _text.countDimensions(
|
const auto texth = _text.countDimensions(
|
||||||
textGeometry(innerw, firstLineSkip, &lineCounter, &elided)).height;
|
textGeometry(innerw, firstLineSkip, &lineCounter, &elided)).height;
|
||||||
|
const auto useh = elided
|
||||||
|
? (kNonExpandedLinesLimit * st::normalFont->height)
|
||||||
|
: std::max(texth, st::normalFont->height);
|
||||||
|
if (!texth) {
|
||||||
|
int a = 0;
|
||||||
|
}
|
||||||
_expandable = (_multiline && elided) ? 1 : 0;
|
_expandable = (_multiline && elided) ? 1 : 0;
|
||||||
_height = st::historyReplyPadding.top()
|
_height = st::historyReplyPadding.top()
|
||||||
+ nameh
|
+ nameh
|
||||||
+ (elided ? kNonExpandedLinesLimit * st::normalFont->height : texth)
|
+ useh
|
||||||
+ st::historyReplyPadding.bottom();
|
+ st::historyReplyPadding.bottom();
|
||||||
return height();
|
return height();
|
||||||
}
|
}
|
||||||
|
@ -551,7 +571,10 @@ QSize Reply::countMultilineOptimalSize(
|
||||||
const auto max = previewSkip + _text.maxWidth();
|
const auto max = previewSkip + _text.maxWidth();
|
||||||
const auto result = _text.countDimensions(
|
const auto result = _text.countDimensions(
|
||||||
textGeometry(max, previewSkip, &lineCounter, &elided));
|
textGeometry(max, previewSkip, &lineCounter, &elided));
|
||||||
return { result.width, result.height };
|
return {
|
||||||
|
result.width,
|
||||||
|
std::max(result.height, st::normalFont->height),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reply::paint(
|
void Reply::paint(
|
||||||
|
@ -663,6 +686,8 @@ void Reply::paint(
|
||||||
? nullptr
|
? nullptr
|
||||||
: data->resolvedStory
|
: data->resolvedStory
|
||||||
? data->resolvedStory->replyPreview()
|
? data->resolvedStory->replyPreview()
|
||||||
|
: data->fields().externalMedia
|
||||||
|
? data->fields().externalMedia->replyPreview()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (image) {
|
if (image) {
|
||||||
auto to = style::rtlrect(
|
auto to = style::rtlrect(
|
||||||
|
|
Loading…
Add table
Reference in a new issue