Hide controls in wide video mode.

This commit is contained in:
John Preston 2021-05-11 17:17:35 +04:00
parent 0db0abe608
commit 64c34b7029
6 changed files with 192 additions and 36 deletions

View File

@ -30,7 +30,9 @@ LargeVideo::LargeVideo(
, _st(st)
, _pin(st::groupCallLargeVideoPin)
, _pinButton(&_content)
, _topControls(_st.controlsAlign == style::al_top) {
, _controlsShown(_st.controlsAlign == style::al_top)
, _topControls(_st.controlsAlign == style::al_top)
, _controlsShownRatio(_controlsShown.current() ? 1. : 0.) {
_content.setVisible(visible);
setup(std::move(track), std::move(pinned));
}
@ -47,10 +49,25 @@ void LargeVideo::setGeometry(int x, int y, int width, int height) {
_content.setGeometry(x, y, width, height);
}
void LargeVideo::setControlsShown(bool shown) {
if (_mouseInside == shown) {
return;
}
_mouseInside = shown;
if (!_toggleControlsScheduled) {
_toggleControlsScheduled = true;
crl::on_main(&_content, [=] { toggleControls(); });
}
}
rpl::producer<bool> LargeVideo::pinToggled() const {
return _pinButton.clicks() | rpl::map([=] { return !_pinned; });
}
rpl::producer<float64> LargeVideo::controlsShown() const {
return _controlsShownRatio.value();
}
rpl::producer<QSize> LargeVideo::trackSizeValue() const {
return _trackSize.value();
}
@ -60,10 +77,26 @@ void LargeVideo::setup(
rpl::producer<bool> pinned) {
_content.setAttribute(Qt::WA_OpaquePaintEvent);
_content.events(
) | rpl::start_with_next([=](not_null<QEvent*> e) {
if (e->type() == QEvent::Enter) {
Ui::Integration::Instance().registerLeaveSubscription(&_content);
setControlsShown(true);
} else if (e->type() == QEvent::Leave) {
Ui::Integration::Instance().unregisterLeaveSubscription(
&_content);
setControlsShown(false);
}
}, _content.lifetime());
rpl::combine(
_content.shownValue(),
std::move(track)
) | rpl::map([=](bool shown, LargeVideoTrack track) {
if (!shown) {
_controlsAnimation.stop();
_controlsShownRatio = _controlsShown.current() ? 1. : 0.;
}
return shown ? track : LargeVideoTrack();
}) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](LargeVideoTrack track) {
@ -90,6 +123,34 @@ void LargeVideo::setup(
setupControls(std::move(pinned));
}
void LargeVideo::toggleControls() {
_toggleControlsScheduled = false;
const auto shown = _mouseInside;
if (_controlsShown.current() == shown) {
return;
}
_controlsShown = shown;
const auto callback = [=] {
_controlsShownRatio = _controlsAnimation.value(
_controlsShown.current() ? 1. : 0.);
if (_topControls) {
_content.update(0, 0, _content.width(), _st.shadowHeight);
} else {
_content.update();
}
updateControlsGeometry();
};
if (_content.isHidden()) {
updateControlsGeometry();
} else {
_controlsAnimation.start(
callback,
shown ? 0. : 1.,
shown ? 1. : 0.,
140);
}
}
void LargeVideo::setupControls(rpl::producer<bool> pinned) {
std::move(pinned) | rpl::start_with_next([=](bool pinned) {
_pinned = pinned;
@ -186,13 +247,17 @@ void LargeVideo::paint(QRect clip) {
}
void LargeVideo::paintControls(Painter &p, QRect clip) {
const auto shown = _controlsAnimation.value(_controlsShown ? 1. : 0.);
if (shown == 0.) {
const auto shown = _controlsShownRatio.current();
if (shown == 0. && _topControls) {
return;
}
const auto width = _content.width();
const auto height = _content.height();
const auto fullShift = _st.statusPosition.y() + st::normalFont->height;
const auto shift = _topControls
? anim::interpolate(-fullShift, 0, shown)
: 0;
// Shadow.
if (_shadow.isNull()) {
@ -204,7 +269,9 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
}
const auto shadowRect = QRect(
0,
_topControls ? 0 : (height - _st.shadowHeight),
(_topControls
? anim::interpolate(-_st.shadowHeight, 0, shown)
: (height - _st.shadowHeight)),
width,
_st.shadowHeight);
const auto shadowFill = shadowRect.intersected(clip);
@ -231,7 +298,7 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
- _st.namePosition.x();
const auto nameLeft = _st.namePosition.x();
const auto nameTop = _topControls
? _st.namePosition.y()
? (_st.namePosition.y() + shift)
: (height - _st.namePosition.y());
_track.row->name().drawLeftElided(p, nameLeft, nameTop, hasWidth, width);
@ -239,7 +306,7 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
p.setPen(st::groupCallVideoSubTextFg);
const auto statusLeft = _st.statusPosition.x();
const auto statusTop = _topControls
? _st.statusPosition.y()
? (_st.statusPosition.y() + shift)
: (height - _st.statusPosition.y());
_track.row->paintComplexStatusText(
p,
@ -255,7 +322,7 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
const auto &icon = st::groupCallLargeVideoCrossLine.icon;
const auto iconLeft = width - _st.iconPosition.x() - icon.width();
const auto iconTop = _topControls
? _st.iconPosition.y()
? (_st.iconPosition.y() + shift)
: (height - _st.iconPosition.y() - icon.height());
_track.row->paintMuteIcon(
p,
@ -268,7 +335,7 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
? (width - _st.pinPosition.x() - pin.width())
: _st.pinPosition.x();
const auto pinTop = _topControls
? _st.pinPosition.y()
? (_st.pinPosition.y() + shift)
: (height - _st.pinPosition.y() - pin.height());
_pin.paint(p, pinLeft, pinTop, _pinned ? 1. : 0.);
}

View File

@ -61,8 +61,10 @@ public:
void raise();
void setVisible(bool visible);
void setGeometry(int x, int y, int width, int height);
void setControlsShown(bool shown);
[[nodiscard]] rpl::producer<bool> pinToggled() const;
[[nodiscard]] rpl::producer<float64> controlsShown() const;
[[nodiscard]] rpl::producer<QSize> trackSizeValue() const;
[[nodiscard]] rpl::lifetime &lifetime() {
@ -99,6 +101,7 @@ private:
void paint(QRect clip);
void paintControls(Painter &p, QRect clip);
void updateControlsGeometry();
void toggleControls();
Content _content;
const style::GroupCallLargeVideo &_st;
@ -107,9 +110,12 @@ private:
Ui::CrossLineAnimation _pin;
Ui::AbstractButton _pinButton;
Ui::Animations::Simple _controlsAnimation;
bool _topControls = false;
rpl::variable<bool> _controlsShown = true;
const bool _topControls = true;
bool _pinned = false;
bool _controlsShown = true;
bool _mouseInside = false;
bool _toggleControlsScheduled = false;
rpl::variable<float64> _controlsShownRatio = 1.;
rpl::variable<QSize> _trackSize;
rpl::lifetime _trackLifetime;

View File

@ -1016,6 +1016,21 @@ void Panel::setupPinnedVideo() {
_call->pinVideoEndpoint(large);
}
}, _pinnedVideo->lifetime());
_pinnedVideo->controlsShown(
) | rpl::filter([=](float64 shown) {
return (_pinnedVideoControlsShown != shown);
}) | rpl::start_with_next([=](float64 shown) {
const auto hiding = (shown <= _pinnedVideoControlsShown);
_pinnedVideoControlsShown = shown;
if (_mode == PanelMode::Wide) {
if (hiding && _trackControlsLifetime) {
_trackControlsLifetime.destroy();
} else if (!hiding && !_trackControlsLifetime) {
trackControls();
}
updateButtonsGeometry();
}
}, _pinnedVideo->lifetime());
raiseControls();
}
@ -1536,6 +1551,7 @@ bool Panel::updateMode() {
void Panel::refreshControlsBackground() {
if (_mode != PanelMode::Wide) {
_trackControlsLifetime.destroy();
_controlsBackground.destroy();
} else if (_controlsBackground) {
return;
@ -1556,17 +1572,92 @@ void Panel::refreshControlsBackground() {
auto p = QPainter(_controlsBackground.data());
corners->paint(p, _controlsBackground->rect());
}, lifetime);
if (_pinnedVideoControlsShown > 0.) {
trackControls();
}
raiseControls();
}
void Panel::trackControls() {
const auto trackOne = [&](auto &&widget) {
if (widget) {
widget->events(
) | rpl::start_with_next([=](not_null<QEvent*> e) {
if (e->type() == QEvent::Enter) {
_pinnedVideo->setControlsShown(true);
} else if (e->type() == QEvent::Leave) {
_pinnedVideo->setControlsShown(false);
}
}, _trackControlsLifetime);
}
};
trackOne(_mute);
trackOne(_video);
trackOne(_screenShare);
trackOne(_settings);
trackOne(_callShare);
trackOne(_hangup);
trackOne(_controlsBackground);
}
void Panel::updateControlsGeometry() {
if (widget()->size().isEmpty() || (!_settings && !_callShare)) {
return;
}
updateButtonsGeometry();
updateMembersGeometry();
refreshTitle();
#ifdef Q_OS_MAC
const auto controlsOnTheLeft = true;
#else // Q_OS_MAC
const auto controlsOnTheLeft = _controls->geometry().center().x()
< widget()->width() / 2;
#endif // Q_OS_MAC
const auto menux = st::groupCallMenuTogglePosition.x();
const auto menuy = st::groupCallMenuTogglePosition.y();
if (controlsOnTheLeft) {
if (_menuToggle) {
_menuToggle->moveToRight(menux, menuy);
} else if (_joinAsToggle) {
_joinAsToggle->moveToRight(menux, menuy);
}
} else {
if (_menuToggle) {
_menuToggle->moveToLeft(menux, menuy);
} else if (_joinAsToggle) {
_joinAsToggle->moveToLeft(menux, menuy);
}
}
}
void Panel::updateButtonsGeometry() {
const auto toggle = [&](bool shown) {
const auto toggleOne = [&](auto &widget) {
if (widget && widget->isHidden() == shown) {
widget->setVisible(shown);
}
};
toggleOne(_mute);
toggleOne(_video);
toggleOne(_screenShare);
toggleOne(_settings);
toggleOne(_callShare);
toggleOne(_hangup);
};
if (_videoMode.current()) {
_mute->setStyle(st::callMuteButtonSmall);
toggle(_mode != PanelMode::Wide || _pinnedVideoControlsShown > 0.);
const auto buttonsTop = widget()->height()
- st::groupCallButtonBottomSkipSmall;
- st::groupCallButtonBottomSkipSmall
+ (_mode == PanelMode::Wide
? anim::interpolate(
st::groupCallButtonBottomSkipSmall,
0,
_pinnedVideoControlsShown)
: 0);
const auto addSkip = st::callMuteButtonSmall.active.outerRadius;
const auto muteSize = _mute->innerSize().width() + 2 * addSkip;
const auto skip = (_video ? 1 : 2) * st::groupCallButtonSkipSmall;
@ -1619,6 +1710,8 @@ void Panel::updateControlsGeometry() {
}
} else {
_mute->setStyle(st::callMuteButton);
toggle(true);
const auto muteTop = widget()->height()
- st::groupCallMuteBottomSkip;
const auto buttonsTop = widget()->height()
@ -1640,30 +1733,6 @@ void Panel::updateControlsGeometry() {
_hangup->setStyle(st::groupCallHangup);
_hangup->moveToRight(leftButtonLeft, buttonsTop);
}
updateMembersGeometry();
refreshTitle();
#ifdef Q_OS_MAC
const auto controlsOnTheLeft = true;
#else // Q_OS_MAC
const auto controlsOnTheLeft = _controls->geometry().center().x()
< widget()->width() / 2;
#endif // Q_OS_MAC
const auto menux = st::groupCallMenuTogglePosition.x();
const auto menuy = st::groupCallMenuTogglePosition.y();
if (controlsOnTheLeft) {
if (_menuToggle) {
_menuToggle->moveToRight(menux, menuy);
} else if (_joinAsToggle) {
_joinAsToggle->moveToRight(menux, menuy);
}
} else {
if (_menuToggle) {
_menuToggle->moveToLeft(menux, menuy);
} else if (_joinAsToggle) {
_joinAsToggle->moveToLeft(menux, menuy);
}
}
}
void Panel::updateMembersGeometry() {

View File

@ -91,10 +91,12 @@ private:
bool handleClose();
void startScheduledNow();
void trackControls();
void raiseControls();
bool updateMode();
void updateControlsGeometry();
void updateButtonsGeometry();
void updateMembersGeometry();
void refreshControlsBackground();
void showControls();
@ -143,7 +145,8 @@ private:
object_ptr<Ui::AbstractButton> _joinAsToggle = { nullptr };
object_ptr<Members> _members = { nullptr };
std::unique_ptr<LargeVideo> _pinnedVideo;
rpl::lifetime _pinnedTrackLifetime;
float64 _pinnedVideoControlsShown = 1.;
rpl::lifetime _trackControlsLifetime;
object_ptr<Ui::FlatLabel> _startsIn = { nullptr };
object_ptr<Ui::RpWidget> _countdown = { nullptr };
std::shared_ptr<Ui::GroupCallScheduledLeft> _countdownData;

View File

@ -18,6 +18,7 @@
#include "styles/style_calls.h"
#include <QtCore/QtMath>
#include <QtCore/QCoreApplication>
namespace Ui {
namespace {
@ -1038,6 +1039,10 @@ rpl::producer<Qt::MouseButton> CallMuteButton::clicks() {
});
}
rpl::producer<not_null<QEvent*>> CallMuteButton::events() const {
return _content->events();
}
QSize CallMuteButton::innerSize() const {
return innerGeometry().size();
}
@ -1071,6 +1076,10 @@ void CallMuteButton::setVisible(bool visible) {
_blobs->setVisible(visible);
}
bool CallMuteButton::isHidden() const {
return _content->isHidden();
}
void CallMuteButton::raise() {
_blobs->raise();
_content->raise();

View File

@ -62,6 +62,7 @@ public:
void setStyle(const style::CallMuteButton &st);
void setLevel(float level);
[[nodiscard]] rpl::producer<Qt::MouseButton> clicks();
[[nodiscard]] rpl::producer<not_null<QEvent*>> events() const;
[[nodiscard]] QSize innerSize() const;
[[nodiscard]] QRect innerGeometry() const;
@ -76,6 +77,7 @@ public:
void hide() {
setVisible(false);
}
[[nodiscard]] bool isHidden() const;
void raise();
void lower();