Show video_timestamp progress line.

This commit is contained in:
John Preston 2025-01-24 20:21:59 +04:00
parent b618d1e56a
commit cb03d5a9d3
5 changed files with 107 additions and 1 deletions

View file

@ -374,6 +374,28 @@ QString WebPageData::displayedSiteName() const {
: siteName;
}
TimeId WebPageData::extractVideoTimestamp() const {
const auto take = [&](const QStringList &list, int index) {
return (index >= 0 && index < list.size()) ? list[index] : QString();
};
const auto hashed = take(url.split('#'), 0);
const auto params = take(hashed.split('?'), 1);
const auto parts = params.split('&');
for (const auto &part : parts) {
if (part.startsWith(u"t="_q)) {
const auto value = part.mid(2);
const auto kExp = u"^(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$"_q;
const auto m = QRegularExpression(kExp).match(value);
return m.hasMatch()
? (m.capturedView(1).toInt() * 3600
+ m.capturedView(2).toInt() * 60
+ m.capturedView(3).toInt())
: value.toInt();
}
}
return 0;
}
bool WebPageData::computeDefaultSmallMedia() const {
if (!collage.items.empty()) {
return false;

View file

@ -114,6 +114,7 @@ struct WebPageData {
const MTPmessages_Messages &result);
[[nodiscard]] QString displayedSiteName() const;
[[nodiscard]] TimeId extractVideoTimestamp() const;
[[nodiscard]] bool computeDefaultSmallMedia() const;
[[nodiscard]] bool suggestEnlargePhoto() const;

View file

@ -54,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_click_handler.h"
#include "data/data_file_origin.h"
#include "data/data_document_media.h"
#include "data/data_web_page.h"
#include "styles/style_chat.h"
#include <QSvgRenderer>
@ -134,6 +135,18 @@ Gif::Streamed::Streamed(
&& parent->data()->media()->ttlSeconds();
}
[[nodiscard]] TimeId ExtractVideoTimestamp(not_null<HistoryItem*> item) {
const auto media = item->media();
if (!media) {
return 0;
} else if (const auto timestamp = media->videoTimestamp()) {
return timestamp;
} else if (const auto webpage = media->webpage()) {
return webpage->extractVideoTimestamp();
}
return 0;
}
Gif::Gif(
not_null<Element*> parent,
not_null<HistoryItem*> realParent,
@ -150,6 +163,7 @@ Gif::Gif(
? std::make_unique<MediaSpoiler>()
: nullptr)
, _downloadSize(Ui::FormatSizeText(_data->size))
, _videoTimestamp(ExtractVideoTimestamp(realParent))
, _sensitiveSpoiler(realParent->isMediaSensitive())
, _hasVideoCover(realParent->media() && realParent->media()->videoCover()) {
if (_data->isVideoMessage() && _parent->data()->media()->ttlSeconds()) {
@ -396,7 +410,7 @@ bool Gif::downloadInCorner() const {
bool Gif::autoplayEnabled() const {
if (_realParent->isSponsored()) {
return true;
} else if (_hasVideoCover) {
} else if (_videoTimestamp || _hasVideoCover) {
return false;
}
return Data::AutoDownload::ShouldAutoPlay(
@ -581,6 +595,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
ensureDataMediaCreated();
validateThumbCache({ usew, painth }, isRound, rounding);
p.drawImage(rthumb, _thumbCache);
paintTimestampMark(p, rthumb, rounding);
}
if (revealed < 1.) {
@ -867,6 +882,68 @@ void Gif::paintTranscribe(
context);
}
void Gif::paintTimestampMark(
Painter &p,
QRect rthumb,
std::optional<Ui::BubbleRounding> rounding) const {
if (_videoTimestamp <= 0) {
return;
}
const auto roundingLeft = rounding
? rounding->bottomLeft
: Ui::BubbleCornerRounding::Small;
const auto roundingRight = rounding
? rounding->bottomRight
: Ui::BubbleCornerRounding::Small;
const auto convert = [](Ui::BubbleCornerRounding rounding) {
return (rounding == Ui::BubbleCornerRounding::Small)
? st::roundRadiusSmall
: (rounding == Ui::BubbleCornerRounding::Large)
? st::roundRadiusLarge
: 0;
};
const auto radiusl = convert(roundingLeft);
const auto radiusr = convert(roundingRight);
const auto line = st::historyVideoTimestampProgressLine;
const auto duration = _data->duration() / 1000;
if (rthumb.height() <= line
|| rthumb.width() <= radiusl + radiusr
|| _videoTimestamp >= duration) {
return;
}
auto hq = PainterHighQualityEnabler(p);
const auto used = rthumb.width() - radiusl - radiusr;
const auto progress = _videoTimestamp / float64(duration);
const auto edge = radiusl + int(base::SafeRound(used * progress));
const auto top = rthumb.y() + rthumb.height() - line;
p.save();
p.setPen(Qt::NoPen);
if (edge > 0) {
p.setBrush(st::windowBgActive);
p.setClipRect(rthumb.x(), top, edge, line);
p.drawRoundedRect(
rthumb.x(),
top - radiusl,
edge + radiusl,
line + radiusl,
radiusl,
radiusl);
}
if (const auto width = rthumb.width() - edge; width > 0) {
const auto left = rthumb.x() + edge;
p.setBrush(st::mediaviewPlaybackProgressFg);
p.setClipRect(left, top, width, line);
p.drawRoundedRect(
left - radiusr,
top - radiusr,
width + radiusr,
line + radiusr,
radiusr, radiusr);
}
p.restore();
}
void Gif::drawSpoilerTag(
Painter &p,
QRect rthumb,

View file

@ -163,6 +163,10 @@ private:
int y,
bool right,
const PaintContext &context) const;
void paintTimestampMark(
Painter &p,
QRect rthumb,
std::optional<Ui::BubbleRounding> rounding) const;
[[nodiscard]] bool needInfoDisplay() const;
[[nodiscard]] bool needCornerStatusDisplay() const;
@ -218,6 +222,7 @@ private:
QString _downloadSize;
mutable QImage _thumbCache;
mutable QImage _roundingMask;
mutable TimeId _videoTimestamp = 0;
mutable std::optional<Ui::BubbleRounding> _thumbCacheRounding;
mutable bool _thumbCacheBlurred : 1 = false;
mutable bool _thumbIsEllipse : 1 = false;

View file

@ -686,6 +686,7 @@ historyVideoCancelSelected: icon {{ "player/playlist_cancel", historyFileThumbIc
historyVideoDownload: icon {{ "player/playlist_download", historyFileThumbIconFg }};
historyVideoDownloadSelected: icon {{ "player/playlist_download", historyFileThumbIconFgSelected }};
historyVideoRadialLine: msgFileRadialLine;
historyVideoTimestampProgressLine: 4px;
historyAudioDownloadSize: 20px;
historyAudioRadialLine: 2px;