Move volume dropdown management to audio player.

This commit is contained in:
John Preston 2021-11-24 18:26:39 +04:00
parent cdf09e0519
commit 551e1f787c
8 changed files with 66 additions and 242 deletions

View File

@ -813,8 +813,6 @@ PRIVATE
media/player/media_player_instance.h
media/player/media_player_panel.cpp
media/player/media_player_panel.h
media/player/media_player_repeat_controls.cpp
media/player/media_player_repeat_controls.h
media/player/media_player_volume_controller.cpp
media/player/media_player_volume_controller.h
media/player/media_player_widget.cpp

View File

@ -81,8 +81,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/player/media_player_panel.h"
#include "media/player/media_player_widget.h"
#include "media/player/media_player_dropdown.h"
#include "media/player/media_player_repeat_controls.h"
#include "media/player/media_player_volume_controller.h"
#include "media/player/media_player_instance.h"
#include "media/player/media_player_float.h"
#include "base/qthelp_regex.h"
@ -801,8 +799,6 @@ void MainWidget::closeBothPlayers() {
if (_player) {
_player->hide(anim::type::normal);
}
_playerVolume.destroyDelayed();
_playerRepeat.destroyDelayed();
_playerPlaylist->hideIgnoringEnterEvents();
Media::Player::instance()->stop(AudioMsgId::Type::Voice);
@ -821,7 +817,7 @@ void MainWidget::createPlayer() {
if (!_player) {
_player.create(
this,
object_ptr<Media::Player::Widget>(this, &session()),
object_ptr<Media::Player::Widget>(this, this, _controller),
_controller->adaptive().oneColumnValue());
rpl::merge(
_player->heightValue() | rpl::map_to(true),
@ -849,14 +845,6 @@ void MainWidget::createPlayer() {
_playerPlaylist->showFromOther();
}, _player->lifetime());
_playerVolume.create(this);
Media::Player::PrepareVolumeDropdown(
_playerVolume.data(),
_controller);
_player->entity()->volumeWidgetCreated(_playerVolume);
_playerRepeat.create(this);
Media::Player::PrepareRepeatDropdown(_playerRepeat.data());
_player->entity()->repeatWidgetCreated(_playerRepeat);
orderWidgets();
if (_a_show.animating()) {
_player->show(anim::type::instant);
@ -890,8 +878,6 @@ void MainWidget::playerHeightUpdated() {
if (!_playerHeight && _player->isHidden()) {
const auto state = Media::Player::instance()->getState(Media::Player::instance()->getActiveType());
if (!state.id || Media::Player::IsStoppedOrStopping(state.state)) {
_playerVolume.destroyDelayed();
_playerRepeat.destroyDelayed();
_player.destroyDelayed();
}
}
@ -1539,15 +1525,7 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(
floatPlayerHideAll();
if (_player) {
_player->hideShadow();
}
auto playerVolumeVisible = _playerVolume && !_playerVolume->isHidden();
if (playerVolumeVisible) {
_playerVolume->hide();
}
auto playerRepeatVisible = _playerRepeat && !_playerRepeat->isHidden();
if (playerRepeatVisible) {
_playerRepeat->hide();
_player->entity()->hideShadowAndDropdowns();
}
auto playerPlaylistVisible = !_playerPlaylist->isHidden();
if (playerPlaylistVisible) {
@ -1573,17 +1551,11 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(
height() - sectionTop));
}
if (playerVolumeVisible) {
_playerVolume->show();
}
if (playerRepeatVisible) {
_playerRepeat->show();
}
if (playerPlaylistVisible) {
_playerPlaylist->show();
}
if (_player) {
_player->showShadow();
_player->entity()->showShadowAndDropdowns();
}
floatPlayerShowVisible();
@ -1848,11 +1820,8 @@ void MainWidget::orderWidgets() {
_connecting->raise();
floatPlayerRaiseAll();
_playerPlaylist->raise();
if (_playerVolume) {
_playerVolume->raise();
}
if (_playerRepeat) {
_playerRepeat->raise();
if (_player) {
_player->entity()->raiseDropdowns();
}
if (_hider) _hider->raise();
}
@ -1861,15 +1830,7 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams &param
QPixmap result;
floatPlayerHideAll();
if (_player) {
_player->hideShadow();
}
auto playerVolumeVisible = _playerVolume && !_playerVolume->isHidden();
if (playerVolumeVisible) {
_playerVolume->hide();
}
auto playerRepeatVisible = _playerRepeat && !_playerRepeat->isHidden();
if (playerRepeatVisible) {
_playerRepeat->hide();
_player->entity()->hideShadowAndDropdowns();
}
auto playerPlaylistVisible = !_playerPlaylist->isHidden();
if (playerPlaylistVisible) {
@ -1898,17 +1859,11 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams &param
_thirdShadow->show();
}
}
if (playerVolumeVisible) {
_playerVolume->show();
}
if (playerRepeatVisible) {
_playerRepeat->show();
}
if (playerPlaylistVisible) {
_playerPlaylist->show();
}
if (_player) {
_player->showShadow();
_player->entity()->showShadowAndDropdowns();
}
floatPlayerShowVisible();
return result;
@ -2193,7 +2148,9 @@ void MainWidget::updateControlsGeometry() {
_mainSection->setGeometryWithTopMoved(mainSectionGeometry, _contentScrollAddToY);
}
refreshResizeAreas();
updateMediaPlayerPosition();
if (_player) {
_player->entity()->updateDropdownsGeometry();
}
updateMediaPlaylistPosition(_playerPlaylist->x());
_contentScrollAddToY = 0;
@ -2392,22 +2349,6 @@ void MainWidget::updateThirdColumnToCurrentChat(
}
}
void MainWidget::updateMediaPlayerPosition() {
if (!_player) {
return;
}
if (_playerVolume) {
auto relativePosition = _player->entity()->getPositionForVolumeWidget();
auto playerMargins = _playerVolume->getMargin();
_playerVolume->moveToLeft(_player->x() + relativePosition.x() - playerMargins.left(), _player->y() + relativePosition.y() - playerMargins.top());
}
if (_playerRepeat) {
auto relativePosition = _player->entity()->getPositionForRepeatWidget();
auto playerMargins = _playerRepeat->getMargin();
_playerRepeat->moveToLeft(_player->x() + relativePosition.x() - playerMargins.left(), _player->y() + relativePosition.y() - playerMargins.top());
}
}
void MainWidget::updateMediaPlaylistPosition(int x) {
if (_player) {
auto playlistLeft = x;
@ -2429,12 +2370,10 @@ void MainWidget::returnTabbedSelector() {
}
}
void MainWidget::keyPressEvent(QKeyEvent *e) {
}
bool MainWidget::eventFilter(QObject *o, QEvent *e) {
if (e->type() == QEvent::FocusIn) {
if (const auto widget = qobject_cast<QWidget*>(o)) {
if (o->isWidgetType()) {
const auto widget = static_cast<QWidget*>(o);
if (_history == widget || _history->isAncestorOf(widget)
|| (_mainSection && (_mainSection == widget || _mainSection->isAncestorOf(widget)))
|| (_thirdSection && (_thirdSection == widget || _thirdSection->isAncestorOf(widget)))) {
@ -2555,10 +2494,8 @@ void MainWidget::searchInChat(Dialogs::Key chat) {
}
bool MainWidget::contentOverlapped(const QRect &globalRect) {
return (_history->contentOverlapped(globalRect)
|| _playerPlaylist->overlaps(globalRect)
|| (_playerVolume && _playerVolume->overlaps(globalRect)))
|| (_playerRepeat && _playerRepeat->overlaps(globalRect));
return _history->contentOverlapped(globalRect)
|| _playerPlaylist->overlaps(globalRect);
}
void MainWidget::activate() {

View File

@ -55,7 +55,6 @@ class Widget;
namespace Media {
namespace Player {
class Widget;
class Dropdown;
class Panel;
struct TrackState;
} // namespace Player
@ -241,7 +240,6 @@ public Q_SLOTS:
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
bool eventFilter(QObject *o, QEvent *e) override;
private:
@ -249,7 +247,6 @@ private:
void handleAdaptiveLayoutUpdate();
void updateWindowAdaptiveLayout();
void handleAudioUpdate(const Media::Player::TrackState &state);
void updateMediaPlayerPosition();
void updateMediaPlaylistPosition(int x);
void updateControlsGeometry();
void updateDialogsWidthAnimated();
@ -366,8 +363,6 @@ private:
object_ptr<Window::TopBarWrapWidget<Media::Player::Widget>> _player
= { nullptr };
object_ptr<Media::Player::Dropdown> _playerVolume = { nullptr };
object_ptr<Media::Player::Dropdown> _playerRepeat = { nullptr };
object_ptr<Media::Player::Panel> _playerPlaylist;
bool _playerUsingPanel = false;

View File

@ -33,10 +33,12 @@ Dropdown::Dropdown(QWidget *parent)
}
QMargins Dropdown::getMargin() const {
const auto top = st::mediaPlayerHeight
const auto top1 = st::mediaPlayerHeight
+ st::lineWidth
- st::mediaPlayerPlayTop
- st::mediaPlayerVolumeToggle.height;
const auto top2 = st::mediaPlayerPlayback.fullWidth;
const auto top = std::max(top1, top2);
return QMargins(st::mediaPlayerVolumeMargin, top, st::mediaPlayerVolumeMargin, st::mediaPlayerVolumeMargin);
}

View File

@ -1,103 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "media/player/media_player_repeat_controls.h"
#include "media/player/media_player_dropdown.h"
#include "media/player/media_player_instance.h"
#include "ui/widgets/buttons.h"
#include "core/core_settings.h"
#include "core/application.h"
#include "styles/style_media_player.h"
namespace Media::Player {
void PrepareRepeatDropdown(not_null<Dropdown*> dropdown) {
const auto makeButton = [&] {
const auto result = Ui::CreateChild<Ui::IconButton>(
dropdown.get(),
st::mediaPlayerRepeatButton);
result->show();
return result;
};
const auto repeatOne = makeButton();
const auto repeatAll = makeButton();
const auto shuffle = makeButton();
const auto reverse = makeButton();
Core::App().settings().playerRepeatModeValue(
) | rpl::start_with_next([=](RepeatMode mode) {
const auto one = (mode == RepeatMode::One);
repeatOne->setIconOverride(one
? &st::mediaPlayerRepeatOneIcon
: &st::mediaPlayerRepeatOneDisabledIcon,
one ? nullptr : &st::mediaPlayerRepeatOneDisabledIconOver);
repeatOne->setRippleColorOverride(
one ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
const auto all = (mode == RepeatMode::All);
repeatAll->setIconOverride(all
? nullptr
: &st::mediaPlayerRepeatDisabledIcon,
all ? nullptr : &st::mediaPlayerRepeatDisabledIconOver);
repeatAll->setRippleColorOverride(
all ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
}, dropdown->lifetime());
Core::App().settings().playerOrderModeValue(
) | rpl::start_with_next([=](OrderMode mode) {
const auto shuffled = (mode == OrderMode::Shuffle);
shuffle->setIconOverride(shuffled
? &st::mediaPlayerShuffleIcon
: &st::mediaPlayerShuffleIcon,
shuffled ? nullptr : &st::mediaPlayerShuffleIcon);
shuffle->setRippleColorOverride(
shuffled ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
const auto reversed = (mode == OrderMode::Reverse);
reverse->setIconOverride(reversed
? &st::mediaPlayerReverseIcon
: &st::mediaPlayerReverseDisabledIcon,
reversed ? nullptr : &st::mediaPlayerReverseDisabledIconOver);
reverse->setRippleColorOverride(
reversed ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
}, dropdown->lifetime());
const auto toggleRepeat = [](RepeatMode mode) {
auto &settings = Core::App().settings();
const auto active = (settings.playerRepeatMode() == mode);
settings.setPlayerRepeatMode(active ? RepeatMode::None : mode);
Core::App().saveSettingsDelayed();
};
const auto toggleOrder = [](OrderMode mode) {
auto &settings = Core::App().settings();
const auto active = (settings.playerOrderMode() == mode);
settings.setPlayerOrderMode(active ? OrderMode::Default : mode);
Core::App().saveSettingsDelayed();
};
repeatOne->setClickedCallback([=] { toggleRepeat(RepeatMode::One); });
repeatAll->setClickedCallback([=] { toggleRepeat(RepeatMode::All); });
shuffle->setClickedCallback([=] { toggleOrder(OrderMode::Shuffle); });
reverse->setClickedCallback([=] { toggleOrder(OrderMode::Reverse); });
dropdown->sizeValue(
) | rpl::start_with_next([=](QSize size) {
const auto rect = QRect(QPoint(), size);
const auto inner = rect.marginsRemoved(dropdown->getMargin());
const auto skip = (inner.height() - repeatOne->height() * 4) / 3;
auto top = 0;
const auto move = [&](auto &widget) {
widget->move((size.width() - widget->width()) / 2, top);
top += widget->height() + skip;
};
move(repeatOne);
move(repeatAll);
move(shuffle);
move(reverse);
}, dropdown->lifetime());
}
} // namespace Media::Player

View File

@ -1,16 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Media::Player {
class Dropdown;
void PrepareRepeatDropdown(not_null<Dropdown*> dropdown);
} // namespace Media::Player

View File

@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/player/media_player_button.h"
#include "media/player/media_player_instance.h"
#include "media/player/media_player_dropdown.h"
#include "media/player/media_player_volume_controller.h"
#include "styles/style_media_player.h"
#include "styles/style_media_view.h"
#include "history/history_item.h"
@ -238,9 +239,12 @@ QPoint Widget::PlayButton::prepareRippleStartPosition() const {
return QPoint(mapFromGlobal(QCursor::pos()) - st::mediaPlayerButton.rippleAreaPosition);
}
Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
Widget::Widget(
QWidget *parent,
not_null<Ui::RpWidget*> dropdownsParent,
not_null<Window::SessionController*> controller)
: RpWidget(parent)
, _session(session)
, _controller(controller)
, _nameLabel(this, st::mediaPlayerName)
, _rightControls(this, object_ptr<Ui::RpWidget>(this))
, _timeLabel(rightControls(), st::mediaPlayerTime)
@ -252,6 +256,7 @@ Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
, _close(this, st::mediaPlayerClose)
, _shadow(this)
, _playbackSlider(this, st::mediaPlayerPlayback)
, _volume(dropdownsParent.get())
, _playbackProgress(std::make_unique<View::PlaybackProgress>())
, _speedController(
std::make_unique<SpeedController>(
@ -357,6 +362,10 @@ Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
handleSongUpdate(state);
}, lifetime());
PrepareVolumeDropdown(_volume.data(), controller);
_volumeToggle->installEventFilter(_volume.data());
_volume->installEventFilter(this);
setType(AudioMsgId::Type::Song);
}
@ -419,37 +428,36 @@ void Widget::setShadowGeometryToLeft(int x, int y, int w, int h) {
_shadow->setGeometryToLeft(x, y, w, h);
}
void Widget::showShadow() {
void Widget::showShadowAndDropdowns() {
_shadow->show();
_playbackSlider->setVisible(_type == AudioMsgId::Type::Song);
if (_volumeHidden) {
_volumeHidden = false;
_volume->show();
}
}
void Widget::hideShadow() {
void Widget::updateDropdownsGeometry() {
const auto position = _volume->parentWidget()->mapFromGlobal(
_volumeToggle->mapToGlobal(
QPoint(
(_volumeToggle->width() - st::mediaPlayerVolumeSize.width()) / 2,
height())));
const auto playerMargins = _volume->getMargin();
_volume->move(position - QPoint(playerMargins.left(), playerMargins.top()));
}
void Widget::hideShadowAndDropdowns() {
_shadow->hide();
_playbackSlider->hide();
if (!_volume->isHidden()) {
_volumeHidden = true;
_volume->hide();
}
}
QPoint Widget::getPositionForVolumeWidget() const {
auto x = _volumeToggle->x() + _rightControls->x();
x += (_volumeToggle->width() - st::mediaPlayerVolumeSize.width()) / 2;
if (rtl()) x = width() - x - st::mediaPlayerVolumeSize.width();
return QPoint(x, height());
}
void Widget::volumeWidgetCreated(Dropdown *widget) {
_volumeToggle->installEventFilter(widget);
widget->installEventFilter(this);
}
QPoint Widget::getPositionForRepeatWidget() const {
auto x = _orderToggle->x() + _rightControls->x();
x += (_orderToggle->width() - st::mediaPlayerVolumeSize.width()) / 2;
if (rtl()) x = width() - x - st::mediaPlayerVolumeSize.width();
return QPoint(x, height());
}
void Widget::repeatWidgetCreated(Dropdown *widget) {
_orderToggle->installEventFilter(widget);
void Widget::raiseDropdowns() {
_volume->raise();
}
Widget::~Widget() = default;
@ -502,6 +510,8 @@ void Widget::updateControlsGeometry() {
updatePlayPrevNextPositions();
_playbackSlider->setGeometry(0, height() - st::mediaPlayerPlayback.fullWidth, width(), st::mediaPlayerPlayback.fullWidth);
updateDropdownsGeometry();
}
void Widget::updateControlsWrapGeometry() {

View File

@ -29,9 +29,9 @@ class PlaybackProgress;
} // namespace Clip
} // namespace Media
namespace Main {
class Session;
} // namespace Main
namespace Window {
class SessionController;
} // namespace Window
namespace Media {
namespace Player {
@ -43,20 +43,19 @@ struct TrackState;
class Widget final : public Ui::RpWidget, private base::Subscriber {
public:
Widget(QWidget *parent, not_null<Main::Session*> session);
Widget(
QWidget *parent,
not_null<Ui::RpWidget*> dropdownsParent,
not_null<Window::SessionController*> controller);
void setCloseCallback(Fn<void()> callback);
void setShowItemCallback(Fn<void(not_null<const HistoryItem*>)> callback);
void stopAndClose();
void setShadowGeometryToLeft(int x, int y, int w, int h);
void showShadow();
void hideShadow();
[[nodiscard]] QPoint getPositionForVolumeWidget() const;
void volumeWidgetCreated(Dropdown *widget);
[[nodiscard]] QPoint getPositionForRepeatWidget() const;
void repeatWidgetCreated(Dropdown *widget);
void hideShadowAndDropdowns();
void showShadowAndDropdowns();
void updateDropdownsGeometry();
void raiseDropdowns();
[[nodiscard]] rpl::producer<bool> togglePlaylistRequests() const {
return _togglePlaylistRequests.events();
@ -111,7 +110,7 @@ private:
void updateTimeLabel();
void markOver(bool over);
const not_null<Main::Session*> _session;
const not_null<Window::SessionController*> _controller;
crl::time _seekPositionMs = -1;
crl::time _lastDurationMs = 0;
@ -133,6 +132,7 @@ private:
bool _narrow = false;
bool _over = false;
bool _wontBeOver = false;
bool _volumeHidden = false;
class PlayButton;
class SpeedController;
@ -149,6 +149,7 @@ private:
object_ptr<Ui::IconButton> _close;
object_ptr<Ui::PlainShadow> _shadow = { nullptr };
object_ptr<Ui::FilledSlider> _playbackSlider;
object_ptr<Dropdown> _volume;
std::unique_ptr<View::PlaybackProgress> _playbackProgress;
std::unique_ptr<SpeedController> _speedController;