Show external reply media preview.

This commit is contained in:
John Preston 2023-11-03 16:03:08 +04:00
parent 4e0490494e
commit 537c656ee1
8 changed files with 96 additions and 36 deletions

View File

@ -86,9 +86,16 @@ struct FileReferenceAccumulator {
}, [](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) {
data.match([&](const MTPDmessage &data) {
push(data.vmedia());
push(data.vreply_to());
}, [&](const MTPDmessageService &data) {
data.vaction().match(
[&](const MTPDmessageActionChatEditPhoto &data) {
@ -99,6 +106,7 @@ struct FileReferenceAccumulator {
push(data.vwallpaper());
}, [](const auto &data) {
});
push(data.vreply_to());
}, [](const MTPDmessageEmpty &data) {
});
}

View File

@ -705,7 +705,7 @@ ItemPreview MediaPhoto::toPreview(ToPreviewOptions options) const {
}
}
const auto type = tr::lng_in_dlg_photo(tr::now);
const auto caption = options.hideCaption
const auto caption = (options.hideCaption || options.ignoreMessageText)
? TextWithEntities()
: options.translated
? parent()->translatedText()
@ -951,7 +951,7 @@ ItemPreview MediaFile::toPreview(ToPreviewOptions options) const {
}
return tr::lng_in_dlg_file(tr::now);
}();
const auto caption = options.hideCaption
const auto caption = (options.hideCaption || options.ignoreMessageText)
? TextWithEntities()
: options.translated
? parent()->translatedText()
@ -1500,7 +1500,9 @@ bool MediaWebPage::replyPreviewLoaded() const {
}
ItemPreview MediaWebPage::toPreview(ToPreviewOptions options) const {
auto text = options.translated
auto text = options.ignoreMessageText
? TextWithEntities()
: options.translated
? parent()->translatedText()
: parent()->originalText();
if (text.empty()) {
@ -2038,28 +2040,23 @@ MediaStory::MediaStory(
owner->registerStoryItem(storyId, parent);
const auto stories = &owner->stories();
if (const auto maybeStory = stories->lookup(storyId)) {
if (!_mention) {
parent->setText((*maybeStory)->caption());
}
} else {
if (maybeStory.error() == NoStory::Unknown) {
stories->resolve(storyId, crl::guard(this, [=] {
if (const auto maybeStory = stories->lookup(storyId)) {
if (!_mention) {
parent->setText((*maybeStory)->caption());
}
} else {
_expired = true;
const auto maybeStory = stories->lookup(storyId);
if (!maybeStory && maybeStory.error() == NoStory::Unknown) {
stories->resolve(storyId, crl::guard(this, [=] {
if (const auto maybeStory = stories->lookup(storyId)) {
if (!_mention && _viewMayExist) {
parent->setText((*maybeStory)->caption());
}
if (_mention) {
parent->updateStoryMentionText();
}
parent->history()->owner().requestItemViewRefresh(parent);
}));
} else {
_expired = true;
}
} else {
_expired = true;
}
if (_mention) {
parent->updateStoryMentionText();
}
parent->history()->owner().requestItemViewRefresh(parent);
}));
} else if (!maybeStory) {
_expired = true;
}
}
@ -2154,6 +2151,7 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
if (_mention) {
return nullptr;
}
_viewMayExist = true;
return std::make_unique<HistoryView::Photo>(
message,
realParent,
@ -2161,6 +2159,7 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
spoiler);
}
_expired = false;
_viewMayExist = true;
const auto story = *maybeStory;
if (_mention) {
return std::make_unique<HistoryView::ServiceBox>(

View File

@ -623,6 +623,7 @@ public:
private:
const FullStoryId _storyId;
const bool _mention = false;
bool _viewMayExist = false;
bool _expired = false;
};

View File

@ -451,7 +451,7 @@ HistoryItem::HistoryItem(
config.reply.topicPost = (topicRootId != 0);
if (const auto originalReply = original->Get<HistoryMessageReply>()) {
if (originalReply->external()) {
config.reply = originalReply->fields();
config.reply = originalReply->fields().clone(this);
if (!config.reply.externalPeerId) {
config.reply.messageId = 0;
}
@ -3133,7 +3133,7 @@ void HistoryItem::createComponents(CreateConfig &&config) {
UpdateComponents(mask);
if (const auto reply = Get<HistoryMessageReply>()) {
reply->set(config.reply);
reply->set(std::move(config.reply));
if (!reply->updateData(this)) {
if (const auto messageId = reply->messageId()) {
RequestDependentMessageItem(
@ -3456,7 +3456,7 @@ void HistoryItem::createComponents(const MTPDmessage &data) {
});
}
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.viewsCount = data.vviews().value_or(-1);

View File

@ -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(
not_null<History*> history,
not_null<HistoryItem*> item,
const MTPMessageReplyHeader &reply) {
return reply.match([&](const MTPDmessageReplyHeader &data) {
auto result = ReplyFields();
if (const auto peer = data.vreply_to_peer_id()) {
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()) {
result.messageId = data.is_reply_to_scheduled()
? owner->scheduledMessages().localMessageId(id)
@ -297,6 +315,9 @@ ReplyFields ReplyFieldsFromMTP(
result.externalSenderName
= qs(data.vfrom_name().value_or_empty());
}
if (const auto media = data.vreply_media()) {
result.externalMedia = HistoryItem::CreateMedia(item, *media);
}
result.quote = TextWithEntities{
qs(data.vquote_text().value_or_empty()),
Api::EntitiesFromMTP(
@ -357,6 +378,7 @@ HistoryMessageReply &HistoryMessageReply::operator=(
HistoryMessageReply::~HistoryMessageReply() {
// clearData() should be called by holder.
Expects(resolvedMessage.empty());
_fields.externalMedia = nullptr;
}
bool HistoryMessageReply::updateData(
@ -407,7 +429,8 @@ bool HistoryMessageReply::updateData(
const auto displaying = resolvedMessage
|| resolvedStory
|| (!_fields.quote.empty() && (!_fields.messageId || force));
|| ((!_fields.quote.empty() || _fields.externalMedia)
&& (!_fields.messageId || force));
_displaying = displaying ? 1 : 0;
const auto unavailable = !resolvedMessage

View File

@ -233,7 +233,10 @@ private:
};
struct ReplyFields {
ReplyFields clone(not_null<HistoryItem*> parent) const;
TextWithEntities quote;
std::unique_ptr<Data::Media> externalMedia;
PeerId externalSenderId = 0;
QString externalSenderName;
QString externalPostAuthor;
@ -246,7 +249,7 @@ struct ReplyFields {
};
[[nodiscard]] ReplyFields ReplyFieldsFromMTP(
not_null<History*> history,
not_null<HistoryItem*> item,
const MTPMessageReplyHeader &reply);
[[nodiscard]] FullReplyTo ReplyToFromMTP(

View File

@ -40,6 +40,7 @@ struct ToPreviewOptions {
const std::vector<ItemPreviewImage> *existing = nullptr;
bool hideSender = false;
bool hideCaption = false;
bool ignoreMessageText = false;
bool generateImages = true;
bool ignoreGroup = false;
bool ignoreTopic = true;

View File

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "data/data_story.h"
#include "data/data_user.h"
#include "history/view/history_view_item_preview.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_components.h"
@ -176,6 +177,7 @@ void Reply::update(
const auto &fields = data->fields();
const auto message = data->resolvedMessage.get();
const auto story = data->resolvedStory.get();
const auto externalMedia = fields.externalMedia.get();
if (!_externalSender) {
if (const auto id = fields.externalSenderId) {
_externalSender = view->history()->owner().peer(id);
@ -195,7 +197,8 @@ void Reply::update(
const auto hasPreview = (story && story->hasReplyPreview())
|| (message
&& message->media()
&& message->media()->hasReplyPreview());
&& message->media()->hasReplyPreview())
|| (externalMedia && externalMedia->hasReplyPreview());
_hasPreview = hasPreview ? 1 : 0;
_displaying = data->displaying() ? 1 : 0;
_multiline = data->multiline() ? 1 : 0;
@ -213,6 +216,15 @@ void Reply::update(
? message->inReplyText()
: story
? story->inReplyText()
: externalMedia
? externalMedia->toPreview({
.hideSender = true,
.hideCaption = true,
.ignoreMessageText = true,
.generateImages = false,
.ignoreGroup = true,
.ignoreTopic = true,
}).text
: TextWithEntities();
const auto repaint = [=] { item->customEmojiRepaint(); };
const auto context = Core::MarkedTextContext{
@ -222,7 +234,7 @@ void Reply::update(
_text.setMarkedText(
st::defaultTextStyle,
text,
Ui::DialogTextOptions(),
_multiline ? Ui::ItemTextDefaultOptions() : Ui::DialogTextOptions(),
context);
updateName(view, data);
@ -388,7 +400,9 @@ void Reply::updateName(
const auto externalPeer = fields.externalPeerId
? view->history()->owner().peer(fields.externalPeerId).get()
: 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 name = sender
? senderName(sender, shorten)
@ -508,10 +522,16 @@ int Reply::resizeToWidth(int width) const {
auto elided = false;
const auto texth = _text.countDimensions(
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;
_height = st::historyReplyPadding.top()
+ nameh
+ (elided ? kNonExpandedLinesLimit * st::normalFont->height : texth)
+ useh
+ st::historyReplyPadding.bottom();
return height();
}
@ -551,7 +571,10 @@ QSize Reply::countMultilineOptimalSize(
const auto max = previewSkip + _text.maxWidth();
const auto result = _text.countDimensions(
textGeometry(max, previewSkip, &lineCounter, &elided));
return { result.width, result.height };
return {
result.width,
std::max(result.height, st::normalFont->height),
};
}
void Reply::paint(
@ -663,6 +686,8 @@ void Reply::paint(
? nullptr
: data->resolvedStory
? data->resolvedStory->replyPreview()
: data->fields().externalMedia
? data->fields().externalMedia->replyPreview()
: nullptr;
if (image) {
auto to = style::rtlrect(