Highlight YouTube video timestamps as external links.
This commit is contained in:
parent
ebded1b421
commit
f2e4a5a35a
|
@ -65,6 +65,26 @@ bool UrlRequiresConfirmation(const QUrl &url) {
|
||||||
RegExOption::CaseInsensitive);
|
RegExOption::CaseInsensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString HiddenUrlClickHandler::copyToClipboardText() const {
|
||||||
|
return url().startsWith(qstr("internal:url:"))
|
||||||
|
? url().mid(qstr("internal:url:").size())
|
||||||
|
: url();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString HiddenUrlClickHandler::copyToClipboardContextItemText() const {
|
||||||
|
return url().isEmpty()
|
||||||
|
? QString()
|
||||||
|
: !url().startsWith(qstr("internal:"))
|
||||||
|
? UrlClickHandler::copyToClipboardContextItemText()
|
||||||
|
: url().startsWith(qstr("internal:url:"))
|
||||||
|
? UrlClickHandler::copyToClipboardContextItemText()
|
||||||
|
: QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString HiddenUrlClickHandler::dragText() const {
|
||||||
|
return HiddenUrlClickHandler::copyToClipboardText();
|
||||||
|
}
|
||||||
|
|
||||||
void HiddenUrlClickHandler::Open(QString url, QVariant context) {
|
void HiddenUrlClickHandler::Open(QString url, QVariant context) {
|
||||||
url = Core::TryConvertUrlToLocal(url);
|
url = Core::TryConvertUrlToLocal(url);
|
||||||
if (Core::InternalPassportLink(url)) {
|
if (Core::InternalPassportLink(url)) {
|
||||||
|
|
|
@ -39,11 +39,9 @@ class HiddenUrlClickHandler : public UrlClickHandler {
|
||||||
public:
|
public:
|
||||||
HiddenUrlClickHandler(QString url) : UrlClickHandler(url, false) {
|
HiddenUrlClickHandler(QString url) : UrlClickHandler(url, false) {
|
||||||
}
|
}
|
||||||
QString copyToClipboardContextItemText() const override {
|
QString copyToClipboardText() const override;
|
||||||
return (url().isEmpty() || url().startsWith(qstr("internal:")))
|
QString copyToClipboardContextItemText() const override;
|
||||||
? QString()
|
QString dragText() const override;
|
||||||
: UrlClickHandler::copyToClipboardContextItemText();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Open(QString url, QVariant context = {});
|
static void Open(QString url, QVariant context = {});
|
||||||
void onClick(ClickContext context) const override {
|
void onClick(ClickContext context) const override {
|
||||||
|
|
|
@ -474,6 +474,15 @@ bool ShowInviteLink(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenExternalLink(
|
||||||
|
Window::SessionController *controller,
|
||||||
|
const Match &match,
|
||||||
|
const QVariant &context) {
|
||||||
|
return Ui::Integration::Instance().handleUrlClick(
|
||||||
|
match->captured(1),
|
||||||
|
context);
|
||||||
|
}
|
||||||
|
|
||||||
void ExportTestChatTheme(
|
void ExportTestChatTheme(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
not_null<const Data::CloudTheme*> theme) {
|
not_null<const Data::CloudTheme*> theme) {
|
||||||
|
@ -698,6 +707,10 @@ const std::vector<LocalUrlHandler> &InternalUrlHandlers() {
|
||||||
qsl("^show_invite_link/?\\?link=([a-zA-Z0-9_\\+\\/\\=\\-]+)(&|$)"),
|
qsl("^show_invite_link/?\\?link=([a-zA-Z0-9_\\+\\/\\=\\-]+)(&|$)"),
|
||||||
ShowInviteLink
|
ShowInviteLink
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
qsl("^url:(.+)$"),
|
||||||
|
OpenExternalLink
|
||||||
|
},
|
||||||
};
|
};
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
#include "data/data_web_page.h"
|
||||||
#include "data/data_file_click_handler.h"
|
#include "data/data_file_click_handler.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
|
@ -224,7 +225,7 @@ void HistoryMessageForwarded::create(const HistoryMessageVia *via) const {
|
||||||
bool HistoryMessageReply::updateData(
|
bool HistoryMessageReply::updateData(
|
||||||
not_null<HistoryMessage*> holder,
|
not_null<HistoryMessage*> holder,
|
||||||
bool force) {
|
bool force) {
|
||||||
const auto guard = gsl::finally([&] { refreshReplyToDocument(); });
|
const auto guard = gsl::finally([&] { refreshReplyToMedia(); });
|
||||||
if (!force) {
|
if (!force) {
|
||||||
if (replyToMsg || !replyToMsgId) {
|
if (replyToMsg || !replyToMsgId) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -291,7 +292,7 @@ void HistoryMessageReply::clearData(not_null<HistoryMessage*> holder) {
|
||||||
replyToMsg = nullptr;
|
replyToMsg = nullptr;
|
||||||
}
|
}
|
||||||
replyToMsgId = 0;
|
replyToMsgId = 0;
|
||||||
refreshReplyToDocument();
|
refreshReplyToMedia();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryMessageReply::isNameUpdated() const {
|
bool HistoryMessageReply::isNameUpdated() const {
|
||||||
|
@ -416,11 +417,14 @@ void HistoryMessageReply::paint(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMessageReply::refreshReplyToDocument() {
|
void HistoryMessageReply::refreshReplyToMedia() {
|
||||||
replyToDocumentId = 0;
|
replyToDocumentId = 0;
|
||||||
|
replyToWebPageId = 0;
|
||||||
if (const auto media = replyToMsg ? replyToMsg->media() : nullptr) {
|
if (const auto media = replyToMsg ? replyToMsg->media() : nullptr) {
|
||||||
if (const auto document = media->document()) {
|
if (const auto document = media->document()) {
|
||||||
replyToDocumentId = document->id;
|
replyToDocumentId = document->id;
|
||||||
|
} else if (const auto webpage = media->webpage()) {
|
||||||
|
replyToWebPageId = webpage->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,7 @@ struct HistoryMessageReply : public RuntimeComponent<HistoryMessageReply, Histor
|
||||||
replyToMsgId = other.replyToMsgId;
|
replyToMsgId = other.replyToMsgId;
|
||||||
replyToMsgTop = other.replyToMsgTop;
|
replyToMsgTop = other.replyToMsgTop;
|
||||||
replyToDocumentId = other.replyToDocumentId;
|
replyToDocumentId = other.replyToDocumentId;
|
||||||
|
replyToWebPageId = other.replyToWebPageId;
|
||||||
std::swap(replyToMsg, other.replyToMsg);
|
std::swap(replyToMsg, other.replyToMsg);
|
||||||
replyToLnk = std::move(other.replyToLnk);
|
replyToLnk = std::move(other.replyToLnk);
|
||||||
replyToName = std::move(other.replyToName);
|
replyToName = std::move(other.replyToName);
|
||||||
|
@ -182,13 +183,14 @@ struct HistoryMessageReply : public RuntimeComponent<HistoryMessageReply, Histor
|
||||||
void setReplyToLinkFrom(
|
void setReplyToLinkFrom(
|
||||||
not_null<HistoryMessage*> holder);
|
not_null<HistoryMessage*> holder);
|
||||||
|
|
||||||
void refreshReplyToDocument();
|
void refreshReplyToMedia();
|
||||||
|
|
||||||
PeerId replyToPeerId = 0;
|
PeerId replyToPeerId = 0;
|
||||||
MsgId replyToMsgId = 0;
|
MsgId replyToMsgId = 0;
|
||||||
MsgId replyToMsgTop = 0;
|
MsgId replyToMsgTop = 0;
|
||||||
HistoryItem *replyToMsg = nullptr;
|
HistoryItem *replyToMsg = nullptr;
|
||||||
DocumentId replyToDocumentId = 0;
|
DocumentId replyToDocumentId = 0;
|
||||||
|
WebPageId replyToWebPageId = 0;
|
||||||
ClickHandlerPtr replyToLnk;
|
ClickHandlerPtr replyToLnk;
|
||||||
mutable Ui::Text::String replyToName, replyToText;
|
mutable Ui::Text::String replyToName, replyToText;
|
||||||
mutable int replyToVersion = 0;
|
mutable int replyToVersion = 0;
|
||||||
|
|
|
@ -45,6 +45,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_histories.h"
|
#include "data/data_histories.h"
|
||||||
|
#include "data/data_web_page.h"
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
#include "styles/style_widgets.h"
|
#include "styles/style_widgets.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
@ -1000,9 +1001,11 @@ void HistoryMessage::setCommentsItemId(FullMsgId id) {
|
||||||
bool HistoryMessage::updateDependencyItem() {
|
bool HistoryMessage::updateDependencyItem() {
|
||||||
if (const auto reply = Get<HistoryMessageReply>()) {
|
if (const auto reply = Get<HistoryMessageReply>()) {
|
||||||
const auto documentId = reply->replyToDocumentId;
|
const auto documentId = reply->replyToDocumentId;
|
||||||
|
const auto webpageId = reply->replyToWebPageId;
|
||||||
const auto result = reply->updateData(this, true);
|
const auto result = reply->updateData(this, true);
|
||||||
if (documentId != reply->replyToDocumentId
|
const auto mediaIdChanged = (documentId != reply->replyToDocumentId)
|
||||||
&& generateLocalEntitiesByReply()) {
|
|| (webpageId != reply->replyToWebPageId);
|
||||||
|
if (mediaIdChanged && generateLocalEntitiesByReply()) {
|
||||||
reapplyText();
|
reapplyText();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1524,34 +1527,50 @@ Storage::SharedMediaTypesMask HistoryMessage::sharedMediaTypes() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryMessage::generateLocalEntitiesByReply() const {
|
bool HistoryMessage::generateLocalEntitiesByReply() const {
|
||||||
return !_media || _media->webpage();
|
if (!_media) {
|
||||||
|
return true;
|
||||||
|
} else if (const auto webpage = _media->webpage()) {
|
||||||
|
return !webpage->document && webpage->type != WebPageType::Video;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextWithEntities HistoryMessage::withLocalEntities(
|
TextWithEntities HistoryMessage::withLocalEntities(
|
||||||
const TextWithEntities &textWithEntities) const {
|
const TextWithEntities &textWithEntities) const {
|
||||||
|
using namespace HistoryView;
|
||||||
if (!generateLocalEntitiesByReply()) {
|
if (!generateLocalEntitiesByReply()) {
|
||||||
|
if (const auto webpage = _media ? _media->webpage() : nullptr) {
|
||||||
|
if (const auto duration = DurationForTimestampLinks(webpage)) {
|
||||||
|
return AddTimestampLinks(
|
||||||
|
textWithEntities,
|
||||||
|
duration,
|
||||||
|
TimestampLinkBase(webpage, fullId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
return textWithEntities;
|
return textWithEntities;
|
||||||
}
|
}
|
||||||
if (const auto reply = Get<HistoryMessageReply>()) {
|
if (const auto reply = Get<HistoryMessageReply>()) {
|
||||||
const auto document = reply->replyToDocumentId
|
const auto document = reply->replyToDocumentId
|
||||||
? history()->owner().document(reply->replyToDocumentId).get()
|
? history()->owner().document(reply->replyToDocumentId).get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (document
|
const auto webpage = reply->replyToWebPageId
|
||||||
&& (document->isVideoFile()
|
? history()->owner().webpage(reply->replyToWebPageId).get()
|
||||||
|| document->isSong()
|
: nullptr;
|
||||||
|| document->isVoiceMessage())) {
|
if (document) {
|
||||||
using namespace HistoryView;
|
if (const auto duration = DurationForTimestampLinks(document)) {
|
||||||
const auto duration = document->getDuration();
|
const auto context = reply->replyToMsg->fullId();
|
||||||
const auto base = (duration > 0)
|
|
||||||
? DocumentTimestampLinkBase(
|
|
||||||
document,
|
|
||||||
reply->replyToMsg->fullId())
|
|
||||||
: QString();
|
|
||||||
if (!base.isEmpty()) {
|
|
||||||
return AddTimestampLinks(
|
return AddTimestampLinks(
|
||||||
textWithEntities,
|
textWithEntities,
|
||||||
duration,
|
duration,
|
||||||
base);
|
TimestampLinkBase(document, context));
|
||||||
|
}
|
||||||
|
} else if (webpage) {
|
||||||
|
if (const auto duration = DurationForTimestampLinks(webpage)) {
|
||||||
|
const auto context = reply->replyToMsg->fullId();
|
||||||
|
return AddTimestampLinks(
|
||||||
|
textWithEntities,
|
||||||
|
duration,
|
||||||
|
TimestampLinkBase(webpage, context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1084,12 +1084,9 @@ TextWithEntities Document::getCaption() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ui::Text::String Document::createCaption() {
|
Ui::Text::String Document::createCaption() {
|
||||||
const auto timestampLinksDuration = (_data->isSong()
|
const auto timestampLinksDuration = DurationForTimestampLinks(_data);
|
||||||
|| _data->isVoiceMessage())
|
|
||||||
? _data->getDuration()
|
|
||||||
: 0;
|
|
||||||
const auto timestampLinkBase = timestampLinksDuration
|
const auto timestampLinkBase = timestampLinksDuration
|
||||||
? DocumentTimestampLinkBase(_data, _realParent->fullId())
|
? TimestampLinkBase(_data, _realParent->fullId())
|
||||||
: QString();
|
: QString();
|
||||||
return File::createCaption(
|
return File::createCaption(
|
||||||
_realParent,
|
_realParent,
|
||||||
|
|
|
@ -1322,11 +1322,9 @@ void Gif::refreshParentId(not_null<HistoryItem*> realParent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gif::refreshCaption() {
|
void Gif::refreshCaption() {
|
||||||
const auto timestampLinksDuration = _data->isVideoFile()
|
const auto timestampLinksDuration = DurationForTimestampLinks(_data);
|
||||||
? _data->getDuration()
|
|
||||||
: 0;
|
|
||||||
const auto timestampLinkBase = timestampLinksDuration
|
const auto timestampLinkBase = timestampLinksDuration
|
||||||
? DocumentTimestampLinkBase(_data, _realParent->fullId())
|
? TimestampLinkBase(_data, _realParent->fullId())
|
||||||
: QString();
|
: QString();
|
||||||
_caption = createCaption(
|
_caption = createCaption(
|
||||||
_parent->data(),
|
_parent->data(),
|
||||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lottie/lottie_single_player.h"
|
#include "lottie/lottie_single_player.h"
|
||||||
#include "storage/storage_shared_media.h"
|
#include "storage/storage_shared_media.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
#include "data/data_web_page.h"
|
||||||
#include "ui/item_text_options.h"
|
#include "ui/item_text_options.h"
|
||||||
#include "ui/chat/chat_style.h"
|
#include "ui/chat/chat_style.h"
|
||||||
#include "ui/chat/message_bubble.h"
|
#include "ui/chat/message_bubble.h"
|
||||||
|
@ -44,18 +45,77 @@ namespace {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
QString DocumentTimestampLinkBase(
|
TimeId DurationForTimestampLinks(not_null<DocumentData*> document) {
|
||||||
|
if (!document->isVideoFile()
|
||||||
|
&& !document->isSong()
|
||||||
|
&& !document->isVoiceMessage()) {
|
||||||
|
return TimeId(0);
|
||||||
|
}
|
||||||
|
return std::max(document->getDuration(), TimeId(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TimestampLinkBase(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
FullMsgId context) {
|
FullMsgId context) {
|
||||||
return QString(
|
return QString(
|
||||||
"doc%1_%2_%3"
|
"media_timestamp?base=doc%1_%2_%3&t="
|
||||||
).arg(document->id).arg(context.channel.bare).arg(context.msg.bare);
|
).arg(document->id).arg(context.channel.bare).arg(context.msg.bare);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimeId DurationForTimestampLinks(not_null<WebPageData*> webpage) {
|
||||||
|
if (!webpage->collage.items.empty()) {
|
||||||
|
return false;
|
||||||
|
} else if (const auto document = webpage->document) {
|
||||||
|
return DurationForTimestampLinks(document);
|
||||||
|
} else if (webpage->type != WebPageType::Video
|
||||||
|
|| webpage->siteName != qstr("YouTube")) {
|
||||||
|
return TimeId(0);
|
||||||
|
} else if (webpage->duration > 0) {
|
||||||
|
return webpage->duration;
|
||||||
|
}
|
||||||
|
constexpr auto kMaxYouTubeTimestampDuration = 10 * 60 * TimeId(60);
|
||||||
|
return kMaxYouTubeTimestampDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TimestampLinkBase(
|
||||||
|
not_null<WebPageData*> webpage,
|
||||||
|
FullMsgId context) {
|
||||||
|
const auto url = webpage->url;
|
||||||
|
if (url.isEmpty()) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
auto parts = url.split(QChar('#'));
|
||||||
|
const auto base = parts[0];
|
||||||
|
parts.pop_front();
|
||||||
|
const auto use = [&] {
|
||||||
|
const auto query = base.indexOf(QChar('?'));
|
||||||
|
if (query < 0) {
|
||||||
|
return base + QChar('?');
|
||||||
|
}
|
||||||
|
auto params = base.mid(query + 1).split(QChar('&'));
|
||||||
|
for (auto i = params.begin(); i != params.end();) {
|
||||||
|
if (i->startsWith("t=")) {
|
||||||
|
i = params.erase(i);
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return base.mid(0, query)
|
||||||
|
+ (params.empty() ? "?" : ("?" + params.join(QChar('&')) + "&"));
|
||||||
|
}();
|
||||||
|
return "url:"
|
||||||
|
+ use
|
||||||
|
+ "t="
|
||||||
|
+ (parts.empty() ? QString() : ("#" + parts.join(QChar('#'))));
|
||||||
|
}
|
||||||
|
|
||||||
TextWithEntities AddTimestampLinks(
|
TextWithEntities AddTimestampLinks(
|
||||||
TextWithEntities text,
|
TextWithEntities text,
|
||||||
TimeId duration,
|
TimeId duration,
|
||||||
const QString &base) {
|
const QString &base) {
|
||||||
|
if (base.isEmpty()) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
static const auto expression = QRegularExpression(
|
static const auto expression = QRegularExpression(
|
||||||
"(?<![^\\s\\(\\)\"\\,\\.\\-])(?:(?:(\\d{1,2}):)?(\\d))?(\\d):(\\d\\d)(?![^\\s\\(\\)\",\\.\\-])");
|
"(?<![^\\s\\(\\)\"\\,\\.\\-])(?:(?:(\\d{1,2}):)?(\\d))?(\\d):(\\d\\d)(?![^\\s\\(\\)\",\\.\\-])");
|
||||||
const auto &string = text.text;
|
const auto &string = text.text;
|
||||||
|
@ -104,10 +164,7 @@ TextWithEntities AddTimestampLinks(
|
||||||
EntityType::CustomUrl,
|
EntityType::CustomUrl,
|
||||||
from,
|
from,
|
||||||
till - from,
|
till - from,
|
||||||
("internal:media_timestamp?base="
|
("internal:" + base + QString::number(time))));
|
||||||
+ base
|
|
||||||
+ "&t="
|
|
||||||
+ QString::number(time))));
|
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,9 +52,18 @@ enum class MediaInBubbleState {
|
||||||
Bottom,
|
Bottom,
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] QString DocumentTimestampLinkBase(
|
[[nodiscard]] TimeId DurationForTimestampLinks(
|
||||||
|
not_null<DocumentData*> document);
|
||||||
|
[[nodiscard]] QString TimestampLinkBase(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
FullMsgId context);
|
FullMsgId context);
|
||||||
|
|
||||||
|
[[nodiscard]] TimeId DurationForTimestampLinks(
|
||||||
|
not_null<WebPageData*> webpage);
|
||||||
|
[[nodiscard]] QString TimestampLinkBase(
|
||||||
|
not_null<WebPageData*> webpage,
|
||||||
|
FullMsgId context);
|
||||||
|
|
||||||
[[nodiscard]] TextWithEntities AddTimestampLinks(
|
[[nodiscard]] TextWithEntities AddTimestampLinks(
|
||||||
TextWithEntities text,
|
TextWithEntities text,
|
||||||
TimeId duration,
|
TimeId duration,
|
||||||
|
|
|
@ -677,18 +677,16 @@ void GroupedMedia::updateNeedBubbleState() {
|
||||||
QString base;
|
QString base;
|
||||||
};
|
};
|
||||||
const auto timestamp = [&]() -> Timestamp {
|
const auto timestamp = [&]() -> Timestamp {
|
||||||
const auto &document = part->content->getDocument();
|
const auto document = part->content->getDocument();
|
||||||
if (!document || document->isAnimation()) {
|
const auto duration = document
|
||||||
|
? DurationForTimestampLinks(document)
|
||||||
|
: TimeId(0);
|
||||||
|
if (!duration) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const auto duration = document->getDuration();
|
|
||||||
return {
|
return {
|
||||||
.duration = duration,
|
.duration = duration,
|
||||||
.base = duration
|
.base = TimestampLinkBase(document, part->item->fullId()),
|
||||||
? DocumentTimestampLinkBase(
|
|
||||||
document,
|
|
||||||
part->item->fullId())
|
|
||||||
: QString(),
|
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
_caption = createCaption(
|
_caption = createCaption(
|
||||||
|
|
|
@ -2102,18 +2102,20 @@ void OverlayWidget::refreshCaption() {
|
||||||
|
|
||||||
using namespace HistoryView;
|
using namespace HistoryView;
|
||||||
_caption = Ui::Text::String(st::msgMinWidth);
|
_caption = Ui::Text::String(st::msgMinWidth);
|
||||||
const auto duration = (_streamed && _document && !videoIsGifOrUserpic())
|
const auto duration = (_streamed && _document)
|
||||||
? _document->getDuration()
|
? DurationForTimestampLinks(_document)
|
||||||
: 0;
|
: 0;
|
||||||
const auto base = duration
|
const auto base = duration
|
||||||
? DocumentTimestampLinkBase(_document, _message->fullId())
|
? TimestampLinkBase(_document, _message->fullId())
|
||||||
: QString();
|
: QString();
|
||||||
const auto context = Core::MarkedTextContext{
|
const auto context = Core::MarkedTextContext{
|
||||||
.session = &_message->history()->session()
|
.session = &_message->history()->session()
|
||||||
};
|
};
|
||||||
_caption.setMarkedText(
|
_caption.setMarkedText(
|
||||||
st::mediaviewCaptionStyle,
|
st::mediaviewCaptionStyle,
|
||||||
AddTimestampLinks(caption, duration, base),
|
(base.isEmpty()
|
||||||
|
? caption
|
||||||
|
: AddTimestampLinks(caption, duration, base)),
|
||||||
Ui::ItemTextOptions(_message),
|
Ui::ItemTextOptions(_message),
|
||||||
context);
|
context);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue