mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 07:07:08 +02:00
Add reverse / shuffle options dropdown.
This commit is contained in:
parent
eb6afdf438
commit
c947586091
4 changed files with 154 additions and 15 deletions
Telegram
Resources/langs
SourceFiles/media/player
|
@ -2320,6 +2320,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_player_message_yesterday" = "Yesterday at {time}";
|
||||
"lng_player_message_date" = "{date} at {time}";
|
||||
|
||||
"lng_audio_player_reverse" = "Reverse order";
|
||||
"lng_audio_player_shuffle" = "Shuffle";
|
||||
|
||||
"lng_rights_edit_admin" = "Manage permissions";
|
||||
"lng_rights_edit_admin_header" = "What can this admin do?";
|
||||
"lng_rights_edit_admin_rank_name" = "Custom title";
|
||||
|
|
|
@ -286,3 +286,18 @@ mediaPlayerFileLayout: OverviewFileLayout(overviewFileLayout) {
|
|||
|
||||
mediaPlayerFloatSize: 128px;
|
||||
mediaPlayerFloatMargin: 12px;
|
||||
|
||||
mediaPlayerOrderMenuPosition: point(-2px, -4px);
|
||||
mediaPlayerOrderMenu: Menu(defaultMenu) {
|
||||
itemIconPosition: point(13px, 8px);
|
||||
itemPadding: margins(49px, 9px, 17px, 11px);
|
||||
itemStyle: boxTextStyle;
|
||||
}
|
||||
mediaPlayerOrderMenuActive: Menu(mediaPlayerOrderMenu) {
|
||||
itemFg: windowActiveTextFg;
|
||||
itemFgOver: windowActiveTextFg;
|
||||
}
|
||||
mediaPlayerOrderIconReverse: icon{{ "player/player_order", windowFg }};
|
||||
mediaPlayerOrderIconReverseActive: icon{{ "player/player_order", windowActiveTextFg }};
|
||||
mediaPlayerOrderIconShuffle: icon{{ "player/player_shuffle", windowFg }};
|
||||
mediaPlayerOrderIconShuffleActive: icon{{ "player/player_shuffle", windowActiveTextFg }};
|
||||
|
|
|
@ -18,6 +18,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/dropdown_menu.h"
|
||||
#include "ui/widgets/menu/menu_action.h"
|
||||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/text/format_values.h"
|
||||
|
@ -245,6 +247,7 @@ Widget::Widget(
|
|||
not_null<Window::SessionController*> controller)
|
||||
: RpWidget(parent)
|
||||
, _controller(controller)
|
||||
, _orderMenuParent(dropdownsParent)
|
||||
, _nameLabel(this, st::mediaPlayerName)
|
||||
, _rightControls(this, object_ptr<Ui::RpWidget>(this))
|
||||
, _timeLabel(rightControls(), st::mediaPlayerTime)
|
||||
|
@ -256,7 +259,7 @@ Widget::Widget(
|
|||
, _close(this, st::mediaPlayerClose)
|
||||
, _shadow(this)
|
||||
, _playbackSlider(this, st::mediaPlayerPlayback)
|
||||
, _volume(dropdownsParent.get())
|
||||
, _volume(std::in_place, dropdownsParent.get())
|
||||
, _playbackProgress(std::make_unique<View::PlaybackProgress>())
|
||||
, _speedController(
|
||||
std::make_unique<SpeedController>(
|
||||
|
@ -313,6 +316,16 @@ Widget::Widget(
|
|||
updateRepeatToggleIcon();
|
||||
}, lifetime());
|
||||
|
||||
_orderToggle->setClickedCallback([=] {
|
||||
showOrderMenu();
|
||||
});
|
||||
_orderToggle->events(
|
||||
) | rpl::filter([=](not_null<QEvent*> e) {
|
||||
return e->type() == QEvent::Enter;
|
||||
}) | rpl::start_with_next([=] {
|
||||
showOrderMenu();
|
||||
}, _orderToggle->lifetime());
|
||||
|
||||
Core::App().settings().playerOrderModeValue(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateOrderToggleIcon();
|
||||
|
@ -362,13 +375,25 @@ Widget::Widget(
|
|||
handleSongUpdate(state);
|
||||
}, lifetime());
|
||||
|
||||
PrepareVolumeDropdown(_volume.data(), controller);
|
||||
_volumeToggle->installEventFilter(_volume.data());
|
||||
PrepareVolumeDropdown(_volume.get(), controller);
|
||||
_volumeToggle->installEventFilter(_volume.get());
|
||||
_volume->installEventFilter(this);
|
||||
|
||||
hidePlaylistOn(_playPause);
|
||||
hidePlaylistOn(_close);
|
||||
|
||||
setType(AudioMsgId::Type::Song);
|
||||
}
|
||||
|
||||
void Widget::hidePlaylistOn(const object_ptr<Ui::IconButton> &button) {
|
||||
button->events(
|
||||
) | rpl::filter([=](not_null<QEvent*> e) {
|
||||
return (e->type() == QEvent::Enter);
|
||||
}) | rpl::start_with_next([=] {
|
||||
updateOverLabelsState(false);
|
||||
}, button->lifetime());
|
||||
}
|
||||
|
||||
void Widget::setupRightControls() {
|
||||
const auto raw = rightControls();
|
||||
raw->paintRequest(
|
||||
|
@ -437,14 +462,101 @@ void Widget::showShadowAndDropdowns() {
|
|||
}
|
||||
}
|
||||
|
||||
void Widget::showOrderMenu() {
|
||||
if (_orderMenu) {
|
||||
return;
|
||||
}
|
||||
_orderMenu.emplace(_orderMenuParent);
|
||||
_orderMenu->installEventFilter(this);
|
||||
_orderMenu->setHiddenCallback([weak = Ui::MakeWeak(this), menu = _orderMenu.get()] {
|
||||
menu->deleteLater();
|
||||
if (weak && weak->_orderMenu == menu) {
|
||||
weak->_orderMenu = nullptr;
|
||||
weak->_orderToggle->setForceRippled(false);
|
||||
}
|
||||
});
|
||||
_orderMenu->setShowStartCallback(crl::guard(this, [this, menu = _orderMenu.get()] {
|
||||
if (_orderMenu == menu) {
|
||||
_orderToggle->setForceRippled(true);
|
||||
}
|
||||
}));
|
||||
_orderMenu->setHideStartCallback(crl::guard(this, [this, menu = _orderMenu.get()] {
|
||||
if (_orderMenu == menu) {
|
||||
_orderToggle->setForceRippled(false);
|
||||
}
|
||||
}));
|
||||
_orderToggle->installEventFilter(_orderMenu);
|
||||
const auto addOrderAction = [&](OrderMode mode) {
|
||||
struct Fields {
|
||||
QString label;
|
||||
const style::icon &icon;
|
||||
const style::icon &activeIcon;
|
||||
};
|
||||
const auto current = Core::App().settings().playerOrderMode();
|
||||
const auto active = (current == mode);
|
||||
const auto callback = [=] {
|
||||
Core::App().settings().setPlayerOrderMode(active
|
||||
? OrderMode::Default
|
||||
: mode);
|
||||
Core::App().saveSettingsDelayed();
|
||||
};
|
||||
const auto fields = [&]() -> Fields {
|
||||
switch (mode) {
|
||||
case OrderMode::Reverse: return {
|
||||
.label = tr::lng_audio_player_reverse(tr::now),
|
||||
.icon = st::mediaPlayerOrderIconReverse,
|
||||
.activeIcon = st::mediaPlayerOrderIconReverseActive,
|
||||
};
|
||||
case OrderMode::Shuffle: return {
|
||||
.label = tr::lng_audio_player_shuffle(tr::now),
|
||||
.icon = st::mediaPlayerOrderIconShuffle,
|
||||
.activeIcon = st::mediaPlayerOrderIconShuffleActive,
|
||||
};
|
||||
}
|
||||
Unexpected("Order mode in addOrderAction.");
|
||||
}();
|
||||
const auto parent = _orderMenu.get();
|
||||
const auto action = Ui::Menu::CreateAction(
|
||||
parent,
|
||||
fields.label,
|
||||
callback);
|
||||
auto item = base::make_unique_q<Ui::Menu::Action>(
|
||||
parent,
|
||||
(active
|
||||
? st::mediaPlayerOrderMenuActive
|
||||
: st::mediaPlayerOrderMenu),
|
||||
std::move(action),
|
||||
&(active ? fields.activeIcon : fields.icon),
|
||||
&(active ? fields.activeIcon : fields.icon));
|
||||
_orderMenu->addAction(std::move(item));
|
||||
};
|
||||
addOrderAction(OrderMode::Reverse);
|
||||
addOrderAction(OrderMode::Shuffle);
|
||||
updateDropdownsGeometry();
|
||||
_orderMenu->showAnimated(Ui::PanelAnimation::Origin::TopRight);
|
||||
}
|
||||
|
||||
void Widget::updateDropdownsGeometry() {
|
||||
const auto dropdownWidth = st::mediaPlayerVolumeSize.width();
|
||||
const auto position = _volume->parentWidget()->mapFromGlobal(
|
||||
_volumeToggle->mapToGlobal(
|
||||
QPoint(
|
||||
(_volumeToggle->width() - st::mediaPlayerVolumeSize.width()) / 2,
|
||||
(_volumeToggle->width() - dropdownWidth) / 2,
|
||||
height())));
|
||||
const auto playerMargins = _volume->getMargin();
|
||||
_volume->move(position - QPoint(playerMargins.left(), playerMargins.top()));
|
||||
const auto shift = QPoint(playerMargins.left(), playerMargins.top());
|
||||
_volume->move(position - shift);
|
||||
|
||||
if (_orderMenu) {
|
||||
const auto position = _orderMenu->parentWidget()->mapFromGlobal(
|
||||
_orderToggle->mapToGlobal(
|
||||
QPoint(_orderToggle->width(), _orderToggle->height())));
|
||||
const auto padding = st::defaultInnerDropdown.padding;
|
||||
_orderMenu->move(position
|
||||
- QPoint(_orderMenu->width(), 0)
|
||||
+ QPoint(padding.right(), -padding.top())
|
||||
+ st::mediaPlayerOrderMenuPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::hideShadowAndDropdowns() {
|
||||
|
@ -516,11 +628,10 @@ void Widget::updateControlsGeometry() {
|
|||
|
||||
void Widget::updateControlsWrapGeometry() {
|
||||
const auto fade = st::mediaPlayerControlsFade.width();
|
||||
rightControls()->resize(
|
||||
getTimeRight() + _timeLabel->width() + fade,
|
||||
_repeatToggle->height());
|
||||
_rightControls->moveToRight(
|
||||
st::mediaPlayerCloseRight + _close->width(),
|
||||
const auto controls = getTimeRight() + _timeLabel->width() + fade;
|
||||
rightControls()->resize(controls, _repeatToggle->height());
|
||||
_rightControls->move(
|
||||
width() - st::mediaPlayerCloseRight - _close->width() - controls,
|
||||
st::mediaPlayerPlayTop);
|
||||
}
|
||||
|
||||
|
@ -561,6 +672,7 @@ void Widget::markOver(bool over) {
|
|||
_over = true;
|
||||
_wontBeOver = false;
|
||||
updateControlsWrapVisibility();
|
||||
updateOverLabelsState(true);
|
||||
} else {
|
||||
_wontBeOver = true;
|
||||
InvokeQueued(this, [=] {
|
||||
|
@ -570,8 +682,8 @@ void Widget::markOver(bool over) {
|
|||
_wontBeOver = false;
|
||||
_over = false;
|
||||
updateControlsWrapVisibility();
|
||||
updateOverLabelsState(false);
|
||||
});
|
||||
updateOverLabelsState(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -705,7 +817,7 @@ void Widget::updateOrderToggleIcon() {
|
|||
&st::mediaPlayerRepeatDisabledRippleBg);
|
||||
break;
|
||||
case OrderMode::Reverse:
|
||||
_orderToggle->setIconOverride(nullptr);
|
||||
_orderToggle->setIconOverride(&st::mediaPlayerReverseIcon);
|
||||
_orderToggle->setRippleColorOverride(nullptr);
|
||||
break;
|
||||
case OrderMode::Shuffle:
|
||||
|
@ -736,6 +848,7 @@ bool Widget::hasPlaybackSpeedControl() const {
|
|||
|
||||
void Widget::updateControlsVisibility() {
|
||||
_repeatToggle->setVisible(_type == AudioMsgId::Type::Song);
|
||||
_orderToggle->setVisible(_type == AudioMsgId::Type::Song);
|
||||
_volumeToggle->setVisible(_type == AudioMsgId::Type::Song);
|
||||
_playbackSpeed->setVisible(hasPlaybackSpeedControl());
|
||||
if (!_shadow->isHidden()) {
|
||||
|
@ -906,13 +1019,15 @@ void Widget::createPrevNextButtons() {
|
|||
_previousTrack.create(this, st::mediaPlayerPreviousButton);
|
||||
_previousTrack->show();
|
||||
_previousTrack->setClickedCallback([=]() {
|
||||
instance()->previous();
|
||||
instance()->previous(_type);
|
||||
});
|
||||
_nextTrack.create(this, st::mediaPlayerNextButton);
|
||||
_nextTrack->show();
|
||||
_nextTrack->setClickedCallback([=]() {
|
||||
instance()->next();
|
||||
instance()->next(_type);
|
||||
});
|
||||
hidePlaylistOn(_previousTrack);
|
||||
hidePlaylistOn(_nextTrack);
|
||||
updatePlayPrevNextPositions();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ class FlatLabel;
|
|||
class LabelSimple;
|
||||
class IconButton;
|
||||
class PlainShadow;
|
||||
class DropdownMenu;
|
||||
class FilledSlider;
|
||||
template <typename Widget>
|
||||
class FadeWrap;
|
||||
|
@ -85,6 +86,7 @@ private:
|
|||
[[nodiscard]] int getTimeRight() const;
|
||||
void updateOverLabelsState(QPoint pos);
|
||||
void updateOverLabelsState(bool over);
|
||||
void hidePlaylistOn(const object_ptr<Ui::IconButton> &button);
|
||||
|
||||
void updatePlayPrevNextPositions();
|
||||
void updateLabelsGeometry();
|
||||
|
@ -110,7 +112,10 @@ private:
|
|||
void updateTimeLabel();
|
||||
void markOver(bool over);
|
||||
|
||||
void showOrderMenu();
|
||||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
const not_null<Ui::RpWidget*> _orderMenuParent;
|
||||
|
||||
crl::time _seekPositionMs = -1;
|
||||
crl::time _lastDurationMs = 0;
|
||||
|
@ -149,7 +154,8 @@ private:
|
|||
object_ptr<Ui::IconButton> _close;
|
||||
object_ptr<Ui::PlainShadow> _shadow = { nullptr };
|
||||
object_ptr<Ui::FilledSlider> _playbackSlider;
|
||||
object_ptr<Dropdown> _volume;
|
||||
base::unique_qptr<Dropdown> _volume;
|
||||
base::unique_qptr<Ui::DropdownMenu> _orderMenu;
|
||||
std::unique_ptr<View::PlaybackProgress> _playbackProgress;
|
||||
std::unique_ptr<SpeedController> _speedController;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue