mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-19 07:37:11 +02:00
Support enlarge / minimize of video.
This commit is contained in:
parent
64c34b7029
commit
2a5977e97f
7 changed files with 158 additions and 9 deletions
|
@ -1139,7 +1139,7 @@ groupCallNarrowNameTop: 65px;
|
|||
groupCallNarrowIconTop: 62px;
|
||||
groupCallNarrowIconLess: 5px;
|
||||
groupCallWideModeWidthMin: 550px;
|
||||
groupCallWideModeSize: size(720px, 480px);
|
||||
groupCallWideModeSize: size(960px, 580px);
|
||||
groupCallNarrowAddMemberHeight: 32px;
|
||||
groupCallNarrowOutline: 2px;
|
||||
groupCallNarrowShadowHeight: 36px;
|
||||
|
@ -1184,6 +1184,7 @@ GroupCallLargeVideo {
|
|||
statusPosition: point;
|
||||
pinPosition: point;
|
||||
iconPosition: point;
|
||||
minimizePosition: point;
|
||||
}
|
||||
|
||||
groupCallLargeVideoWide: GroupCallLargeVideo {
|
||||
|
@ -1193,6 +1194,7 @@ groupCallLargeVideoWide: GroupCallLargeVideo {
|
|||
statusPosition: point(15px, 28px);
|
||||
pinPosition: point(52px, 16px);
|
||||
iconPosition: point(14px, 16px);
|
||||
minimizePosition: point(94px, 16px);
|
||||
}
|
||||
groupCallLargeVideoNarrow: GroupCallLargeVideo {
|
||||
shadowHeight: 80px;
|
||||
|
@ -1216,3 +1218,5 @@ groupCallLargeVideoPin: CrossLineAnimation {
|
|||
endPosition: point(20px, 17px);
|
||||
stroke: 2px;
|
||||
}
|
||||
groupCallVideoEnlarge: icon {{ "calls/voice_enlarge", mediaviewPipControlsFgOver }};
|
||||
groupCallVideoMinimize: icon {{ "calls/voice_minimize", groupCallVideoSubTextFg }};
|
||||
|
|
|
@ -30,6 +30,9 @@ LargeVideo::LargeVideo(
|
|||
, _st(st)
|
||||
, _pin(st::groupCallLargeVideoPin)
|
||||
, _pinButton(&_content)
|
||||
, _minimizeButton((_st.controlsAlign == style::al_top)
|
||||
? std::make_unique<Ui::AbstractButton>(&_content)
|
||||
: nullptr)
|
||||
, _controlsShown(_st.controlsAlign == style::al_top)
|
||||
, _topControls(_st.controlsAlign == style::al_top)
|
||||
, _controlsShownRatio(_controlsShown.current() ? 1. : 0.) {
|
||||
|
@ -64,6 +67,12 @@ rpl::producer<bool> LargeVideo::pinToggled() const {
|
|||
return _pinButton.clicks() | rpl::map([=] { return !_pinned; });
|
||||
}
|
||||
|
||||
rpl::producer<> LargeVideo::minimizeClicks() const {
|
||||
return _minimizeButton
|
||||
? (_minimizeButton->clicks() | rpl::to_empty)
|
||||
: (rpl::never<rpl::empty_value>() | rpl::type_erased());
|
||||
}
|
||||
|
||||
rpl::producer<float64> LargeVideo::controlsShown() const {
|
||||
return _controlsShownRatio.value();
|
||||
}
|
||||
|
@ -86,6 +95,18 @@ void LargeVideo::setup(
|
|||
Ui::Integration::Instance().unregisterLeaveSubscription(
|
||||
&_content);
|
||||
setControlsShown(false);
|
||||
} else if (e->type() == QEvent::MouseButtonPress
|
||||
&& static_cast<QMouseEvent*>(
|
||||
e.get())->button() == Qt::LeftButton) {
|
||||
_mouseDown = true;
|
||||
} else if (e->type() == QEvent::MouseButtonRelease
|
||||
&& static_cast<QMouseEvent*>(
|
||||
e.get())->button() == Qt::LeftButton
|
||||
&& _mouseDown) {
|
||||
_mouseDown = false;
|
||||
if (!_content.isHidden()) {
|
||||
_clicks.fire({});
|
||||
}
|
||||
}
|
||||
}, _content.lifetime());
|
||||
|
||||
|
@ -118,6 +139,9 @@ void LargeVideo::setup(
|
|||
}
|
||||
_content.update();
|
||||
}, _trackLifetime);
|
||||
if (const auto size = track.track->frameSize(); !size.isEmpty()) {
|
||||
_trackSize = size;
|
||||
}
|
||||
}, _content.lifetime());
|
||||
|
||||
setupControls(std::move(pinned));
|
||||
|
@ -147,7 +171,7 @@ void LargeVideo::toggleControls() {
|
|||
callback,
|
||||
shown ? 0. : 1.,
|
||||
shown ? 1. : 0.,
|
||||
140);
|
||||
st::slideWrapDuration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,18 +190,26 @@ void LargeVideo::setupControls(rpl::producer<bool> pinned) {
|
|||
void LargeVideo::updateControlsGeometry() {
|
||||
if (_topControls) {
|
||||
const auto &pin = st::groupCallLargeVideoPin.icon;
|
||||
const auto pinWidth = pin.width();
|
||||
const auto pinRight = (_content.width() - _st.pinPosition.x());
|
||||
const auto pinLeft = pinRight - pin.width();
|
||||
const auto pinTop = _st.pinPosition.y();
|
||||
const auto &icon = st::groupCallLargeVideoCrossLine.icon;
|
||||
const auto iconLeft = _content.width()
|
||||
- _st.iconPosition.x()
|
||||
- icon.width();
|
||||
const auto skip = iconLeft - pinRight;
|
||||
const auto skip1 = iconLeft - pinRight;
|
||||
const auto &min = st::groupCallVideoMinimize;
|
||||
const auto minRight = _content.width() - _st.minimizePosition.x();
|
||||
const auto skip2 = pinLeft - minRight;
|
||||
_pinButton.setGeometry(
|
||||
pinRight - pin.width() - (skip / 2),
|
||||
pinLeft - (skip2 / 2),
|
||||
0,
|
||||
pin.width() + skip,
|
||||
pin.width() + (skip2 / 2) + (skip1 / 2),
|
||||
pinTop * 2 + pin.height());
|
||||
_minimizeButton->setGeometry(
|
||||
minRight - min.width() - (skip2 / 2),
|
||||
0,
|
||||
min.width() + skip2,
|
||||
pinTop * 2 + pin.height());
|
||||
} else {
|
||||
_pinButton.setGeometry(
|
||||
|
@ -271,11 +303,11 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
|
|||
0,
|
||||
(_topControls
|
||||
? anim::interpolate(-_st.shadowHeight, 0, shown)
|
||||
: (height - _st.shadowHeight)),
|
||||
: (height - anim::interpolate(_st.shadowHeight, 0, shown))),
|
||||
width,
|
||||
_st.shadowHeight);
|
||||
const auto shadowFill = shadowRect.intersected(clip);
|
||||
if (shadowFill.isEmpty()) {
|
||||
if (shadowFill.isEmpty() && (_topControls || shown == 0.)) {
|
||||
return;
|
||||
}
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
|
@ -287,6 +319,16 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
|
|||
(shadowFill.y() - shadowRect.y()) * factor,
|
||||
_shadow.width(),
|
||||
shadowFill.height() * factor));
|
||||
if (!_topControls && shown > 0.) {
|
||||
auto color = st::radialBg->c;
|
||||
color.setAlphaF(color.alphaF() * shown);
|
||||
p.fillRect(clip, color);
|
||||
|
||||
p.setOpacity(shown);
|
||||
st::groupCallVideoEnlarge.paintInCenter(p, _content.rect());
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
|
||||
_track.row->lazyInitialize(st::groupCallMembersListItem);
|
||||
|
||||
// Name.
|
||||
|
@ -338,6 +380,14 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
|
|||
? (_st.pinPosition.y() + shift)
|
||||
: (height - _st.pinPosition.y() - pin.height());
|
||||
_pin.paint(p, pinLeft, pinTop, _pinned ? 1. : 0.);
|
||||
|
||||
// Minimize.
|
||||
if (_topControls) {
|
||||
const auto &min = st::groupCallVideoMinimize;
|
||||
const auto minLeft = width - _st.minimizePosition.x() - min.width();
|
||||
const auto minTop = _st.minimizePosition.y() + shift;
|
||||
min.paint(p, minLeft, minTop, width);
|
||||
}
|
||||
}
|
||||
|
||||
QImage GenerateShadow(int height, int topAlpha, int bottomAlpha) {
|
||||
|
|
|
@ -64,8 +64,12 @@ public:
|
|||
void setControlsShown(bool shown);
|
||||
|
||||
[[nodiscard]] rpl::producer<bool> pinToggled() const;
|
||||
[[nodiscard]] rpl::producer<> minimizeClicks() const;
|
||||
[[nodiscard]] rpl::producer<float64> controlsShown() const;
|
||||
[[nodiscard]] rpl::producer<QSize> trackSizeValue() const;
|
||||
[[nodiscard]] rpl::producer<> clicks() const {
|
||||
return _clicks.events();
|
||||
}
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime() {
|
||||
return _content.lifetime();
|
||||
|
@ -109,11 +113,14 @@ private:
|
|||
QImage _shadow;
|
||||
Ui::CrossLineAnimation _pin;
|
||||
Ui::AbstractButton _pinButton;
|
||||
std::unique_ptr<Ui::AbstractButton> _minimizeButton;
|
||||
Ui::Animations::Simple _controlsAnimation;
|
||||
rpl::variable<bool> _controlsShown = true;
|
||||
rpl::event_stream<> _clicks;
|
||||
const bool _topControls = true;
|
||||
bool _pinned = false;
|
||||
bool _mouseInside = false;
|
||||
bool _mouseDown = false;
|
||||
bool _toggleControlsScheduled = false;
|
||||
rpl::variable<float64> _controlsShownRatio = 1.;
|
||||
rpl::variable<QSize> _trackSize;
|
||||
|
|
|
@ -1605,6 +1605,10 @@ void Members::setupAddMember(not_null<GroupCall*> call) {
|
|||
}, lifetime());
|
||||
}
|
||||
|
||||
rpl::producer<> Members::enlargeVideo() const {
|
||||
return _pinnedVideo->clicks();
|
||||
}
|
||||
|
||||
Row *Members::lookupRow(not_null<PeerData*> peer) const {
|
||||
return _listController->findRow(peer);
|
||||
}
|
||||
|
@ -1681,8 +1685,8 @@ void Members::setupPinnedVideo() {
|
|||
QSize(width, heightMax),
|
||||
Qt::KeepAspectRatio);
|
||||
const auto height = std::max(scaled.height(), heightMin);
|
||||
_pinnedVideoWrap->resize(width, height);
|
||||
_pinnedVideo->setGeometry(0, 0, width, height);
|
||||
_pinnedVideoWrap->resize(width, height);
|
||||
}, _pinnedVideo->lifetime());
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
[[nodiscard]] rpl::producer<> addMembersRequests() const {
|
||||
return _addMemberRequests.events();
|
||||
}
|
||||
[[nodiscard]] rpl::producer<> enlargeVideo() const;
|
||||
|
||||
[[nodiscard]] MembersRow *lookupRow(not_null<PeerData*> peer) const;
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <QtWidgets/QDesktopWidget>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QScreen>
|
||||
|
||||
namespace Calls::Group {
|
||||
namespace {
|
||||
|
@ -970,6 +971,79 @@ void Panel::setupMembers() {
|
|||
addMembers();
|
||||
}
|
||||
}, _callLifetime);
|
||||
|
||||
_members->enlargeVideo(
|
||||
) | rpl::start_with_next([=] {
|
||||
enlargeVideo();
|
||||
}, _callLifetime);
|
||||
}
|
||||
|
||||
void Panel::enlargeVideo() {
|
||||
_lastSmallGeometry = _window->geometry();
|
||||
|
||||
const auto available = _window->screen()->availableGeometry();
|
||||
const auto width = std::max(
|
||||
_window->width(),
|
||||
std::max(
|
||||
std::min(available.width(), st::groupCallWideModeSize.width()),
|
||||
st::groupCallWideModeWidthMin));
|
||||
const auto height = std::max(
|
||||
_window->height(),
|
||||
std::min(available.height(), st::groupCallWideModeSize.height()));
|
||||
auto geometry = QRect(
|
||||
_window->x() - (width - _window->width()) / 2,
|
||||
_window->y() - (height - _window->height()) / 2,
|
||||
width,
|
||||
height);
|
||||
if (geometry.x() < available.x()) {
|
||||
geometry.setX(std::min(available.x(), _window->x()));
|
||||
}
|
||||
if (geometry.x() + geometry.width()
|
||||
> available.x() + available.width()) {
|
||||
geometry.setX(std::max(
|
||||
available.x() + available.width(),
|
||||
_window->x() + _window->width()) - geometry.width());
|
||||
}
|
||||
if (geometry.y() < available.y()) {
|
||||
geometry.setY(std::min(available.y(), _window->y()));
|
||||
}
|
||||
if (geometry.y() + geometry.height() > available.y() + available.height()) {
|
||||
geometry.setY(std::max(
|
||||
available.y() + available.height(),
|
||||
_window->y() + _window->height()) - geometry.height());
|
||||
}
|
||||
if (_lastLargeMaximized) {
|
||||
_window->setWindowState(
|
||||
_window->windowState() | Qt::WindowMaximized);
|
||||
} else {
|
||||
_window->setGeometry((_lastLargeGeometry
|
||||
&& available.intersects(*_lastLargeGeometry))
|
||||
? *_lastLargeGeometry
|
||||
: geometry);
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::minimizeVideo() {
|
||||
if (_window->windowState() & Qt::WindowMaximized) {
|
||||
_lastLargeMaximized = true;
|
||||
_window->setWindowState(
|
||||
_window->windowState() & ~Qt::WindowMaximized);
|
||||
} else {
|
||||
_lastLargeMaximized = false;
|
||||
_lastLargeGeometry = _window->geometry();
|
||||
}
|
||||
const auto available = _window->screen()->availableGeometry();
|
||||
const auto width = st::groupCallWidth;
|
||||
const auto height = st::groupCallHeight;
|
||||
auto geometry = QRect(
|
||||
_window->x() + (_window->width() - width) / 2,
|
||||
_window->y() + (_window->height() - height) / 2,
|
||||
width,
|
||||
height);
|
||||
_window->setGeometry((_lastSmallGeometry
|
||||
&& available.intersects(*_lastSmallGeometry))
|
||||
? *_lastSmallGeometry
|
||||
: geometry);
|
||||
}
|
||||
|
||||
void Panel::raiseControls() {
|
||||
|
@ -1008,6 +1082,10 @@ void Panel::setupPinnedVideo() {
|
|||
visible,
|
||||
std::move(track),
|
||||
_call->videoEndpointPinnedValue());
|
||||
_pinnedVideo->minimizeClicks(
|
||||
) | rpl::start_with_next([=] {
|
||||
minimizeVideo();
|
||||
}, _pinnedVideo->lifetime());
|
||||
_pinnedVideo->pinToggled(
|
||||
) | rpl::start_with_next([=](bool pinned) {
|
||||
if (!pinned) {
|
||||
|
|
|
@ -93,6 +93,8 @@ private:
|
|||
void startScheduledNow();
|
||||
void trackControls();
|
||||
void raiseControls();
|
||||
void enlargeVideo();
|
||||
void minimizeVideo();
|
||||
|
||||
bool updateMode();
|
||||
void updateControlsGeometry();
|
||||
|
@ -153,6 +155,9 @@ private:
|
|||
object_ptr<Ui::FlatLabel> _startsWhen = { nullptr };
|
||||
ChooseJoinAsProcess _joinAsProcess;
|
||||
rpl::variable<bool> _videoMode;
|
||||
std::optional<QRect> _lastSmallGeometry;
|
||||
std::optional<QRect> _lastLargeGeometry;
|
||||
bool _lastLargeMaximized = false;
|
||||
|
||||
object_ptr<Ui::RpWidget> _controlsBackground = { nullptr };
|
||||
object_ptr<Ui::CallButton> _settings = { nullptr };
|
||||
|
|
Loading…
Add table
Reference in a new issue