From 4b489ee7d2c07366d360b6f4c0f52c062ce5a62a Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 24 Nov 2021 17:44:47 +0400 Subject: [PATCH] Fade out controls in a narrow player. --- .../media/player/media_player.style | 3 + .../media/player/media_player_widget.cpp | 78 +++++++++++++++++-- .../media/player/media_player_widget.h | 13 +++- 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/Telegram/SourceFiles/media/player/media_player.style b/Telegram/SourceFiles/media/player/media_player.style index ff24886a91..5b75be8c70 100644 --- a/Telegram/SourceFiles/media/player/media_player.style +++ b/Telegram/SourceFiles/media/player/media_player.style @@ -30,6 +30,7 @@ mediaPlayerButtonSize: size(25px, 30px); mediaPlayerButtonPosition: point(5px, 10px); +mediaPlayerWideWidth: 460px; mediaPlayerHeight: 35px; mediaPlayerPadding: 8px; mediaPlayerNameTop: 22px; @@ -171,6 +172,8 @@ mediaPlayerVolumeToggle: IconButton(mediaPlayerRepeatButton) { mediaPlayerVolumeMargin: 10px; mediaPlayerVolumeSize: size(27px, 100px); +mediaPlayerControlsFade: icon {{ "fade_horizontal", mediaPlayerBg }}; + mediaPlayerNextButton: IconButton(mediaPlayerPlayButton) { icon: icon { { "player/player_forward", mediaPlayerActiveFg }, diff --git a/Telegram/SourceFiles/media/player/media_player_widget.cpp b/Telegram/SourceFiles/media/player/media_player_widget.cpp index da0be18201..f31fa8ae2c 100644 --- a/Telegram/SourceFiles/media/player/media_player_widget.cpp +++ b/Telegram/SourceFiles/media/player/media_player_widget.cpp @@ -252,7 +252,7 @@ Widget::Widget(QWidget *parent, not_null session) setMouseTracking(true); resize(width(), st::mediaPlayerHeight + st::lineWidth); - _rightControls->show(anim::type::instant); + setupRightControls(); _nameLabel->setAttribute(Qt::WA_TransparentForMouseEvents); _timeLabel->setAttribute(Qt::WA_TransparentForMouseEvents); @@ -350,7 +350,25 @@ Widget::Widget(QWidget *parent, not_null session) }, lifetime()); setType(AudioMsgId::Type::Song); - //_playPause->finishTransform(); +} + +void Widget::setupRightControls() { + const auto raw = rightControls(); + raw->paintRequest( + ) | rpl::start_with_next([=](QRect clip) { + auto p = QPainter(raw); + const auto &icon = st::mediaPlayerControlsFade; + const auto fade = QRect(0, 0, icon.width(), raw->height()); + if (fade.intersects(clip)) { + icon.fill(p, fade); + } + const auto fill = clip.intersected( + { icon.width(), 0, raw->width() - icon.width(), raw->height() }); + if (!fill.isEmpty()) { + p.fillRect(fill, st::mediaPlayerBg); + } + }, raw->lifetime()); + _rightControls->show(anim::type::instant); } void Widget::updateVolumeToggleIcon() { @@ -358,7 +376,7 @@ void Widget::updateVolumeToggleIcon() { const auto volume = Core::App().settings().songVolume(); return (volume == 0.) ? &st::mediaPlayerVolumeIcon0 - : (volume < 0.5) + : (volume < 0.66) ? &st::mediaPlayerVolumeIcon1 : nullptr; }()); @@ -412,6 +430,7 @@ QPoint Widget::getPositionForVolumeWidget() const { void Widget::volumeWidgetCreated(Dropdown *widget) { _volumeToggle->installEventFilter(widget); + widget->installEventFilter(this); } QPoint Widget::getPositionForRepeatWidget() const { @@ -456,6 +475,8 @@ void Widget::handleSeekFinished(float64 progress) { void Widget::resizeEvent(QResizeEvent *e) { updateControlsGeometry(); + _narrow = (width() < st::mediaPlayerWideWidth); + updateControlsWrapVisibility(); } void Widget::updateControlsGeometry() { @@ -476,12 +497,21 @@ void Widget::updateControlsGeometry() { } void Widget::updateControlsWrapGeometry() { - rightControls()->resize(getTimeRight() + _timeLabel->width(), _repeatToggle->height()); + const auto fade = st::mediaPlayerControlsFade.width(); + rightControls()->resize( + getTimeRight() + _timeLabel->width() + fade, + _repeatToggle->height()); _rightControls->moveToRight( st::mediaPlayerCloseRight + _close->width(), st::mediaPlayerPlayTop); } +void Widget::updateControlsWrapVisibility() { + _rightControls->toggle( + _over || !_narrow, + isHidden() ? anim::type::instant : anim::type::normal); +} + void Widget::paintEvent(QPaintEvent *e) { Painter p(this); auto fill = e->rect().intersected(QRect(0, 0, width(), st::mediaPlayerHeight)); @@ -490,8 +520,41 @@ void Widget::paintEvent(QPaintEvent *e) { } } +bool Widget::eventFilter(QObject *o, QEvent *e) { + const auto type = e->type(); + if (type == QEvent::Enter) { + markOver(true); + } else if (type == QEvent::Leave) { + markOver(false); + } + return RpWidget::eventFilter(o, e); +} + +void Widget::enterEventHook(QEnterEvent *e) { + markOver(true); +} + void Widget::leaveEventHook(QEvent *e) { - updateOverLabelsState(false); + markOver(false); +} + +void Widget::markOver(bool over) { + if (over) { + _over = true; + _wontBeOver = false; + updateControlsWrapVisibility(); + } else { + _wontBeOver = true; + InvokeQueued(this, [=] { + if (!_wontBeOver) { + return; + } + _wontBeOver = false; + _over = false; + updateControlsWrapVisibility(); + updateOverLabelsState(false); + }); + } } void Widget::mouseMoveEvent(QMouseEvent *e) { @@ -522,7 +585,10 @@ void Widget::mouseReleaseEvent(QMouseEvent *e) { void Widget::updateOverLabelsState(QPoint pos) { const auto left = getNameLeft(); - const auto right = getNameRight(); + const auto right = width() + - _rightControls->x() + - _rightControls->width() + + getTimeRight(); const auto labels = myrtlrect(left, 0, width() - right - left, height() - st::mediaPlayerPlayback.fullWidth); const auto over = labels.contains(pos); updateOverLabelsState(over); diff --git a/Telegram/SourceFiles/media/player/media_player_widget.h b/Telegram/SourceFiles/media/player/media_player_widget.h index 36f2f3ae26..876edc7a79 100644 --- a/Telegram/SourceFiles/media/player/media_player_widget.h +++ b/Telegram/SourceFiles/media/player/media_player_widget.h @@ -41,7 +41,7 @@ class SpeedButton; class Dropdown; struct TrackState; -class Widget : public Ui::RpWidget, private base::Subscriber { +class Widget final : public Ui::RpWidget, private base::Subscriber { public: Widget(QWidget *parent, not_null session); @@ -64,17 +64,19 @@ public: ~Widget(); -protected: +private: void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; + bool eventFilter(QObject *o, QEvent *e) override; + void enterEventHook(QEnterEvent *e) override; void leaveEventHook(QEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; -private: [[nodiscard]] not_null rightControls(); + void setupRightControls(); void handleSeekProgress(float64 progress); void handleSeekFinished(float64 progress); @@ -92,6 +94,7 @@ private: void updateControlsVisibility(); void updateControlsGeometry(); void updateControlsWrapGeometry(); + void updateControlsWrapVisibility(); void createPrevNextButtons(); void destroyPrevNextButtons(); @@ -106,6 +109,7 @@ private: void updateTimeText(const TrackState &state); void updateTimeLabel(); + void markOver(bool over); const not_null _session; @@ -126,6 +130,9 @@ private: bool _labelsOver = false; bool _labelsDown = false; rpl::event_stream _togglePlaylistRequests; + bool _narrow = false; + bool _over = false; + bool _wontBeOver = false; class PlayButton; class SpeedButton;