mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Cycle through repeat modes by repeat toggle button.
This commit is contained in:
parent
969b27cb75
commit
0309eb023e
5 changed files with 61 additions and 168 deletions
|
@ -97,21 +97,9 @@ mediaPlayerShuffleDisabledIconOver: icon {
|
||||||
mediaPlayerRepeatReverseIcon: icon {
|
mediaPlayerRepeatReverseIcon: icon {
|
||||||
{ "player/player_repeat_reverse", mediaPlayerActiveFg, point(9px, 11px)}
|
{ "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 {
|
mediaPlayerRepeatShuffleIcon: icon {
|
||||||
{ "player/player_repeat_shuffle", mediaPlayerActiveFg, point(9px, 11px)}
|
{ "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;
|
mediaPlayerRepeatDisabledRippleBg: windowBgOver;
|
||||||
|
|
||||||
mediaPlayerSpeedButton: IconButton {
|
mediaPlayerSpeedButton: IconButton {
|
||||||
|
|
|
@ -121,6 +121,13 @@ Instance::Instance()
|
||||||
handleSongUpdate(audioId);
|
handleSongUpdate(audioId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_songData.repeat.changes(
|
||||||
|
) | rpl::start_with_next([=](RepeatMode mode) {
|
||||||
|
if (mode == RepeatMode::All) {
|
||||||
|
refreshPlaylist(&_songData);
|
||||||
|
}
|
||||||
|
}, _lifetime);
|
||||||
|
|
||||||
using namespace rpl::mappers;
|
using namespace rpl::mappers;
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
Core::App().calls().currentCallValue(),
|
Core::App().calls().currentCallValue(),
|
||||||
|
@ -254,7 +261,13 @@ void Instance::clearStreamed(not_null<Data*> data, bool savePosition) {
|
||||||
void Instance::refreshPlaylist(not_null<Data*> data) {
|
void Instance::refreshPlaylist(not_null<Data*> data) {
|
||||||
if (!validPlaylist(data)) {
|
if (!validPlaylist(data)) {
|
||||||
validatePlaylist(data);
|
validatePlaylist(data);
|
||||||
} else if (!validOtherPlaylist(data)) {
|
} else {
|
||||||
|
refreshOtherPlaylist(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Instance::refreshOtherPlaylist(not_null<Data*> data) {
|
||||||
|
if (!validOtherPlaylist(data)) {
|
||||||
validateOtherPlaylist(data);
|
validateOtherPlaylist(data);
|
||||||
}
|
}
|
||||||
playlistUpdated(data);
|
playlistUpdated(data);
|
||||||
|
@ -322,12 +335,12 @@ void Instance::validatePlaylist(not_null<Data*> data) {
|
||||||
) | rpl::start_with_next([=](SparseIdsMergedSlice &&update) {
|
) | rpl::start_with_next([=](SparseIdsMergedSlice &&update) {
|
||||||
data->playlistSlice = std::move(update);
|
data->playlistSlice = std::move(update);
|
||||||
data->playlistSliceKey = key;
|
data->playlistSliceKey = key;
|
||||||
playlistUpdated(data);
|
refreshOtherPlaylist(data);
|
||||||
}, data->playlistLifetime);
|
}, data->playlistLifetime);
|
||||||
} else {
|
} else {
|
||||||
data->playlistSlice = std::nullopt;
|
data->playlistSlice = std::nullopt;
|
||||||
data->playlistSliceKey = data->playlistRequestedKey = std::nullopt;
|
data->playlistSliceKey = data->playlistRequestedKey = std::nullopt;
|
||||||
playlistUpdated(data);
|
refreshOtherPlaylist(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,7 +469,14 @@ bool Instance::moveInPlaylist(
|
||||||
};
|
};
|
||||||
const auto newIndex = *data->playlistIndex
|
const auto newIndex = *data->playlistIndex
|
||||||
+ (data->order.current() == OrderMode::Reverse ? -delta : delta);
|
+ (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);
|
return jumpByItem(item);
|
||||||
} else if (data->repeat.current() == RepeatMode::All
|
} else if (data->repeat.current() == RepeatMode::All
|
||||||
&& data->playlistOtherSlice
|
&& 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) {
|
void Instance::startSeeking(AudioMsgId::Type type) {
|
||||||
if (auto data = getData(type)) {
|
if (auto data = getData(type)) {
|
||||||
data->seeking = data->current;
|
data->seeking = data->current;
|
||||||
|
|
|
@ -116,50 +116,6 @@ public:
|
||||||
return AudioMsgId();
|
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 {
|
[[nodiscard]] bool isSeeking(AudioMsgId::Type type) const {
|
||||||
if (const auto data = getData(type)) {
|
if (const auto data = getData(type)) {
|
||||||
return (data->seeking == data->current);
|
return (data->seeking == data->current);
|
||||||
|
@ -268,6 +224,7 @@ private:
|
||||||
|
|
||||||
void setCurrent(const AudioMsgId &audioId);
|
void setCurrent(const AudioMsgId &audioId);
|
||||||
void refreshPlaylist(not_null<Data*> data);
|
void refreshPlaylist(not_null<Data*> data);
|
||||||
|
void refreshOtherPlaylist(not_null<Data*> data);
|
||||||
std::optional<SliceKey> playlistKey(not_null<const Data*> data) const;
|
std::optional<SliceKey> playlistKey(not_null<const Data*> data) const;
|
||||||
bool validPlaylist(not_null<const Data*> data) const;
|
bool validPlaylist(not_null<const Data*> data) const;
|
||||||
void validatePlaylist(not_null<Data*> data);
|
void validatePlaylist(not_null<Data*> data);
|
||||||
|
|
|
@ -70,22 +70,12 @@ void PrepareRepeatDropdown(not_null<Dropdown*> dropdown) {
|
||||||
auto &settings = Core::App().settings();
|
auto &settings = Core::App().settings();
|
||||||
const auto active = (settings.playerRepeatMode() == mode);
|
const auto active = (settings.playerRepeatMode() == mode);
|
||||||
settings.setPlayerRepeatMode(active ? RepeatMode::None : 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();
|
Core::App().saveSettingsDelayed();
|
||||||
};
|
};
|
||||||
const auto toggleOrder = [](OrderMode mode) {
|
const auto toggleOrder = [](OrderMode mode) {
|
||||||
auto &settings = Core::App().settings();
|
auto &settings = Core::App().settings();
|
||||||
const auto active = (settings.playerOrderMode() == mode);
|
const auto active = (settings.playerOrderMode() == mode);
|
||||||
settings.setPlayerOrderMode(active ? OrderMode::Default : 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();
|
Core::App().saveSettingsDelayed();
|
||||||
};
|
};
|
||||||
repeatOne->setClickedCallback([=] { toggleRepeat(RepeatMode::One); });
|
repeatOne->setClickedCallback([=] { toggleRepeat(RepeatMode::One); });
|
||||||
|
|
|
@ -292,31 +292,22 @@ Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
|
||||||
|
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
Core::App().settings().playerRepeatModeValue(),
|
Core::App().settings().playerRepeatModeValue(),
|
||||||
Core::App().settings().playerOrderModeValue(),
|
Core::App().settings().playerOrderModeValue()
|
||||||
instance()->repeatModeValue(AudioMsgId::Type::Song),
|
|
||||||
instance()->orderModeValue(AudioMsgId::Type::Song)
|
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
updateRepeatToggleIcon();
|
updateRepeatToggleIcon();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
_repeatToggle->setClickedCallback([=] {
|
_repeatToggle->setClickedCallback([=] {
|
||||||
const auto type = AudioMsgId::Type::Song;
|
auto &settings = Core::App().settings();
|
||||||
const auto repeat = Core::App().settings().playerRepeatMode();
|
settings.setPlayerRepeatMode([&] {
|
||||||
const auto order = Core::App().settings().playerOrderMode();
|
switch (settings.playerRepeatMode()) {
|
||||||
const auto mayBeActive = (repeat != RepeatMode::None)
|
case RepeatMode::None: return RepeatMode::One;
|
||||||
|| (order != OrderMode::Default);
|
case RepeatMode::One: return RepeatMode::All;
|
||||||
const auto active = mayBeActive
|
case RepeatMode::All: return RepeatMode::None;
|
||||||
&& (repeat == instance()->repeatMode(type))
|
}
|
||||||
&& (order == instance()->orderMode(type));
|
Unexpected("Repeat mode in Settings.");
|
||||||
if (!active && !mayBeActive) {
|
}());
|
||||||
Core::App().settings().setPlayerRepeatMode(RepeatMode::All);
|
Core::App().saveSettingsDelayed();
|
||||||
Core::App().saveSettingsDelayed();
|
|
||||||
}
|
|
||||||
instance()->setRepeatMode(type, active
|
|
||||||
? RepeatMode::None
|
|
||||||
: mayBeActive
|
|
||||||
? repeat
|
|
||||||
: RepeatMode::All);
|
|
||||||
instance()->setOrderMode(type, active ? OrderMode::Default : order);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
_playbackSpeed->saved(
|
_playbackSpeed->saved(
|
||||||
|
@ -577,70 +568,34 @@ void Widget::updateRepeatToggleIcon() {
|
||||||
const auto type = AudioMsgId::Type::Song;
|
const auto type = AudioMsgId::Type::Song;
|
||||||
const auto repeat = Core::App().settings().playerRepeatMode();
|
const auto repeat = Core::App().settings().playerRepeatMode();
|
||||||
const auto order = Core::App().settings().playerOrderMode();
|
const auto order = Core::App().settings().playerOrderMode();
|
||||||
const auto active = (repeat == instance()->repeatMode(type))
|
if (repeat == RepeatMode::None && order == OrderMode::Default) {
|
||||||
&& (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:
|
|
||||||
_repeatToggle->setIconOverride(
|
_repeatToggle->setIconOverride(
|
||||||
(active
|
&st::mediaPlayerRepeatDisabledIcon,
|
||||||
? &st::mediaPlayerRepeatOneIcon
|
&st::mediaPlayerRepeatDisabledIconOver);
|
||||||
: &st::mediaPlayerRepeatOneDisabledIcon),
|
_repeatToggle->setRippleColorOverride(
|
||||||
active ? nullptr : &st::mediaPlayerRepeatOneDisabledIconOver);
|
&st::mediaPlayerRepeatDisabledRippleBg);
|
||||||
break;
|
return;
|
||||||
case RepeatMode::All:
|
}
|
||||||
switch (order) {
|
const auto &icon = [&]() -> const style::icon& {
|
||||||
case OrderMode::Default:
|
switch (repeat) {
|
||||||
_repeatToggle->setIconOverride(
|
case RepeatMode::None:
|
||||||
(active ? nullptr : &st::mediaPlayerRepeatDisabledIcon),
|
switch (order) {
|
||||||
(active ? nullptr : &st::mediaPlayerRepeatDisabledIconOver));
|
case OrderMode::Reverse: return st::mediaPlayerReverseIcon;
|
||||||
|
case OrderMode::Shuffle: return st::mediaPlayerShuffleIcon;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OrderMode::Reverse:
|
case RepeatMode::One: return st::mediaPlayerRepeatOneIcon;
|
||||||
_repeatToggle->setIconOverride(
|
case RepeatMode::All:
|
||||||
(active
|
switch (order) {
|
||||||
? &st::mediaPlayerRepeatReverseIcon
|
case OrderMode::Default: return st::mediaPlayerRepeatButton.icon;
|
||||||
: &st::mediaPlayerRepeatReverseDisabledIcon),
|
case OrderMode::Reverse: return st::mediaPlayerRepeatReverseIcon;
|
||||||
(active
|
case OrderMode::Shuffle: return st::mediaPlayerRepeatShuffleIcon;
|
||||||
? nullptr
|
}
|
||||||
: &st::mediaPlayerRepeatReverseDisabledIconOver));
|
|
||||||
break;
|
|
||||||
case OrderMode::Shuffle:
|
|
||||||
_repeatToggle->setIconOverride(
|
|
||||||
(active
|
|
||||||
? &st::mediaPlayerRepeatShuffleIcon
|
|
||||||
: &st::mediaPlayerRepeatShuffleDisabledIcon),
|
|
||||||
(active
|
|
||||||
? nullptr
|
|
||||||
: &st::mediaPlayerRepeatShuffleDisabledIconOver));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
Unexpected("Repeat / order values in Settings.");
|
||||||
}
|
}();
|
||||||
_repeatToggle->setRippleColorOverride(
|
_repeatToggle->setIconOverride(&icon);
|
||||||
active ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::checkForTypeChange() {
|
void Widget::checkForTypeChange() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue