Added context menu to voice playback speed button.

Fixed #16868.
Fixed #16138.
This commit is contained in:
23rd 2021-08-31 02:31:34 +03:00 committed by John Preston
parent 2f1db4f449
commit 81a72caf07
16 changed files with 189 additions and 27 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1,015 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -2855,6 +2855,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_photo_editor_menu_flip" = "Flip";
"lng_photo_editor_menu_duplicate" = "Duplicate";
"lng_voice_speed_slow" = "Slow";
"lng_voice_speed_normal" = "Normal";
"lng_voice_speed_fast" = "Fast";
"lng_voice_speed_very_fast" = "Very fast";
// Wnd specific
"lng_wnd_choose_program_menu" = "Choose Default Program...";

View file

@ -77,9 +77,9 @@ mediaPlayerSpeedButton: IconButton {
height: 30px;
icon: icon {
{ "voice2x", mediaPlayerActiveFg, point(8px, 11px) }
{ "voice_speed/voice_speed2", mediaPlayerActiveFg }
};
iconPosition: point(0px, 0px);
iconPosition: point(3px, 10px);
rippleAreaPosition: point(3px, 5px);
rippleAreaSize: 25px;
@ -88,15 +88,38 @@ mediaPlayerSpeedButton: IconButton {
}
}
mediaPlayerSpeedDisabledIcon: icon {
{ "voice2x", menuIconFg, point(8px, 11px)}
{ "voice_speed/voice_speed2", menuIconFg }
};
mediaPlayerSpeedDisabledIconOver: icon {
{ "voice2x", menuIconFgOver, point(8px, 11px)}
{ "voice_speed/voice_speed2", menuIconFgOver }
};
mediaPlayerSpeedSlowIcon: icon {
{ "voice_speed/voice_speed0.5", mediaPlayerActiveFg }
};
mediaPlayerSpeedSlowDisabledIcon: icon {
{ "voice_speed/voice_speed0.5", menuIconFg }
};
mediaPlayerSpeedSlowDisabledIconOver: icon {
{ "voice_speed/voice_speed0.5", menuIconFgOver }
};
mediaPlayerSpeedFastIcon: icon {
{ "voice_speed/voice_speed1.5", mediaPlayerActiveFg }
};
mediaPlayerSpeedFastDisabledIcon: icon {
{ "voice_speed/voice_speed1.5", menuIconFg }
};
mediaPlayerSpeedFastDisabledIconOver: icon {
{ "voice_speed/voice_speed1.5", menuIconFgOver }
};
mediaPlayerSpeedDisabledRippleBg: windowBgOver;
mediaPlayerSpeedInactiveIcon: icon {
{ "voice2x", mediaPlayerInactiveFg, point(8px, 11px)}
};
mediaPlayerPopupMenu: PopupMenu(defaultPopupMenu) {
menu: Menu(defaultMenu) {
itemIconPosition: point(6px, 5px);
itemPadding: margins(34px, 8px, 17px, 7px);
}
}
mediaPlayerMenuCheck: icon {{ "player_check", mediaPlayerActiveFg }};
mediaPlayerVolumeIcon0: icon {
{ "player_volume0", mediaPlayerActiveFg },

View file

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/continuous_sliders.h"
#include "ui/widgets/shadow.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h"
#include "ui/effects/ripple_animation.h"
#include "ui/text/format_values.h"
#include "ui/text/format_song_document_name.h"
@ -60,6 +61,153 @@ private:
};
class Widget::SpeedButton : public Ui::IconButton {
public:
SpeedButton(QWidget *parent, const style::IconButton &st);
[[nodiscard]] rpl::producer<> saved() const;
protected:
void contextMenuEvent(QContextMenuEvent *e) override;
private:
class SpeedController final {
public:
SpeedController() {
setSpeed(Core::App().settings().voicePlaybackSpeed());
}
[[nodiscard]] rpl::producer<float64> speedValue() const {
return _speedChanged.events_starting_with(speed());
}
[[nodiscard]] rpl::producer<> saved() const {
return _saved.events();
}
[[nodiscard]] float64 speed() const {
return _isDefault ? 1. : _speed;
}
[[nodiscard]] bool isDefault() const {
return _isDefault;
}
[[nodiscard]] float64 lastNonDefaultSpeed() const {
return _speed;
}
void toggleDefault() {
_isDefault = !_isDefault;
_speedChanged.fire(speed());
}
void setSpeed(float64 newSpeed) {
if (!(_isDefault = (newSpeed == 1.))) {
_speed = newSpeed;
}
_speedChanged.fire(speed());
}
void save() {
Core::App().settings().setVoicePlaybackSpeed(speed());
Core::App().saveSettingsDelayed();
_saved.fire({});
}
private:
float64 _speed = 2.;
bool _isDefault = true;
rpl::event_stream<float64> _speedChanged;
rpl::event_stream<> _saved;
};
SpeedController _speed;
base::unique_qptr<Ui::PopupMenu> _menu;
};
Widget::SpeedButton::SpeedButton(QWidget *parent, const style::IconButton &st)
: IconButton(parent, st) {
setClickedCallback([=] {
_speed.toggleDefault();
_speed.save();
});
struct Icons {
const style::icon *icon = nullptr;
const style::icon *over = nullptr;
};
_speed.speedValue(
) | rpl::start_with_next([=](float64 speed) {
const auto isDefaultSpeed = _speed.isDefault();
const auto nonDefaultSpeed = _speed.lastNonDefaultSpeed();
const auto icons = [&]() -> Icons {
if (nonDefaultSpeed == .5) {
return {
.icon = isDefaultSpeed
? &st::mediaPlayerSpeedSlowDisabledIcon
: &st::mediaPlayerSpeedSlowIcon,
.over = isDefaultSpeed
? &st::mediaPlayerSpeedSlowDisabledIconOver
: &st::mediaPlayerSpeedSlowIcon,
};
} else if (nonDefaultSpeed == 1.5) {
return {
.icon = isDefaultSpeed
? &st::mediaPlayerSpeedFastDisabledIcon
: &st::mediaPlayerSpeedFastIcon,
.over = isDefaultSpeed
? &st::mediaPlayerSpeedFastDisabledIconOver
: &st::mediaPlayerSpeedFastIcon,
};
} else {
return {
.icon = isDefaultSpeed
? &st::mediaPlayerSpeedDisabledIcon
: nullptr, // 2x icon.
.over = isDefaultSpeed
? &st::mediaPlayerSpeedDisabledIconOver
: nullptr, // 2x icon.
};
}
}();
setIconOverride(icons.icon, icons.over);
setRippleColorOverride(isDefaultSpeed
? &st::mediaPlayerSpeedDisabledRippleBg
: nullptr);
}, lifetime());
}
void Widget::SpeedButton::contextMenuEvent(QContextMenuEvent *e) {
_menu = base::make_unique_q<Ui::PopupMenu>(
this,
st::mediaPlayerPopupMenu);
const auto setPlaybackSpeed = [=](float64 speed) {
_speed.setSpeed(speed);
_speed.save();
};
const auto currentSpeed = _speed.speed();
const auto addSpeed = [&](float64 speed, QString text = QString()) {
if (text.isEmpty()) {
text = QString::number(speed);
}
const auto action = _menu->addAction(
text,
[=] { setPlaybackSpeed(speed); },
(speed == currentSpeed) ? &st::mediaPlayerMenuCheck : nullptr);
};
addSpeed(0.5, tr::lng_voice_speed_slow(tr::now));
addSpeed(1., tr::lng_voice_speed_normal(tr::now));
addSpeed(1.5, tr::lng_voice_speed_fast(tr::now));
addSpeed(2., tr::lng_voice_speed_very_fast(tr::now));
_menu->popup(e->globalPos());
}
rpl::producer<> Widget::SpeedButton::saved() const {
return _speed.saved();
}
Widget::PlayButton::PlayButton(QWidget *parent) : Ui::RippleButton(parent, st::mediaPlayerButton.ripple)
, _layout(st::mediaPlayerButton, [this] { update(); }) {
resize(st::mediaPlayerButtonSize);
@ -146,15 +294,10 @@ Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
instance()->toggleRepeat(AudioMsgId::Type::Song);
});
updatePlaybackSpeedIcon();
_playbackSpeed->setClickedCallback([=] {
const auto doubled = (Core::App().settings().voicePlaybackSpeed()
== 2.);
Core::App().settings().setVoicePlaybackSpeed(doubled ? 1. : 2.);
_playbackSpeed->saved(
) | rpl::start_with_next([=] {
instance()->updateVoicePlaybackSpeed();
updatePlaybackSpeedIcon();
Core::App().saveSettingsDelayed();
});
}, lifetime());
subscribe(instance()->repeatChangedNotifier(), [this](AudioMsgId::Type type) {
if (type == _type) {
@ -403,16 +546,6 @@ void Widget::updateRepeatTrackIcon() {
_repeatTrack->setRippleColorOverride(repeating ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
}
void Widget::updatePlaybackSpeedIcon() {
const auto speed = Core::App().settings().voicePlaybackSpeed();
const auto isDefaultSpeed = (speed == 1.);
_playbackSpeed->setIconOverride(
isDefaultSpeed ? &st::mediaPlayerSpeedDisabledIcon : nullptr,
isDefaultSpeed ? &st::mediaPlayerSpeedDisabledIconOver : nullptr);
_playbackSpeed->setRippleColorOverride(
isDefaultSpeed ? &st::mediaPlayerSpeedDisabledRippleBg : nullptr);
}
void Widget::checkForTypeChange() {
auto hasActiveType = [](AudioMsgId::Type type) {
const auto current = instance()->current(type);

View file

@ -35,6 +35,7 @@ namespace Media {
namespace Player {
class PlayButton;
class SpeedButton;
class VolumeWidget;
struct TrackState;
@ -77,7 +78,6 @@ private:
void updateRepeatTrackIcon();
void updateControlsVisibility();
void updateControlsGeometry();
void updatePlaybackSpeedIcon();
void createPrevNextButtons();
void destroyPrevNextButtons();
@ -113,6 +113,7 @@ private:
bool _labelsDown = false;
class PlayButton;
class SpeedButton;
object_ptr<Ui::FlatLabel> _nameLabel;
object_ptr<Ui::LabelSimple> _timeLabel;
object_ptr<Ui::IconButton> _previousTrack = { nullptr };
@ -120,7 +121,7 @@ private:
object_ptr<Ui::IconButton> _nextTrack = { nullptr };
object_ptr<Ui::IconButton> _volumeToggle;
object_ptr<Ui::IconButton> _repeatTrack;
object_ptr<Ui::IconButton> _playbackSpeed;
object_ptr<SpeedButton> _playbackSpeed;
object_ptr<Ui::IconButton> _close;
object_ptr<Ui::PlainShadow> _shadow = { nullptr };
object_ptr<Ui::FilledSlider> _playbackSlider;