From cb03d5a9d3ab2c850056411cc47335b02df915b1 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 24 Jan 2025 20:21:59 +0400 Subject: [PATCH] Show video_timestamp progress line. --- Telegram/SourceFiles/data/data_web_page.cpp | 22 ++++++ Telegram/SourceFiles/data/data_web_page.h | 1 + .../history/view/media/history_view_gif.cpp | 79 ++++++++++++++++++- .../history/view/media/history_view_gif.h | 5 ++ Telegram/SourceFiles/ui/chat/chat.style | 1 + 5 files changed, 107 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/data/data_web_page.cpp b/Telegram/SourceFiles/data/data_web_page.cpp index 9f53503bb..fe364e038 100644 --- a/Telegram/SourceFiles/data/data_web_page.cpp +++ b/Telegram/SourceFiles/data/data_web_page.cpp @@ -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; diff --git a/Telegram/SourceFiles/data/data_web_page.h b/Telegram/SourceFiles/data/data_web_page.h index f97c79474..04b1a44a1 100644 --- a/Telegram/SourceFiles/data/data_web_page.h +++ b/Telegram/SourceFiles/data/data_web_page.h @@ -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; diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index c6ef0f197..e654b2d80 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -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 @@ -134,6 +135,18 @@ Gif::Streamed::Streamed( && parent->data()->media()->ttlSeconds(); } +[[nodiscard]] TimeId ExtractVideoTimestamp(not_null 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 parent, not_null realParent, @@ -150,6 +163,7 @@ Gif::Gif( ? std::make_unique() : 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 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, diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.h b/Telegram/SourceFiles/history/view/media/history_view_gif.h index bfe5aca04..635e3627d 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.h +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.h @@ -163,6 +163,10 @@ private: int y, bool right, const PaintContext &context) const; + void paintTimestampMark( + Painter &p, + QRect rthumb, + std::optional 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 _thumbCacheRounding; mutable bool _thumbCacheBlurred : 1 = false; mutable bool _thumbIsEllipse : 1 = false; diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 9f9cbaaa0..9099a97c3 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -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;