mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-25 01:36:48 +00:00
Show external reply media preview.
This commit is contained in:
parent
4e0490494e
commit
537c656ee1
@ -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) {
|
||||
});
|
||||
}
|
||||
|
@ -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>(
|
||||
|
@ -623,6 +623,7 @@ public:
|
||||
private:
|
||||
const FullStoryId _storyId;
|
||||
const bool _mention = false;
|
||||
bool _viewMayExist = false;
|
||||
bool _expired = false;
|
||||
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user