mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-19 07:37:11 +02:00
Implement video pin / controls hiding in video tiles.
This commit is contained in:
parent
7f739065e8
commit
316f0537c4
6 changed files with 172 additions and 193 deletions
|
@ -831,7 +831,7 @@ groupCallButtonSkip: 43px;
|
|||
groupCallButtonSkipSmall: 4px;
|
||||
groupCallButtonBottomSkip: 145px;
|
||||
groupCallButtonBottomSkipSmall: 95px;
|
||||
groupCallButtonBottomSkipWide: 89px;
|
||||
groupCallButtonBottomSkipWide: 122px;
|
||||
groupCallMembersBottomSkipSmall: 72px;
|
||||
groupCallControlsBackMargin: margins(2px, 2px, 2px, 2px);
|
||||
groupCallControlsBackRadius: 12px;
|
||||
|
@ -1179,30 +1179,22 @@ groupCallLargeVideoCrossLine: CrossLineAnimation(groupCallMemberColoredCrossLine
|
|||
|
||||
GroupCallLargeVideo {
|
||||
shadowHeight: pixels;
|
||||
controlsAlign: align;
|
||||
enlargeAlign: align;
|
||||
namePosition: point;
|
||||
statusPosition: point;
|
||||
pinPosition: point;
|
||||
iconPosition: point;
|
||||
minimizePosition: point;
|
||||
}
|
||||
|
||||
groupCallLargeVideoWide: GroupCallLargeVideo {
|
||||
shadowHeight: 100px;
|
||||
controlsAlign: align(top);
|
||||
shadowHeight: 40px;
|
||||
enlargeAlign: align(topright);
|
||||
namePosition: point(15px, 8px);
|
||||
statusPosition: point(15px, 28px);
|
||||
pinPosition: point(52px, 16px);
|
||||
iconPosition: point(14px, 16px);
|
||||
minimizePosition: point(94px, 16px);
|
||||
pinPosition: point(18px, 18px);
|
||||
iconPosition: point(10px, 5px);
|
||||
}
|
||||
groupCallLargeVideoNarrow: GroupCallLargeVideo {
|
||||
shadowHeight: 80px;
|
||||
controlsAlign: align(bottom);
|
||||
namePosition: point(64px, 44px);
|
||||
statusPosition: point(64px, 25px);
|
||||
pinPosition: point(20px, 12px);
|
||||
iconPosition: point(18px, 12px);
|
||||
groupCallLargeVideoNarrow: GroupCallLargeVideo(groupCallLargeVideoWide) {
|
||||
enlargeAlign: align(center);
|
||||
pinPosition: point(-1px, -1px);
|
||||
}
|
||||
groupCallLargeVideoListItem: PeerListItem(groupCallMembersListItem) {
|
||||
nameFg: groupCallVideoTextFg;
|
||||
|
@ -1219,7 +1211,6 @@ groupCallLargeVideoPin: CrossLineAnimation {
|
|||
stroke: 2px;
|
||||
}
|
||||
groupCallVideoEnlarge: icon {{ "calls/voice_enlarge", mediaviewPipControlsFgOver }};
|
||||
groupCallVideoMinimize: icon {{ "calls/voice_minimize", groupCallVideoSubTextFg }};
|
||||
|
||||
groupCallVideoSmallSkip: 4px;
|
||||
groupCallVideoLargeSkip: 6px;
|
||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "media/view/media_view_pip.h"
|
||||
#include "webrtc/webrtc_video_track.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/abstract_button.h"
|
||||
#include "styles/style_calls.h"
|
||||
|
||||
namespace Calls::Group {
|
||||
|
@ -30,12 +31,11 @@ LargeVideo::LargeVideo(
|
|||
: _content(parent, [=](QRect clip) { paint(clip); })
|
||||
, _st(st)
|
||||
, _pin(st::groupCallLargeVideoPin)
|
||||
, _pinButton(&_content)
|
||||
, _minimizeButton((_st.controlsAlign == style::al_top)
|
||||
, _pinButton((_st.pinPosition.x() >= 0)
|
||||
? std::make_unique<Ui::AbstractButton>(&_content)
|
||||
: nullptr)
|
||||
, _controlsShown(_st.controlsAlign == style::al_top)
|
||||
, _topControls(_st.controlsAlign == style::al_top)
|
||||
, _controlsShown(_st.enlargeAlign != style::al_center)
|
||||
, _hasEnlarge(_st.enlargeAlign == style::al_center)
|
||||
, _controlsShownRatio(_controlsShown.current() ? 1. : 0.) {
|
||||
_content.setVisible(visible);
|
||||
setup(std::move(track), std::move(pinned));
|
||||
|
@ -74,13 +74,9 @@ void LargeVideo::setControlsShown(bool shown) {
|
|||
}
|
||||
|
||||
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());
|
||||
return _pinButton
|
||||
? _pinButton->clicks() | rpl::map([=] { return !_pinned; })
|
||||
: rpl::never<bool>() | rpl::type_erased();
|
||||
}
|
||||
|
||||
rpl::producer<float64> LargeVideo::controlsShown() const {
|
||||
|
@ -140,7 +136,7 @@ void LargeVideo::setup(
|
|||
) | rpl::map([=](bool shown, LargeVideoTrack track) {
|
||||
if (!shown) {
|
||||
_controlsAnimation.stop();
|
||||
if (!_topControls) {
|
||||
if (_hasEnlarge) {
|
||||
_controlsShown = _mouseInside = false;
|
||||
}
|
||||
_controlsShownRatio = _controlsShown.current() ? 1. : 0.;
|
||||
|
@ -174,9 +170,18 @@ void LargeVideo::setup(
|
|||
setupControls(std::move(pinned));
|
||||
}
|
||||
|
||||
void LargeVideo::toggleControlsHidingEnabled(bool enabled) {
|
||||
if (_controlsHidingEnabled == enabled) {
|
||||
return;
|
||||
}
|
||||
_controlsHidingEnabled = enabled;
|
||||
toggleControls();
|
||||
}
|
||||
|
||||
void LargeVideo::toggleControls() {
|
||||
_toggleControlsScheduled = false;
|
||||
const auto shown = _mouseInside;
|
||||
const auto shown = _mouseInside
|
||||
|| (!_hasEnlarge && !_controlsHidingEnabled);
|
||||
if (_controlsShown.current() == shown) {
|
||||
return;
|
||||
}
|
||||
|
@ -184,11 +189,7 @@ void LargeVideo::toggleControls() {
|
|||
const auto callback = [=] {
|
||||
_controlsShownRatio = _controlsAnimation.value(
|
||||
_controlsShown.current() ? 1. : 0.);
|
||||
if (_topControls) {
|
||||
_content.update(0, 0, _content.width(), _st.shadowHeight);
|
||||
} else {
|
||||
_content.update();
|
||||
}
|
||||
_content.update();
|
||||
updateControlsGeometry();
|
||||
};
|
||||
if (_content.isHidden()) {
|
||||
|
@ -215,45 +216,30 @@ void LargeVideo::setupControls(rpl::producer<bool> pinned) {
|
|||
}
|
||||
|
||||
void LargeVideo::updateControlsGeometry() {
|
||||
if (_topControls) {
|
||||
if (_pinButton) {
|
||||
const auto &pin = st::groupCallLargeVideoPin.icon;
|
||||
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 skip1 = iconLeft - pinRight;
|
||||
const auto &min = st::groupCallVideoMinimize;
|
||||
const auto minRight = _content.width() - _st.minimizePosition.x();
|
||||
const auto skip2 = pinLeft - minRight;
|
||||
_pinButton.setGeometry(
|
||||
pinLeft - (skip2 / 2),
|
||||
const auto buttonWidth = pin.width() + 2 * _st.pinPosition.x();
|
||||
const auto buttonHeight = pin.height() + 2 * _st.pinPosition.y();
|
||||
_pinButton->setGeometry(
|
||||
_content.width() - buttonWidth,
|
||||
0,
|
||||
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(
|
||||
0,
|
||||
_content.height() - _st.namePosition.y(),
|
||||
_st.namePosition.x(),
|
||||
_st.namePosition.y());
|
||||
buttonWidth,
|
||||
buttonHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void LargeVideo::paint(QRect clip) {
|
||||
auto p = Painter(&_content);
|
||||
const auto fill = [&](QRect rect) {
|
||||
if (rect.intersects(clip)) {
|
||||
p.fillRect(rect.intersected(clip), st::groupCallMembersBg);
|
||||
}
|
||||
};
|
||||
const auto [image, rotation] = _track
|
||||
? _track.track->frameOriginalWithRotation()
|
||||
: std::pair<QImage, int>();
|
||||
if (image.isNull()) {
|
||||
p.fillRect(clip, Qt::black);
|
||||
fill(clip);
|
||||
return;
|
||||
}
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
|
@ -282,11 +268,6 @@ void LargeVideo::paint(QRect clip) {
|
|||
}
|
||||
_track.track->markFrameShown();
|
||||
|
||||
const auto fill = [&](QRect rect) {
|
||||
if (rect.intersects(clip)) {
|
||||
p.fillRect(rect.intersected(clip), Qt::black);
|
||||
}
|
||||
};
|
||||
if (left > 0) {
|
||||
fill({ 0, 0, left, size.height() });
|
||||
}
|
||||
|
@ -306,35 +287,29 @@ void LargeVideo::paint(QRect clip) {
|
|||
}
|
||||
|
||||
void LargeVideo::paintControls(Painter &p, QRect clip) {
|
||||
const auto shown = _controlsShownRatio.current();
|
||||
if (shown == 0. && _topControls) {
|
||||
const auto ratio = _controlsShownRatio.current();
|
||||
const auto shown = _hasEnlarge ? 1. : ratio;
|
||||
const auto enlarge = _hasEnlarge ? ratio : 0.;
|
||||
if (shown == 0.) {
|
||||
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;
|
||||
const auto fullShift = _st.namePosition.y() + st::normalFont->height;
|
||||
const auto shift = anim::interpolate(fullShift, 0, shown);
|
||||
|
||||
// Shadow.
|
||||
if (_shadow.isNull()) {
|
||||
if (_topControls) {
|
||||
_shadow = GenerateShadow(_st.shadowHeight, kShadowMaxAlpha, 0);
|
||||
} else {
|
||||
_shadow = GenerateShadow(_st.shadowHeight, 0, kShadowMaxAlpha);
|
||||
}
|
||||
_shadow = GenerateShadow(_st.shadowHeight, 0, kShadowMaxAlpha);
|
||||
}
|
||||
const auto shadowRect = QRect(
|
||||
0,
|
||||
(_topControls
|
||||
? anim::interpolate(-_st.shadowHeight, 0, shown)
|
||||
: (height - anim::interpolate(_st.shadowHeight, 0, shown))),
|
||||
(height - anim::interpolate(0, _st.shadowHeight, shown)),
|
||||
width,
|
||||
_st.shadowHeight);
|
||||
const auto shadowFill = shadowRect.intersected(clip);
|
||||
if (shadowFill.isEmpty() && (_topControls || shown == 0.)) {
|
||||
if (shadowFill.isEmpty() && enlarge == 0. && !_pinButton) {
|
||||
return;
|
||||
}
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
|
@ -346,74 +321,52 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
|
|||
(shadowFill.y() - shadowRect.y()) * factor,
|
||||
_shadow.width(),
|
||||
shadowFill.height() * factor));
|
||||
if (!_topControls && shown > 0.) {
|
||||
if (enlarge > 0.) {
|
||||
auto color = st::radialBg->c;
|
||||
color.setAlphaF(color.alphaF() * shown);
|
||||
color.setAlphaF(color.alphaF() * enlarge);
|
||||
p.fillRect(clip, color);
|
||||
|
||||
p.setOpacity(shown);
|
||||
p.setOpacity(enlarge);
|
||||
st::groupCallVideoEnlarge.paintInCenter(p, _content.rect());
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
|
||||
_track.row->lazyInitialize(st::groupCallMembersListItem);
|
||||
|
||||
// Name.
|
||||
p.setPen(_topControls
|
||||
? st::groupCallVideoTextFg
|
||||
: st::groupCallVideoSubTextFg);
|
||||
const auto hasWidth = width
|
||||
- (_topControls ? _st.pinPosition.x() : _st.iconPosition.x())
|
||||
- _st.namePosition.x();
|
||||
const auto nameLeft = _st.namePosition.x();
|
||||
const auto nameTop = _topControls
|
||||
? (_st.namePosition.y() + shift)
|
||||
: (height - _st.namePosition.y());
|
||||
_track.row->name().drawLeftElided(p, nameLeft, nameTop, hasWidth, width);
|
||||
|
||||
// Status.
|
||||
p.setPen(st::groupCallVideoSubTextFg);
|
||||
const auto statusLeft = _st.statusPosition.x();
|
||||
const auto statusTop = _topControls
|
||||
? (_st.statusPosition.y() + shift)
|
||||
: (height - _st.statusPosition.y());
|
||||
_track.row->paintComplexStatusText(
|
||||
p,
|
||||
st::groupCallLargeVideoListItem,
|
||||
statusLeft,
|
||||
statusTop,
|
||||
hasWidth,
|
||||
width,
|
||||
false,
|
||||
MembersRowStyle::LargeVideo);
|
||||
|
||||
// Mute.
|
||||
const auto &icon = st::groupCallLargeVideoCrossLine.icon;
|
||||
const auto iconLeft = width - _st.iconPosition.x() - icon.width();
|
||||
const auto iconTop = _topControls
|
||||
? (_st.iconPosition.y() + shift)
|
||||
: (height - _st.iconPosition.y() - icon.height());
|
||||
const auto iconTop = (height
|
||||
- _st.iconPosition.y()
|
||||
- icon.height()
|
||||
+ shift);
|
||||
_track.row->paintMuteIcon(
|
||||
p,
|
||||
{ iconLeft, iconTop, icon.width(), icon.height() },
|
||||
MembersRowStyle::LargeVideo);
|
||||
|
||||
// Pin.
|
||||
const auto &pin = st::groupCallLargeVideoPin.icon;
|
||||
const auto pinLeft = _topControls
|
||||
? (width - _st.pinPosition.x() - pin.width())
|
||||
: _st.pinPosition.x();
|
||||
const auto pinTop = _topControls
|
||||
? (_st.pinPosition.y() + shift)
|
||||
: (height - _st.pinPosition.y() - pin.height());
|
||||
_pin.paint(p, pinLeft, pinTop, _pinned ? 1. : 0.);
|
||||
// Name.
|
||||
p.setPen(st::groupCallVideoTextFg);
|
||||
const auto hasWidth = width
|
||||
- _st.iconPosition.x() - icon.width()
|
||||
- _st.namePosition.x();
|
||||
const auto nameLeft = _st.namePosition.x();
|
||||
const auto nameTop = (height
|
||||
- _st.namePosition.y()
|
||||
- st::semiboldFont->height
|
||||
+ shift);
|
||||
_track.row->name().drawLeftElided(p, nameLeft, nameTop, hasWidth, width);
|
||||
|
||||
// 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);
|
||||
// Pin.
|
||||
if (_st.pinPosition.x() >= 0) {
|
||||
const auto &pin = st::groupCallLargeVideoPin.icon;
|
||||
const auto pinLeft = (width - _st.pinPosition.x() - pin.width());
|
||||
const auto pinShift = anim::interpolate(
|
||||
_st.pinPosition.y() + pin.height(),
|
||||
0,
|
||||
shown);
|
||||
const auto pinTop = (_st.pinPosition.y() - pinShift);
|
||||
_pin.paint(p, pinLeft, pinTop, _pinned ? 1. : 0.);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/abstract_button.h"
|
||||
#include "ui/effects/cross_line.h"
|
||||
#include "ui/effects/animations.h"
|
||||
|
||||
|
@ -24,6 +23,10 @@ namespace Webrtc {
|
|||
class VideoTrack;
|
||||
} // namespace Webrtc
|
||||
|
||||
namespace Ui {
|
||||
class AbstractButton;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Calls::Group {
|
||||
|
||||
class MembersRow;
|
||||
|
@ -63,9 +66,9 @@ public:
|
|||
void setVisible(bool visible);
|
||||
void setGeometry(int x, int y, int width, int height);
|
||||
void setControlsShown(bool shown);
|
||||
void toggleControlsHidingEnabled(bool enabled);
|
||||
|
||||
[[nodiscard]] rpl::producer<bool> pinToggled() const;
|
||||
[[nodiscard]] rpl::producer<> minimizeClicks() const;
|
||||
[[nodiscard]] rpl::producer<float64> controlsShown() const;
|
||||
[[nodiscard]] rpl::producer<> clicks() const {
|
||||
return _clicks.events();
|
||||
|
@ -116,13 +119,13 @@ private:
|
|||
LargeVideoTrack _track;
|
||||
QImage _shadow;
|
||||
Ui::CrossLineAnimation _pin;
|
||||
Ui::AbstractButton _pinButton;
|
||||
std::unique_ptr<Ui::AbstractButton> _minimizeButton;
|
||||
std::unique_ptr<Ui::AbstractButton> _pinButton;
|
||||
Ui::Animations::Simple _controlsAnimation;
|
||||
rpl::variable<bool> _controlsShown = true;
|
||||
rpl::event_stream<> _clicks;
|
||||
const bool _topControls = true;
|
||||
const bool _hasEnlarge = true;
|
||||
bool _pinned = false;
|
||||
bool _controlsHidingEnabled = false;
|
||||
bool _mouseInside = false;
|
||||
bool _mouseDown = false;
|
||||
bool _toggleControlsScheduled = false;
|
||||
|
|
|
@ -1686,14 +1686,18 @@ void Members::refreshTilesGeometry() {
|
|||
_pinnedVideoWrap->resize(width, height);
|
||||
return;
|
||||
}
|
||||
const auto min = (st::groupCallWidth
|
||||
- st::groupCallMembersMargin.left()
|
||||
- st::groupCallMembersMargin.right()
|
||||
- st::groupCallVideoSmallSkip) / 2;
|
||||
const auto square = (width - st::groupCallVideoSmallSkip) / 2;
|
||||
const auto skip = (width - 2 * square);
|
||||
const auto put = [&](not_null<LargeVideo*> video, int column, int row) {
|
||||
video->setGeometry(
|
||||
(column == 2) ? 0 : column ? (width - square) : 0,
|
||||
row * (square + skip),
|
||||
row * (min + skip),
|
||||
(column == 2) ? width : square,
|
||||
square);
|
||||
min);
|
||||
};
|
||||
const auto rows = (sizes.size() + 1) / 2;
|
||||
if (sizes.size() == 3) {
|
||||
|
@ -1713,7 +1717,7 @@ void Members::refreshTilesGeometry() {
|
|||
}
|
||||
}
|
||||
}
|
||||
_pinnedVideoWrap->resize(width, rows * (square + skip) - skip);
|
||||
_pinnedVideoWrap->resize(width, rows * (min + skip) - skip);
|
||||
}
|
||||
|
||||
void Members::setupPinnedVideo() {
|
||||
|
@ -1746,6 +1750,9 @@ void Members::setupPinnedVideo() {
|
|||
refreshTilesGeometry();
|
||||
}, video->lifetime());
|
||||
|
||||
video->clicks(
|
||||
) | rpl::start_to_stream(_enlargeVideoClicks, video->lifetime());
|
||||
|
||||
return VideoTile{
|
||||
.video = std::move(video),
|
||||
.endpoint = endpoint,
|
||||
|
|
|
@ -435,6 +435,7 @@ Panel::~Panel() {
|
|||
if (_menu) {
|
||||
_menu.destroy();
|
||||
}
|
||||
_videoTiles.clear();
|
||||
}
|
||||
|
||||
void Panel::setupRealCallViewers() {
|
||||
|
@ -983,10 +984,12 @@ void Panel::setupMembers() {
|
|||
}, _callLifetime);
|
||||
|
||||
_call->videoEndpointPinnedValue(
|
||||
) | rpl::filter([=](const VideoEndpoint &pinned) {
|
||||
return pinned && (_mode == PanelMode::Default);
|
||||
}) | rpl::start_with_next([=] {
|
||||
enlargeVideo();
|
||||
) | rpl::start_with_next([=](const VideoEndpoint &pinned) {
|
||||
if (_mode == PanelMode::Wide) {
|
||||
refreshTilesGeometry();
|
||||
} else if (pinned) {
|
||||
enlargeVideo();
|
||||
}
|
||||
}, _callLifetime);
|
||||
}
|
||||
|
||||
|
@ -1082,6 +1085,7 @@ void Panel::refreshTilesGeometry() {
|
|||
if (_videoTiles.empty()
|
||||
|| outer.isEmpty()
|
||||
|| _mode == PanelMode::Default) {
|
||||
trackControls(nullptr);
|
||||
return;
|
||||
}
|
||||
struct Geometry {
|
||||
|
@ -1089,23 +1093,30 @@ void Panel::refreshTilesGeometry() {
|
|||
QRect columns;
|
||||
QRect rows;
|
||||
};
|
||||
const auto &pinned = _call->videoEndpointPinned();
|
||||
auto sizes = base::flat_map<not_null<LargeVideo*>, Geometry>();
|
||||
sizes.reserve(_videoTiles.size());
|
||||
for (const auto &tile : _videoTiles) {
|
||||
const auto video = tile.video.get();
|
||||
const auto size = video->trackSize();
|
||||
const auto size = (pinned && tile.endpoint != pinned)
|
||||
? QSize()
|
||||
: video->trackSize();
|
||||
if (size.isEmpty()) {
|
||||
video->toggleControlsHidingEnabled(false);
|
||||
video->setGeometry(0, 0, outer.width(), 0);
|
||||
} else {
|
||||
sizes.emplace(video, Geometry{ size });
|
||||
}
|
||||
}
|
||||
if (sizes.empty()) {
|
||||
return;
|
||||
} else if (sizes.size() == 1) {
|
||||
if (sizes.size() == 1) {
|
||||
trackControls(sizes.front().first);
|
||||
sizes.front().first->toggleControlsHidingEnabled(true);
|
||||
sizes.front().first->setGeometry(0, 0, outer.width(), outer.height());
|
||||
return;
|
||||
}
|
||||
if (sizes.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto columnsBlack = uint64();
|
||||
auto rowsBlack = uint64();
|
||||
|
@ -1180,6 +1191,7 @@ void Panel::refreshTilesGeometry() {
|
|||
const auto &rect = (columnsBlack < rowsBlack)
|
||||
? geometry.columns
|
||||
: geometry.rows;
|
||||
video->toggleControlsHidingEnabled(false);
|
||||
video->setGeometry(rect.x(), rect.y(), rect.width(), rect.height());
|
||||
}
|
||||
}
|
||||
|
@ -1195,7 +1207,7 @@ void Panel::setupPinnedVideo() {
|
|||
Assert(row != nullptr);
|
||||
auto video = std::make_unique<LargeVideo>(
|
||||
_pinnedVideoWrap.get(),
|
||||
st::groupCallLargeVideoNarrow,
|
||||
st::groupCallLargeVideoWide,
|
||||
(_mode == PanelMode::Wide),
|
||||
rpl::single(LargeVideoTrack{ track.track.get(), row }),
|
||||
_call->videoEndpointPinnedValue() | rpl::map(_1 == endpoint));
|
||||
|
@ -1210,31 +1222,16 @@ void Panel::setupPinnedVideo() {
|
|||
_call->requestVideoQuality(endpoint, quality);
|
||||
}, video->lifetime());
|
||||
|
||||
video->minimizeClicks(
|
||||
) | rpl::start_with_next([=] {
|
||||
minimizeVideo();
|
||||
}, video->lifetime());
|
||||
|
||||
video->trackSizeValue(
|
||||
) | rpl::start_with_next([=] {
|
||||
refreshTilesGeometry();
|
||||
}, video->lifetime());
|
||||
|
||||
video->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();
|
||||
video->lifetime().add([=, video = video.get()] {
|
||||
if (_trackControlsTile == video) {
|
||||
trackControls(nullptr);
|
||||
}
|
||||
}, video->lifetime());
|
||||
});
|
||||
|
||||
return VideoTile{
|
||||
.video = std::move(video),
|
||||
|
@ -1806,32 +1803,59 @@ void Panel::refreshControlsBackground() {
|
|||
corners->paint(p, _controlsBackground->rect());
|
||||
}, lifetime);
|
||||
|
||||
if (_pinnedVideoControlsShown > 0.) {
|
||||
trackControls();
|
||||
}
|
||||
raiseControls();
|
||||
}
|
||||
|
||||
void Panel::trackControls() {
|
||||
const auto trackOne = [&](auto &&widget) {
|
||||
void Panel::trackControls(LargeVideo *video) {
|
||||
if (_trackControlsTile == video) {
|
||||
return;
|
||||
}
|
||||
_trackControlsTile = video;
|
||||
if (!video) {
|
||||
_trackControlsLifetime.destroy();
|
||||
_trackControlsOverStateLifetime.destroy();
|
||||
if (_pinnedVideoControlsShown != 1.) {
|
||||
_pinnedVideoControlsShown = 1.;
|
||||
updateButtonsGeometry();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
if (e->type() == QEvent::Enter) {
|
||||
video->setControlsShown(true);
|
||||
} else if (e->type() == QEvent::Leave) {
|
||||
video->setControlsShown(false);
|
||||
}
|
||||
}, _trackControlsOverStateLifetime);
|
||||
}
|
||||
};
|
||||
trackOne(_mute);
|
||||
trackOne(_video);
|
||||
trackOne(_screenShare);
|
||||
trackOne(_settings);
|
||||
trackOne(_callShare);
|
||||
trackOne(_hangup);
|
||||
trackOne(_controlsBackground);
|
||||
const auto trackOverState = [=] {
|
||||
trackOne(_mute);
|
||||
trackOne(_video);
|
||||
trackOne(_screenShare);
|
||||
trackOne(_settings);
|
||||
trackOne(_callShare);
|
||||
trackOne(_hangup);
|
||||
trackOne(_controlsBackground);
|
||||
};
|
||||
|
||||
video->controlsShown(
|
||||
) | rpl::filter([=](float64 shown) {
|
||||
return (_pinnedVideoControlsShown != shown);
|
||||
}) | rpl::start_with_next([=](float64 shown) {
|
||||
const auto hiding = (shown <= _pinnedVideoControlsShown);
|
||||
_pinnedVideoControlsShown = shown;
|
||||
if (hiding && _trackControlsLifetime) {
|
||||
_trackControlsOverStateLifetime.destroy();
|
||||
} else if (!hiding && !_trackControlsOverStateLifetime) {
|
||||
trackOverState();
|
||||
}
|
||||
updateButtonsGeometry();
|
||||
}, _trackControlsLifetime);
|
||||
}
|
||||
|
||||
void Panel::updateControlsGeometry() {
|
||||
|
@ -1884,13 +1908,12 @@ void Panel::updateButtonsGeometry() {
|
|||
toggle(_mode != PanelMode::Wide || _pinnedVideoControlsShown > 0.);
|
||||
|
||||
const auto buttonsTop = widget()->height()
|
||||
- st::groupCallButtonBottomSkipSmall
|
||||
+ (_mode == PanelMode::Wide
|
||||
- (_mode == PanelMode::Wide
|
||||
? anim::interpolate(
|
||||
st::groupCallButtonBottomSkipSmall,
|
||||
0,
|
||||
st::groupCallButtonBottomSkipWide,
|
||||
_pinnedVideoControlsShown)
|
||||
: 0);
|
||||
: st::groupCallButtonBottomSkipSmall);
|
||||
const auto addSkip = st::callMuteButtonSmall.active.outerRadius;
|
||||
const auto muteSize = _mute->innerSize().width() + 2 * addSkip;
|
||||
const auto skip = (_video ? 1 : 2) * st::groupCallButtonSkipSmall;
|
||||
|
|
|
@ -92,7 +92,7 @@ private:
|
|||
|
||||
bool handleClose();
|
||||
void startScheduledNow();
|
||||
void trackControls();
|
||||
void trackControls(LargeVideo *video);
|
||||
void raiseControls();
|
||||
void enlargeVideo();
|
||||
void minimizeVideo();
|
||||
|
@ -151,7 +151,9 @@ private:
|
|||
std::unique_ptr<Ui::RpWidget> _pinnedVideoWrap;
|
||||
float64 _pinnedVideoControlsShown = 1.;
|
||||
std::vector<VideoTile> _videoTiles;
|
||||
LargeVideo *_trackControlsTile = nullptr;
|
||||
rpl::lifetime _trackControlsLifetime;
|
||||
rpl::lifetime _trackControlsOverStateLifetime;
|
||||
object_ptr<Ui::FlatLabel> _startsIn = { nullptr };
|
||||
object_ptr<Ui::RpWidget> _countdown = { nullptr };
|
||||
std::shared_ptr<Ui::GroupCallScheduledLeft> _countdownData;
|
||||
|
|
Loading…
Add table
Reference in a new issue