From 1e02c475d62bb00879add94dd63150312b95de6d Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 28 Oct 2024 14:04:22 +0400 Subject: [PATCH] Show speed / quality badges. --- .../media/player/media_player_button.cpp | 108 +++++++++++++++--- .../media/player/media_player_button.h | 14 +++ .../SourceFiles/media/view/media_view.style | 1 + .../view/media_view_playback_controls.cpp | 3 + 4 files changed, 113 insertions(+), 13 deletions(-) diff --git a/Telegram/SourceFiles/media/player/media_player_button.cpp b/Telegram/SourceFiles/media/player/media_player_button.cpp index a429292112..3d828b07fb 100644 --- a/Telegram/SourceFiles/media/player/media_player_button.cpp +++ b/Telegram/SourceFiles/media/player/media_player_button.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/ripple_animation.h" #include "ui/painter.h" #include "styles/style_media_player.h" +#include "styles/style_media_view.h" #include @@ -347,12 +348,18 @@ SettingsButton::SettingsButton( } void SettingsButton::setSpeed(float64 speed) { - _isDefaultSpeed = EqualSpeeds(speed, 1.); - update(); + if (_speed != speed) { + _speed = speed; + _isDefaultSpeed = EqualSpeeds(speed, 1.); + update(); + } } void SettingsButton::setQuality(int quality) { - update(); + if (_quality != quality) { + _quality = quality; + update(); + } } void SettingsButton::setActive(bool active) { @@ -362,7 +369,19 @@ void SettingsButton::setActive(bool active) { _active = active; _activeAnimation.start([=] { update(); - }, active ? 0. : 1., active ? 1. : 0., crl::time(150)); + }, active ? 0. : 1., active ? 1. : 0., st::mediaviewOverDuration); +} + +void SettingsButton::onStateChanged(State was, StateChangeSource source) { + RippleButton::onStateChanged(was, source); + + const auto nowOver = isOver(); + const auto wasOver = static_cast(was & StateFlag::Over); + if (nowOver != wasOver) { + _overAnimation.start([=] { + update(); + }, nowOver ? 0. : 1., nowOver ? 1. : 0., st::mediaviewOverDuration); + } } void SettingsButton::paintEvent(QPaintEvent *e) { @@ -373,13 +392,28 @@ void SettingsButton::paintEvent(QPaintEvent *e) { QPoint(_st.padding.left(), _st.padding.top()), _isDefaultSpeed ? nullptr : &_st.rippleActiveColor->c); - //const auto active = !_isDefaultSpeed; + prepareFrame(); + p.drawImage(0, 0, _frameCache); +} + +void SettingsButton::prepareFrame() { + const auto ratio = style::DevicePixelRatio(); + if (_frameCache.size() != _st.size * ratio) { + _frameCache = QImage( + _st.size * ratio, + QImage::Format_ARGB32_Premultiplied); + } + _frameCache.fill(Qt::transparent); + auto p = QPainter(&_frameCache); + const auto inner = QRect( QPoint(), _st.size ).marginsRemoved(_st.padding); auto hq = std::optional(); + const auto over = _overAnimation.value(isOver() ? 1. : 0.); + const auto color = anim::color(_st.fg, _st.overFg, over); const auto active = _activeAnimation.value(_active ? 1. : 0.); if (active > 0.) { const auto shift = QRectF(inner).center(); @@ -389,20 +423,68 @@ void SettingsButton::paintEvent(QPaintEvent *e) { p.translate(-shift); hq.emplace(p); } - _st.icon.paintInCenter(p, inner); + _st.icon.paintInCenter(p, inner, color); if (active > 0.) { p.restore(); hq.reset(); } - //p.setPen(color); - //p.setFont(_st.font); + const auto rounded = int(base::SafeRound(_speed * 10)); + if (rounded != 10) { + const auto text = (rounded % 10) + ? QString::number(rounded / 10.) + : u"%1X"_q.arg(rounded / 10); + paintBadge(p, text, RectPart::TopLeft, color); + } + const auto text = (!_quality) + ? QString() + : (_quality > 2000) + ? u"4K"_q + : (_quality > 1000) + ? u"FHD"_q + : (_quality > 700) + ? u"HD"_q + : u"SD"_q; + if (!text.isEmpty()) { + paintBadge(p, text, RectPart::BottomRight, color); + } +} - //p.drawText( - // QPointF(inner.topLeft()) + QPointF( - // (inner.width() - _textWidth) / 2., - // (inner.height() - _adjustedHeight) / 2. + _adjustedAscent), - // _text); +void SettingsButton::paintBadge( + QPainter &p, + const QString &text, + RectPart origin, + QColor color) { + auto hq = PainterHighQualityEnabler(p); + const auto xpadding = style::ConvertScale(2.); + const auto ypadding = 0; + const auto skip = style::ConvertScale(2.); + const auto width = _st.font->width(text); + const auto height = _st.font->height; + const auto radius = height / 3.; + const auto left = (origin == RectPart::TopLeft) + || (origin == RectPart::BottomLeft); + const auto top = (origin == RectPart::TopLeft) + || (origin == RectPart::TopRight); + const auto x = left ? 0 : (_st.size.width() - width - 2 * xpadding); + const auto y = top + ? skip + : (_st.size.height() - height - 2 * ypadding - skip); + p.setCompositionMode(QPainter::CompositionMode_Source); + const auto stroke = style::ConvertScaleExact(1.); + p.setPen(QPen(Qt::transparent, stroke)); + p.setFont(_st.font); + p.setBrush(color); + p.drawRoundedRect( + QRectF( + x - stroke / 2., + y - stroke / 2., + width + 2 * xpadding + stroke, + height + 2 * ypadding + stroke), + radius, + radius); + p.setPen(Qt::transparent); + p.drawText(x + xpadding, y + ypadding + _st.font->ascent, text); } QPoint SettingsButton::prepareRippleStartPosition() const { diff --git a/Telegram/SourceFiles/media/player/media_player_button.h b/Telegram/SourceFiles/media/player/media_player_button.h index 8709c0cdd8..0c667b099f 100644 --- a/Telegram/SourceFiles/media/player/media_player_button.h +++ b/Telegram/SourceFiles/media/player/media_player_button.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/animations.h" #include "ui/widgets/buttons.h" +#include "ui/rect_part.h" #include @@ -119,8 +120,21 @@ private: QPoint prepareRippleStartPosition() const override; QImage prepareRippleMask() const override; + void onStateChanged(State was, StateChangeSource source) override; + + void paintBadge( + QPainter &p, + const QString &text, + RectPart origin, + QColor color); + void prepareFrame(); + const style::MediaSpeedButton &_st; Ui::Animations::Simple _activeAnimation; + Ui::Animations::Simple _overAnimation; + QImage _frameCache; + float _speed = 1.; + int _quality = 0; bool _isDefaultSpeed = false; bool _active = false; diff --git a/Telegram/SourceFiles/media/view/media_view.style b/Telegram/SourceFiles/media/view/media_view.style index 55efb6fcc3..e6b41da6f1 100644 --- a/Telegram/SourceFiles/media/view/media_view.style +++ b/Telegram/SourceFiles/media/view/media_view.style @@ -351,6 +351,7 @@ mediaviewSpeedMenu: MediaSpeedMenu(mediaPlayerSpeedMenu) { mediaviewSpeedButton: MediaSpeedButton(mediaPlayerSpeedButton) { size: size(32px, 32px); padding: margins(0px, 0px, 0px, 0px); + font: font(8px bold); fg: mediaviewPlaybackIconFg; overFg: mediaviewPlaybackIconFgOver; activeFg: mediaviewTextLinkFg; diff --git a/Telegram/SourceFiles/media/view/media_view_playback_controls.cpp b/Telegram/SourceFiles/media/view/media_view_playback_controls.cpp index a5aba77d10..6f4bc0f13c 100644 --- a/Telegram/SourceFiles/media/view/media_view_playback_controls.cpp +++ b/Telegram/SourceFiles/media/view/media_view_playback_controls.cpp @@ -70,6 +70,9 @@ PlaybackControls::PlaybackControls( fadeUpdated(opacity); }); + _speedToggle->setSpeed(_delegate->playbackControlsCurrentSpeed(false)); + _speedToggle->setQuality(_delegate->playbackControlsCurrentQuality()); + if (const auto controller = _speedController.get()) { controller->menuToggledValue( ) | rpl::start_with_next([=](bool toggled) {