From 090d7d711203a1c7f0f6c15af66652d269a28ee7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 30 May 2021 19:14:08 +0400 Subject: [PATCH] Show video large on click. --- .../calls/group/calls_group_call.cpp | 36 +++++++++++++----- .../calls/group/calls_group_call.h | 28 +++++++++----- .../calls/group/calls_group_members.cpp | 37 ++++++++++--------- .../calls/group/calls_group_panel.cpp | 37 ++++++++++++------- .../calls/group/calls_group_viewport.cpp | 7 +--- .../calls/group/calls_group_viewport.h | 5 +-- 6 files changed, 91 insertions(+), 59 deletions(-) diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp index 4a0bc193d..d1d13dafb 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp @@ -569,7 +569,6 @@ void GroupCall::subscribeToReal(not_null real) { using Update = Data::GroupCall::ParticipantUpdate; real->participantUpdated( ) | rpl::start_with_next([=](const Update &data) { - const auto &pinned = _videoEndpointPinned.current(); const auto regularEndpoint = [&](const std::string &endpoint) -> const std::string & { return (endpoint.empty() @@ -906,8 +905,8 @@ void GroupCall::markEndpointActive(VideoEndpoint endpoint, bool active) { } addVideoOutput(i->first.id, { track->sink() }); } else { - if (_videoEndpointPinned.current() == endpoint) { - _videoEndpointPinned = VideoEndpoint(); + if (_videoEndpointLarge.current() == endpoint) { + setVideoEndpointLarge({}); } _activeVideoTracks.erase(i); } @@ -2197,8 +2196,8 @@ void GroupCall::fillActiveVideoEndpoints() { Assert(real != nullptr); const auto &participants = real->participants(); - const auto &pinned = _videoEndpointPinned.current(); - auto pinnedFound = false; + const auto &large = _videoEndpointLarge.current(); + auto largeFound = false; auto endpoints = _activeVideoTracks | ranges::views::transform([]( const auto &pair) { return pair.first; @@ -2209,8 +2208,8 @@ void GroupCall::fillActiveVideoEndpoints() { const auto feedOne = [&](VideoEndpoint endpoint) { if (endpoint.empty()) { return; - } else if (endpoint == pinned) { - pinnedFound = true; + } else if (endpoint == large) { + largeFound = true; } if (!removed.remove(endpoint)) { markEndpointActive(std::move(endpoint), true); @@ -2233,8 +2232,8 @@ void GroupCall::fillActiveVideoEndpoints() { } feedOne({ Type::Camera, _joinAs, cameraSharingEndpoint() }); feedOne({ Type::Screen, _joinAs, screenSharingEndpoint() }); - if (pinned && !pinnedFound) { - _videoEndpointPinned = VideoEndpoint(); + if (large && !largeFound) { + setVideoEndpointLarge({}); } for (const auto &endpoint : removed) { markEndpointActive(endpoint, false); @@ -2544,7 +2543,24 @@ void GroupCall::sendSelfUpdate(SendUpdateType type) { } void GroupCall::pinVideoEndpoint(VideoEndpoint endpoint) { - _videoEndpointPinned = endpoint; + _videoEndpointPinned = false; + if (endpoint) { + setVideoEndpointLarge(std::move(endpoint)); + _videoEndpointPinned = true; + } +} + +void GroupCall::showVideoEndpointLarge(VideoEndpoint endpoint) { + _videoEndpointPinned = false; + setVideoEndpointLarge(std::move(endpoint)); + _videoLargeShowTime = crl::now(); +} + +void GroupCall::setVideoEndpointLarge(VideoEndpoint endpoint) { + if (!endpoint) { + _videoEndpointPinned = false; + } + _videoEndpointLarge = endpoint; } void GroupCall::requestVideoQuality( diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.h b/Telegram/SourceFiles/calls/group/calls_group_call.h index 8da0b23fe..6d3c9eb7b 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.h +++ b/Telegram/SourceFiles/calls/group/calls_group_call.h @@ -131,11 +131,6 @@ inline bool operator>=( return !(a < b); } -struct VideoPinToggle { - VideoEndpoint endpoint; - bool pinned = false; -}; - struct VideoActiveToggle { VideoEndpoint endpoint; bool active = false; @@ -301,17 +296,27 @@ public: -> rpl::producer { return _videoStreamShownUpdates.events(); } - void pinVideoEndpoint(VideoEndpoint endpoint); void requestVideoQuality( const VideoEndpoint &endpoint, Group::VideoQuality quality); - [[nodiscard]] const VideoEndpoint &videoEndpointPinned() const { + + [[nodiscard]] bool videoEndpointPinned() const { return _videoEndpointPinned.current(); } - [[nodiscard]] auto videoEndpointPinnedValue() const - -> rpl::producer { + [[nodiscard]] rpl::producer videoEndpointPinnedValue() const { return _videoEndpointPinned.value(); } + void pinVideoEndpoint(VideoEndpoint endpoint); + + void showVideoEndpointLarge(VideoEndpoint endpoint); + [[nodiscard]] const VideoEndpoint &videoEndpointLarge() const { + return _videoEndpointLarge.current(); + } + [[nodiscard]] auto videoEndpointLargeValue() const + -> rpl::producer { + return _videoEndpointLarge.value(); + } + struct VideoTrack { std::unique_ptr track; PeerData *peer = nullptr; @@ -508,6 +513,7 @@ private: void setScreenEndpoint(std::string endpoint); void setCameraEndpoint(std::string endpoint); void addVideoOutput(const std::string &endpoint, SinkPointer sink); + void setVideoEndpointLarge(VideoEndpoint endpoint); void markEndpointActive(VideoEndpoint endpoint, bool active); void markTrackShown(const VideoEndpoint &endpoint, bool shown); @@ -584,7 +590,9 @@ private: rpl::event_stream _videoStreamShownUpdates; base::flat_map _activeVideoTracks; base::flat_set _shownVideoTracks; - rpl::variable _videoEndpointPinned; + rpl::variable _videoEndpointLarge; + rpl::variable _videoEndpointPinned = false; + crl::time _videoLargeShowTime = 0; base::flat_map _lastSpoke; rpl::event_stream _rejoinEvents; rpl::event_stream<> _allowedToSpeakNotifications; diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.cpp b/Telegram/SourceFiles/calls/group/calls_group_members.cpp index 3443d56ca..dfd384dec 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_members.cpp @@ -278,10 +278,10 @@ void Members::Controller::setupListChangeViewers() { } }, _lifetime); - _call->videoEndpointPinnedValue( - ) | rpl::start_with_next([=](const VideoEndpoint &pinned) { - if (pinned) { - hideRowsWithVideoExcept(pinned); + _call->videoEndpointLargeValue( + ) | rpl::start_with_next([=](const VideoEndpoint &large) { + if (large) { + hideRowsWithVideoExcept(large); } else { showAllHiddenRows(); } @@ -289,8 +289,8 @@ void Members::Controller::setupListChangeViewers() { _call->videoStreamShownUpdates( ) | rpl::filter([=](const VideoActiveToggle &update) { - const auto &pinned = _call->videoEndpointPinned(); - return pinned && (update.endpoint != pinned); + const auto &large = _call->videoEndpointLarge(); + return large && (update.endpoint != large); }) | rpl::start_with_next([=](const VideoActiveToggle &update) { if (update.active) { hideRowWithVideo(update.endpoint); @@ -353,10 +353,10 @@ void Members::Controller::hideRowWithVideo(const VideoEndpoint &endpoint) { void Members::Controller::showRowWithVideo(const VideoEndpoint &endpoint) { const auto peer = endpoint.peer; - const auto &pinned = _call->videoEndpointPinned(); - if (pinned) { + const auto &large = _call->videoEndpointLarge(); + if (large) { for (const auto &endpoint : _call->shownVideoTracks()) { - if (endpoint != pinned && endpoint.peer == peer) { + if (endpoint != large && endpoint.peer == peer) { // Still hidden with another video. return; } @@ -1189,11 +1189,12 @@ base::unique_qptr Members::Controller::createRowContextMenu( if (const auto real = _call->lookupReal()) { const auto participant = real->participantByPeer(participantPeer); if (participant) { - const auto &pinned = _call->videoEndpointPinned(); + const auto &large = _call->videoEndpointLarge(); + const auto pinned = _call->videoEndpointPinned(); const auto &camera = computeCameraEndpoint(participant); const auto &screen = computeScreenEndpoint(participant); if (!camera.empty()) { - if (pinned.id == camera) { + if (pinned && large.id == camera) { result->addAction( tr::lng_group_call_context_unpin_camera(tr::now), [=] { _call->pinVideoEndpoint(VideoEndpoint()); }); @@ -1203,11 +1204,12 @@ base::unique_qptr Members::Controller::createRowContextMenu( [=] { _call->pinVideoEndpoint(VideoEndpoint{ VideoEndpointType::Camera, participantPeer, - camera }); }); + camera }); + }); } } if (!screen.empty()) { - if (pinned.id == screen) { + if (pinned && large.id == screen) { result->addAction( tr::lng_group_call_context_unpin_screen(tr::now), [=] { _call->pinVideoEndpoint(VideoEndpoint()); }); @@ -1217,7 +1219,8 @@ base::unique_qptr Members::Controller::createRowContextMenu( [=] { _call->pinVideoEndpoint(VideoEndpoint{ VideoEndpointType::Screen, participantPeer, - screen }); }); + screen }); + }); } } } @@ -1637,9 +1640,9 @@ void Members::setupList() { } void Members::trackViewportGeometry() { - _call->videoEndpointPinnedValue( - ) | rpl::start_with_next([=](const VideoEndpoint &pinned) { - _viewport->showLarge(pinned); + _call->videoEndpointLargeValue( + ) | rpl::start_with_next([=](const VideoEndpoint &large) { + _viewport->showLarge(large); }, _viewport->lifetime()); const auto move = [=] { diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index d9a222b55..cb5ab161d 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -1023,12 +1023,12 @@ void Panel::setupMembers() { } }, _callLifetime); - _call->videoEndpointPinnedValue( - ) | rpl::start_with_next([=](const VideoEndpoint &pinned) { - if (pinned && mode() != PanelMode::Wide) { + _call->videoEndpointLargeValue( + ) | rpl::start_with_next([=](const VideoEndpoint &large) { + if (large && mode() != PanelMode::Wide) { enlargeVideo(); } - _viewport->showLarge(pinned); + _viewport->showLarge(large); }, _callLifetime); } @@ -1127,10 +1127,14 @@ void Panel::setupVideo(not_null viewport) { using namespace rpl::mappers; const auto row = _members->lookupRow(track.peer); Assert(row != nullptr); + auto pinned = rpl::combine( + _call->videoEndpointLargeValue(), + _call->videoEndpointPinnedValue() + ) | rpl::map(_1 == endpoint && _2); viewport->add( endpoint, VideoTileTrack{ track.track.get(), row }, - _call->videoEndpointPinnedValue() | rpl::map(_1 == endpoint)); + std::move(pinned)); }; for (const auto &[endpoint, track] : _call->activeVideoTracks()) { setupTile(endpoint, track); @@ -1154,16 +1158,21 @@ void Panel::setupVideo(not_null viewport) { }, viewport->lifetime()); viewport->pinToggled( - ) | rpl::start_with_next([=](const VideoPinToggle &value) { - _call->pinVideoEndpoint( - value.pinned ? value.endpoint : VideoEndpoint{}); + ) | rpl::start_with_next([=](bool pinned) { + _call->pinVideoEndpoint(pinned + ? _call->videoEndpointLarge() + : VideoEndpoint{}); }, viewport->lifetime()); viewport->clicks( - ) | rpl::filter([=] { - return (_mode.current() == PanelMode::Default); - }) | rpl::start_with_next([=](VideoEndpoint &&endpoint) { - _call->pinVideoEndpoint(std::move(endpoint)); + ) | rpl::start_with_next([=](VideoEndpoint &&endpoint) { + if (_call->videoEndpointLarge() == endpoint) { + _call->showVideoEndpointLarge({}); + } else if (_call->videoEndpointPinned()) { + _call->pinVideoEndpoint(std::move(endpoint)); + } else { + _call->showVideoEndpointLarge(std::move(endpoint)); + } }, viewport->lifetime()); viewport->qualityRequests( @@ -1787,8 +1796,8 @@ bool Panel::updateMode() { if (_mode.current() == mode) { return false; } - if (!wide && _call->videoEndpointPinned()) { - _call->pinVideoEndpoint({}); + if (!wide && _call->videoEndpointLarge()) { + _call->showVideoEndpointLarge({}); } refreshVideoButtons(wide); _niceTooltip.destroy(); diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp b/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp index 0c5199ce1..c0123dcd3 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp @@ -157,10 +157,7 @@ void Viewport::handleMouseRelease(QPoint position, Qt::MouseButton button) { } else if (!wide()) { _clicks.fire_copy(tile->endpoint()); } else if (pressed.element == Selection::Element::PinButton) { - _pinToggles.fire({ - .endpoint = tile->endpoint(), - .pinned = !tile->pinned(), - }); + _pinToggles.fire(!tile->pinned()); } } } @@ -540,7 +537,7 @@ rpl::producer Viewport::fullHeightValue() const { return _fullHeight.value(); } -rpl::producer Viewport::pinToggled() const { +rpl::producer Viewport::pinToggled() const { return _pinToggles.events(); } diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport.h b/Telegram/SourceFiles/calls/group/calls_group_viewport.h index d94eae43e..bcd9a8dad 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport.h +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport.h @@ -21,7 +21,6 @@ struct ChosenRenderer; namespace Calls { class GroupCall; struct VideoEndpoint; -struct VideoPinToggle; struct VideoQualityRequest; } // namespace Calls @@ -80,7 +79,7 @@ public: [[nodiscard]] bool requireARGB32() const; [[nodiscard]] int fullHeight() const; [[nodiscard]] rpl::producer fullHeightValue() const; - [[nodiscard]] rpl::producer pinToggled() const; + [[nodiscard]] rpl::producer pinToggled() const; [[nodiscard]] rpl::producer clicks() const; [[nodiscard]] rpl::producer qualityRequests() const; [[nodiscard]] rpl::producer mouseInsideValue() const; @@ -139,7 +138,7 @@ private: int _scrollTop = 0; QImage _shadow; rpl::event_stream _clicks; - rpl::event_stream _pinToggles; + rpl::event_stream _pinToggles; rpl::event_stream _qualityRequests; float64 _controlsShownRatio = 1.; VideoTile *_large = nullptr;