From 316f0537c49421443fcc5815928756df1e00cbe3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 13 May 2021 14:38:59 +0400 Subject: [PATCH] Implement video pin / controls hiding in video tiles. --- Telegram/SourceFiles/calls/calls.style | 27 +-- .../calls/group/calls_group_large_video.cpp | 185 +++++++----------- .../calls/group/calls_group_large_video.h | 13 +- .../calls/group/calls_group_members.cpp | 13 +- .../calls/group/calls_group_panel.cpp | 123 +++++++----- .../calls/group/calls_group_panel.h | 4 +- 6 files changed, 172 insertions(+), 193 deletions(-) diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index a523139951..79786255fd 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -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; diff --git a/Telegram/SourceFiles/calls/group/calls_group_large_video.cpp b/Telegram/SourceFiles/calls/group/calls_group_large_video.cpp index 9d31c6063e..8690a18797 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_large_video.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_large_video.cpp @@ -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(&_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 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::type_erased()); + return _pinButton + ? _pinButton->clicks() | rpl::map([=] { return !_pinned; }) + : rpl::never() | rpl::type_erased(); } rpl::producer 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 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(); 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.); } } diff --git a/Telegram/SourceFiles/calls/group/calls_group_large_video.h b/Telegram/SourceFiles/calls/group/calls_group_large_video.h index 4204e95003..39d3616044 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_large_video.h +++ b/Telegram/SourceFiles/calls/group/calls_group_large_video.h @@ -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 pinToggled() const; - [[nodiscard]] rpl::producer<> minimizeClicks() const; [[nodiscard]] rpl::producer 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 _minimizeButton; + std::unique_ptr _pinButton; Ui::Animations::Simple _controlsAnimation; rpl::variable _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; diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.cpp b/Telegram/SourceFiles/calls/group/calls_group_members.cpp index de9c1f862a..495400cdb8 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_members.cpp @@ -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 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, diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index ff7913aff8..34f1fb9679 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -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, 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( _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 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; diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.h b/Telegram/SourceFiles/calls/group/calls_group_panel.h index e61c5ed6c7..e6777e917c 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.h +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.h @@ -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 _pinnedVideoWrap; float64 _pinnedVideoControlsShown = 1.; std::vector _videoTiles; + LargeVideo *_trackControlsTile = nullptr; rpl::lifetime _trackControlsLifetime; + rpl::lifetime _trackControlsOverStateLifetime; object_ptr _startsIn = { nullptr }; object_ptr _countdown = { nullptr }; std::shared_ptr _countdownData;