Cycle through repeat modes by repeat toggle button.

This commit is contained in:
John Preston 2021-11-19 19:27:10 +04:00
parent 969b27cb75
commit 0309eb023e
5 changed files with 61 additions and 168 deletions

View file

@ -97,21 +97,9 @@ mediaPlayerShuffleDisabledIconOver: icon {
mediaPlayerRepeatReverseIcon: icon {
{ "player/player_repeat_reverse", mediaPlayerActiveFg, point(9px, 11px)}
};
mediaPlayerRepeatReverseDisabledIcon: icon {
{ "player/player_repeat_reverse", menuIconFg, point(9px, 11px)}
};
mediaPlayerRepeatReverseDisabledIconOver: icon {
{ "player/player_repeat_reverse", menuIconFgOver, point(9px, 11px)}
};
mediaPlayerRepeatShuffleIcon: icon {
{ "player/player_repeat_shuffle", mediaPlayerActiveFg, point(9px, 11px)}
};
mediaPlayerRepeatShuffleDisabledIcon: icon {
{ "player/player_repeat_shuffle", menuIconFg, point(9px, 11px)}
};
mediaPlayerRepeatShuffleDisabledIconOver: icon {
{ "player/player_repeat_shuffle", menuIconFgOver, point(9px, 11px)}
};
mediaPlayerRepeatDisabledRippleBg: windowBgOver;
mediaPlayerSpeedButton: IconButton {

View file

@ -121,6 +121,13 @@ Instance::Instance()
handleSongUpdate(audioId);
});
_songData.repeat.changes(
) | rpl::start_with_next([=](RepeatMode mode) {
if (mode == RepeatMode::All) {
refreshPlaylist(&_songData);
}
}, _lifetime);
using namespace rpl::mappers;
rpl::combine(
Core::App().calls().currentCallValue(),
@ -254,7 +261,13 @@ void Instance::clearStreamed(not_null<Data*> data, bool savePosition) {
void Instance::refreshPlaylist(not_null<Data*> data) {
if (!validPlaylist(data)) {
validatePlaylist(data);
} else if (!validOtherPlaylist(data)) {
} else {
refreshOtherPlaylist(data);
}
}
void Instance::refreshOtherPlaylist(not_null<Data*> data) {
if (!validOtherPlaylist(data)) {
validateOtherPlaylist(data);
}
playlistUpdated(data);
@ -322,12 +335,12 @@ void Instance::validatePlaylist(not_null<Data*> data) {
) | rpl::start_with_next([=](SparseIdsMergedSlice &&update) {
data->playlistSlice = std::move(update);
data->playlistSliceKey = key;
playlistUpdated(data);
refreshOtherPlaylist(data);
}, data->playlistLifetime);
} else {
data->playlistSlice = std::nullopt;
data->playlistSliceKey = data->playlistRequestedKey = std::nullopt;
playlistUpdated(data);
refreshOtherPlaylist(data);
}
}
@ -456,7 +469,14 @@ bool Instance::moveInPlaylist(
};
const auto newIndex = *data->playlistIndex
+ (data->order.current() == OrderMode::Reverse ? -delta : delta);
if (const auto item = itemByIndex(data, newIndex)) {
const auto useIndex = (!data->playlistSlice
|| data->playlistSlice->skippedAfter() != 0
|| data->playlistSlice->skippedBefore() != 0
|| !data->playlistSlice->size())
? newIndex
: ((newIndex + int(data->playlistSlice->size()))
% int(data->playlistSlice->size()));
if (const auto item = itemByIndex(data, useIndex)) {
return jumpByItem(item);
} else if (data->repeat.current() == RepeatMode::All
&& data->playlistOtherSlice
@ -740,23 +760,6 @@ void Instance::playPauseCancelClicked(AudioMsgId::Type type) {
}
}
void Instance::setRepeatMode(AudioMsgId::Type type, RepeatMode mode) {
if (const auto data = getData(type)) {
const auto otherNeeded = (mode == RepeatMode::All)
&& (data->repeat.current() != RepeatMode::All);
data->repeat = mode;
if (otherNeeded) {
refreshPlaylist(data);
}
}
}
void Instance::setOrderMode(AudioMsgId::Type type, OrderMode mode) {
if (const auto data = getData(type)) {
data->order = mode;
}
}
void Instance::startSeeking(AudioMsgId::Type type) {
if (auto data = getData(type)) {
data->seeking = data->current;

View file

@ -116,50 +116,6 @@ public:
return AudioMsgId();
}
[[nodiscard]] RepeatMode repeatMode(AudioMsgId::Type type) const {
if (const auto data = getData(type)) {
return data->repeat.current();
}
return RepeatMode::None;
}
[[nodiscard]] rpl::producer<RepeatMode> repeatModeValue(
AudioMsgId::Type type) const {
if (const auto data = getData(type)) {
return data->repeat.value();
}
return rpl::single(RepeatMode::None);
}
[[nodiscard]] rpl::producer<RepeatMode> repeatModeChanges(
AudioMsgId::Type type) const {
if (const auto data = getData(type)) {
return data->repeat.changes();
}
return rpl::never<RepeatMode>();
}
void setRepeatMode(AudioMsgId::Type type, RepeatMode mode);
[[nodiscard]] OrderMode orderMode(AudioMsgId::Type type) const {
if (const auto data = getData(type)) {
return data->order.current();
}
return OrderMode::Default;
}
[[nodiscard]] rpl::producer<OrderMode> orderModeValue(
AudioMsgId::Type type) const {
if (const auto data = getData(type)) {
return data->order.value();
}
return rpl::single(OrderMode::Default);
}
[[nodiscard]] rpl::producer<OrderMode> orderModeChanges(
AudioMsgId::Type type) const {
if (const auto data = getData(type)) {
return data->order.changes();
}
return rpl::never<OrderMode>();
}
void setOrderMode(AudioMsgId::Type type, OrderMode mode);
[[nodiscard]] bool isSeeking(AudioMsgId::Type type) const {
if (const auto data = getData(type)) {
return (data->seeking == data->current);
@ -268,6 +224,7 @@ private:
void setCurrent(const AudioMsgId &audioId);
void refreshPlaylist(not_null<Data*> data);
void refreshOtherPlaylist(not_null<Data*> data);
std::optional<SliceKey> playlistKey(not_null<const Data*> data) const;
bool validPlaylist(not_null<const Data*> data) const;
void validatePlaylist(not_null<Data*> data);

View file

@ -70,22 +70,12 @@ void PrepareRepeatDropdown(not_null<Dropdown*> dropdown) {
auto &settings = Core::App().settings();
const auto active = (settings.playerRepeatMode() == mode);
settings.setPlayerRepeatMode(active ? RepeatMode::None : mode);
const auto type = AudioMsgId::Type::Song;
instance()->setRepeatMode(type, settings.playerRepeatMode());
if (!active) {
instance()->setOrderMode(type, settings.playerOrderMode());
}
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);
const auto type = AudioMsgId::Type::Song;
instance()->setOrderMode(type, settings.playerOrderMode());
if (!active) {
instance()->setRepeatMode(type, settings.playerRepeatMode());
}
Core::App().saveSettingsDelayed();
};
repeatOne->setClickedCallback([=] { toggleRepeat(RepeatMode::One); });

View file

@ -292,31 +292,22 @@ Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
rpl::combine(
Core::App().settings().playerRepeatModeValue(),
Core::App().settings().playerOrderModeValue(),
instance()->repeatModeValue(AudioMsgId::Type::Song),
instance()->orderModeValue(AudioMsgId::Type::Song)
Core::App().settings().playerOrderModeValue()
) | rpl::start_with_next([=] {
updateRepeatToggleIcon();
}, lifetime());
_repeatToggle->setClickedCallback([=] {
const auto type = AudioMsgId::Type::Song;
const auto repeat = Core::App().settings().playerRepeatMode();
const auto order = Core::App().settings().playerOrderMode();
const auto mayBeActive = (repeat != RepeatMode::None)
|| (order != OrderMode::Default);
const auto active = mayBeActive
&& (repeat == instance()->repeatMode(type))
&& (order == instance()->orderMode(type));
if (!active && !mayBeActive) {
Core::App().settings().setPlayerRepeatMode(RepeatMode::All);
Core::App().saveSettingsDelayed();
}
instance()->setRepeatMode(type, active
? RepeatMode::None
: mayBeActive
? repeat
: RepeatMode::All);
instance()->setOrderMode(type, active ? OrderMode::Default : order);
auto &settings = Core::App().settings();
settings.setPlayerRepeatMode([&] {
switch (settings.playerRepeatMode()) {
case RepeatMode::None: return RepeatMode::One;
case RepeatMode::One: return RepeatMode::All;
case RepeatMode::All: return RepeatMode::None;
}
Unexpected("Repeat mode in Settings.");
}());
Core::App().saveSettingsDelayed();
});
_playbackSpeed->saved(
@ -577,70 +568,34 @@ void Widget::updateRepeatToggleIcon() {
const auto type = AudioMsgId::Type::Song;
const auto repeat = Core::App().settings().playerRepeatMode();
const auto order = Core::App().settings().playerOrderMode();
const auto active = (repeat == instance()->repeatMode(type))
&& (order == instance()->orderMode(type))
&& (repeat != RepeatMode::None || order != OrderMode::Default);
switch (repeat) {
case RepeatMode::None:
switch (order) {
case OrderMode::Default:
_repeatToggle->setIconOverride(
&st::mediaPlayerRepeatDisabledIcon,
&st::mediaPlayerRepeatDisabledIconOver);
break;
case OrderMode::Reverse:
_repeatToggle->setIconOverride(
(active
? &st::mediaPlayerReverseIcon
: &st::mediaPlayerReverseDisabledIcon),
active ? nullptr : &st::mediaPlayerReverseDisabledIconOver);
break;
case OrderMode::Shuffle:
_repeatToggle->setIconOverride(
(active
? &st::mediaPlayerShuffleIcon
: &st::mediaPlayerShuffleDisabledIcon),
active ? nullptr : &st::mediaPlayerShuffleDisabledIconOver);
break;
}
break;
case RepeatMode::One:
if (repeat == RepeatMode::None && order == OrderMode::Default) {
_repeatToggle->setIconOverride(
(active
? &st::mediaPlayerRepeatOneIcon
: &st::mediaPlayerRepeatOneDisabledIcon),
active ? nullptr : &st::mediaPlayerRepeatOneDisabledIconOver);
break;
case RepeatMode::All:
switch (order) {
case OrderMode::Default:
_repeatToggle->setIconOverride(
(active ? nullptr : &st::mediaPlayerRepeatDisabledIcon),
(active ? nullptr : &st::mediaPlayerRepeatDisabledIconOver));
&st::mediaPlayerRepeatDisabledIcon,
&st::mediaPlayerRepeatDisabledIconOver);
_repeatToggle->setRippleColorOverride(
&st::mediaPlayerRepeatDisabledRippleBg);
return;
}
const auto &icon = [&]() -> const style::icon& {
switch (repeat) {
case RepeatMode::None:
switch (order) {
case OrderMode::Reverse: return st::mediaPlayerReverseIcon;
case OrderMode::Shuffle: return st::mediaPlayerShuffleIcon;
}
break;
case OrderMode::Reverse:
_repeatToggle->setIconOverride(
(active
? &st::mediaPlayerRepeatReverseIcon
: &st::mediaPlayerRepeatReverseDisabledIcon),
(active
? nullptr
: &st::mediaPlayerRepeatReverseDisabledIconOver));
break;
case OrderMode::Shuffle:
_repeatToggle->setIconOverride(
(active
? &st::mediaPlayerRepeatShuffleIcon
: &st::mediaPlayerRepeatShuffleDisabledIcon),
(active
? nullptr
: &st::mediaPlayerRepeatShuffleDisabledIconOver));
case RepeatMode::One: return st::mediaPlayerRepeatOneIcon;
case RepeatMode::All:
switch (order) {
case OrderMode::Default: return st::mediaPlayerRepeatButton.icon;
case OrderMode::Reverse: return st::mediaPlayerRepeatReverseIcon;
case OrderMode::Shuffle: return st::mediaPlayerRepeatShuffleIcon;
}
break;
}
break;
}
_repeatToggle->setRippleColorOverride(
active ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
Unexpected("Repeat / order values in Settings.");
}();
_repeatToggle->setIconOverride(&icon);
}
void Widget::checkForTypeChange() {