Add play/pause button to video stories.

This commit is contained in:
John Preston 2023-07-19 18:34:17 +04:00
parent c2805d92a5
commit 80bdf9b74c
5 changed files with 102 additions and 0 deletions

View File

@ -902,10 +902,24 @@ void Controller::subscribeToSession() {
});
}
PauseState Controller::pauseState() const {
const auto inactive = !_windowActive
|| _replyActive
|| _layerShown
|| _menuShown;
const auto playing = !inactive && !_paused;
return playing
? PauseState::Playing
: inactive
? PauseState::Inactive
: PauseState::Paused;
}
void Controller::updatePlayingAllowed() {
if (!_shown) {
return;
}
_header->updatePauseState();
setPlayingAllowed(_started
&& _windowActive
&& !_paused

View File

@ -72,6 +72,12 @@ enum class HeaderLayout {
Outside,
};
enum class PauseState {
Playing,
Paused,
Inactive,
};
struct SiblingLayout {
QRect geometry;
QRect userpic;
@ -136,6 +142,8 @@ public:
void contentPressed(bool pressed);
void setMenuShown(bool shown);
[[nodiscard]] PauseState pauseState() const;
void repaintSibling(not_null<Sibling*> sibling);
[[nodiscard]] SiblingView sibling(SiblingType type) const;

View File

@ -272,6 +272,8 @@ void Header::show(HeaderData data) {
_userpic = nullptr;
_info = nullptr;
_privacy = nullptr;
_playPause = nullptr;
_volumeToggle = nullptr;
const auto parent = _controller->wrap();
auto widget = std::make_unique<Ui::RpWidget>(parent);
const auto raw = widget.get();
@ -336,11 +338,61 @@ void Header::show(HeaderData data) {
});
if (data.video) {
_playPause = std::make_unique<Ui::IconButton>(
_widget.get(),
st::storiesPlayButton);
_playPause->show();
_playPause->setClickedCallback([=] {
_controller->togglePaused(_pauseState != PauseState::Paused);
});
_volumeToggle = std::make_unique<Ui::IconButton>(
_widget.get(),
st::storiesVolumeButton);
_volumeToggle->show();
_widget->widthValue() | rpl::start_with_next([=](int width) {
const auto playPause = st::storiesPlayButtonPosition;
_playPause->moveToRight(playPause.x(), playPause.y(), width);
const auto volume = st::storiesVolumeButtonPosition;
_volumeToggle->moveToRight(volume.x(), volume.y(), width);
}, _playPause->lifetime());
_pauseState = _controller->pauseState();
applyPauseState();
} else {
_playPause = nullptr;
_volumeToggle = nullptr;
}
if (timestamp.changes > 0) {
_dateUpdateTimer.callOnce(timestamp.changes * crl::time(1000));
}
}
void Header::updatePauseState() {
if (!_playPause) {
return;
} else if (const auto s = _controller->pauseState(); _pauseState != s) {
_pauseState = s;
applyPauseState();
}
}
void Header::applyPauseState() {
Expects(_playPause != nullptr);
const auto paused = (_pauseState == PauseState::Paused);
const auto inactive = (_pauseState == PauseState::Inactive);
_playPause->setAttribute(Qt::WA_TransparentForMouseEvents, inactive);
if (inactive) {
_playPause->clearState();
}
const auto icon = paused ? nullptr : &st::storiesPauseIcon;
_playPause->setIconOverride(icon, icon);
}
void Header::raise() {
if (_widget) {
_widget->raise();

View File

@ -27,6 +27,7 @@ class FadeWrap;
namespace Media::Stories {
class Controller;
enum class PauseState;
struct HeaderData {
not_null<UserData*> user;
@ -47,14 +48,19 @@ public:
explicit Header(not_null<Controller*> controller);
~Header();
void updatePauseState();
void show(HeaderData data);
void raise();
private:
void updateDateText();
void applyPauseState();
const not_null<Controller*> _controller;
PauseState _pauseState = {};
std::unique_ptr<Ui::RpWidget> _widget;
std::unique_ptr<Ui::AbstractButton> _info;
std::unique_ptr<Ui::UserpicButton> _userpic;

View File

@ -851,3 +851,25 @@ storiesBadgeSelectedContacts: icon{{ "mediaview/mini_selected_contacts", history
storiesBadgePadding: margins(1px, 1px, 1px, 1px);
storiesBadgeOutline: 2px;
storiesBadgeShift: point(5px, 4px);
storiesPlayIcon: icon{{ "player/player_play", mediaviewPlaybackIconFgOver }};
storiesPauseIcon: icon{{ "player/player_pause", mediaviewPlaybackIconFgOver }};
storiesPlayButton: IconButton(defaultIconButton) {
width: 40px;
height: 40px;
icon: storiesPlayIcon;
iconOver: storiesPlayIcon;
iconPosition: point(8px, 8px);
rippleAreaPosition: point(4px, 4px);
rippleAreaSize: 32px;
ripple: RippleAnimation(defaultRippleAnimation) {
color: mediaviewPlaybackIconRipple;
}
}
storiesPlayButtonPosition: point(54px, 0px);
storiesVolumeButton: IconButton(storiesPlayButton) {
icon: mediaviewVolumeIcon2Over;
iconOver: mediaviewVolumeIcon2Over;
ripple: emptyRippleAnimation;
}
storiesVolumeButtonPosition: point(10px, 0px);