From 361e3565d409d03dfc73e189315d50ce48d7c44a Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 9 Mar 2021 11:24:29 +0400 Subject: [PATCH] Add raised hand display in participants list. --- .../icons/calls/group_calls_muted.png | Bin 718 -> 0 bytes .../icons/calls/group_calls_muted@2x.png | Bin 1288 -> 0 bytes .../icons/calls/group_calls_muted@3x.png | Bin 1894 -> 0 bytes .../icons/calls/group_calls_raised_hand.png | Bin 0 -> 1008 bytes .../calls/group_calls_raised_hand@2x.png | Bin 0 -> 1712 bytes .../calls/group_calls_raised_hand@3x.png | Bin 0 -> 2725 bytes Telegram/Resources/langs/lang.strings | 1 + Telegram/SourceFiles/calls/calls.style | 1 + .../SourceFiles/calls/calls_group_members.cpp | 92 +++++++++++------- Telegram/SourceFiles/data/data_group_call.cpp | 3 + Telegram/SourceFiles/data/data_group_call.h | 1 + 11 files changed, 63 insertions(+), 35 deletions(-) delete mode 100644 Telegram/Resources/icons/calls/group_calls_muted.png delete mode 100644 Telegram/Resources/icons/calls/group_calls_muted@2x.png delete mode 100644 Telegram/Resources/icons/calls/group_calls_muted@3x.png create mode 100644 Telegram/Resources/icons/calls/group_calls_raised_hand.png create mode 100644 Telegram/Resources/icons/calls/group_calls_raised_hand@2x.png create mode 100644 Telegram/Resources/icons/calls/group_calls_raised_hand@3x.png diff --git a/Telegram/Resources/icons/calls/group_calls_muted.png b/Telegram/Resources/icons/calls/group_calls_muted.png deleted file mode 100644 index 1c63be9cde9c27d2acd85f2634fdf5f449de9928..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 718 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEa{HEjtmSN`?>!lvI6-QsS%!O zzP=1vKsE;hV|yk83y{SK#8N=az`(SC2`(bBfEmFCNgn(gJ{_pU(bL5-#DjNhnC4fFRAlj4v+BuV|Q>aIyYxJmx>)f%KWpZ(UlX|D)6nYc+t3iS@(6=MUti0jr}ljYU^>&f3pv~Eel>6qz}vm z=H55KMd{;AhVr_dF+X;GsM;%|Ft6)lh0h|juT^s$`;RNn^;7Q?H1oamO87v;>Z=wz z?!P}B{<-RnhFEu?hRCGNBCYMlR=&(S->R6FU-s-i+T^+HvS#by#D_ZP7pa|kuOifW zqKtLsJO;P@_x<F|}B2vLesYbD!?*S$1Bj?rDtP_4Mc4 x+ux~Q)-jsuHFG9!?*9@d=NA4`>;JF*!Mj)Cxv&0u0ZUM#@^tlcS?83{1OUj@Hsb&Q diff --git a/Telegram/Resources/icons/calls/group_calls_muted@2x.png b/Telegram/Resources/icons/calls/group_calls_muted@2x.png deleted file mode 100644 index 231ce293f003a034690347989e5fc84064bfdcf0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1288 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 literal 0 HcmV?d00001 diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 38d08d5d38..4ea4e79313 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1923,6 +1923,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_call_title" = "Voice Chat"; "lng_group_call_active" = "speaking"; "lng_group_call_inactive" = "listening"; +"lng_group_call_raised_hand_status" = "wants to speak"; "lng_group_call_settings" = "Settings"; "lng_group_call_unmute" = "Unmute"; "lng_group_call_unmute_sub" = "or hold spacebar to talk"; diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index 0c20a1913f..931b47c979 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -588,6 +588,7 @@ groupCallMemberColoredCrossLine: CrossLineAnimation(groupCallMemberInactiveCross } groupCallMemberInvited: icon {{ "calls/group_calls_invited", groupCallMemberInactiveIcon }}; groupCallMemberInvitedPosition: point(2px, 12px); +groupCallMemberRaisedHand: icon {{ "calls/group_calls_raised_hand", groupCallMemberInactiveStatus }}; groupCallSettings: CallButton(callMicrophoneMute) { button: IconButton(callButton) { diff --git a/Telegram/SourceFiles/calls/calls_group_members.cpp b/Telegram/SourceFiles/calls/calls_group_members.cpp index 9298f5e330..2e8edb8a7a 100644 --- a/Telegram/SourceFiles/calls/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/calls_group_members.cpp @@ -79,16 +79,20 @@ class Row; class RowDelegate { public: + struct IconState { + float64 speaking = 0.; + float64 active = 0.; + float64 muted = 0.; + bool mutedByMe = false; + bool raisedHand = false; + }; virtual bool rowIsMe(not_null participantPeer) = 0; virtual bool rowCanMuteMembers() = 0; virtual void rowUpdateRow(not_null row) = 0; virtual void rowPaintIcon( Painter &p, QRect rect, - float64 speaking, - float64 active, - float64 muted, - bool mutedByMe) = 0; + IconState state) = 0; }; class Row final : public PeerListRow { @@ -101,6 +105,7 @@ public: Active, Inactive, Muted, + RaisedHand, MutedByMe, Invited, }; @@ -281,10 +286,7 @@ public: void rowPaintIcon( Painter &p, QRect rect, - float64 speaking, - float64 active, - float64 muted, - bool mutedByMe) override; + IconState state) override; private: [[nodiscard]] std::unique_ptr createRowForMe(); @@ -383,14 +385,19 @@ void Row::updateState(const Data::GroupCall::Participant *participant) { setSounding(participant->sounding && participant->ssrc != 0); setSpeaking(participant->speaking && participant->ssrc != 0); } else if (participant->canSelfUnmute) { - setState(participant->mutedByMe ? State::MutedByMe : State::Inactive); + setState(participant->mutedByMe + ? State::MutedByMe + : State::Inactive); setSounding(false); setSpeaking(false); } else { - setState(State::Muted); + setState(participant->raisedHandRating + ? State::RaisedHand + : State::Muted); setSounding(false); setSpeaking(false); } + refreshStatus(); } void Row::setSpeaking(bool speaking) { @@ -406,7 +413,8 @@ void Row::setSpeaking(bool speaking) { if (!_speaking || (_state == State::MutedByMe) - || (_state == State::Muted)) { + || (_state == State::Muted) + || (_state == State::RaisedHand)) { _statusIcon = nullptr; } else if (!_statusIcon) { _statusIcon = std::make_unique( @@ -456,7 +464,6 @@ void Row::setSounding(bool sounding) { _blobsAnimation->lastTime = crl::now(); updateLevel(GroupCall::kSpeakLevelThreshold); } - refreshStatus(); } void Row::setState(State state) { @@ -464,10 +471,12 @@ void Row::setState(State state) { return; } const auto wasActive = (_state == State::Active); - const auto wasMuted = (_state == State::Muted); + const auto wasMuted = (_state == State::Muted) + || (_state == State::RaisedHand); _state = state; const auto nowActive = (_state == State::Active); - const auto nowMuted = (_state == State::Muted); + const auto nowMuted = (_state == State::Muted) + || (_state == State::RaisedHand); if (nowActive != wasActive) { _activeAnimation.start( [=] { _delegate->rowUpdateRow(this); }, @@ -679,7 +688,9 @@ void Row::paintStatusText( int outerWidth, bool selected) { const auto &font = st::normalFont; - const auto about = (_state == State::Inactive || _state == State::Muted) + const auto about = (_state == State::Inactive + || _state == State::Muted + || _state == State::RaisedHand) ? _aboutText : QString(); if (_aboutText.isEmpty() @@ -752,12 +763,17 @@ void Row::paintAction( } } const auto speaking = _speakingAnimation.value(_speaking ? 1. : 0.); - const auto active = _activeAnimation.value( - (_state == State::Active) ? 1. : 0.); + const auto active = _activeAnimation.value((_state == State::Active) ? 1. : 0.); const auto muted = _mutedAnimation.value( - (_state == State::Muted) ? 1. : 0.); + (_state == State::Muted || _state == State::RaisedHand) ? 1. : 0.); const auto mutedByMe = (_state == State::MutedByMe); - _delegate->rowPaintIcon(p, iconRect, speaking, active, muted, mutedByMe); + _delegate->rowPaintIcon(p, iconRect, { + .speaking = speaking, + .active = active, + .muted = muted, + .mutedByMe = (_state == State::MutedByMe), + .raisedHand = (_state == State::RaisedHand), + }); } void Row::refreshStatus() { @@ -766,6 +782,8 @@ void Row::refreshStatus() { ? u"%1% %2"_q .arg(std::round(_volume / 100.)) .arg(tr::lng_group_call_active(tr::now)) + : (_state == State::RaisedHand) + ? tr::lng_group_call_raised_hand_status(tr::now) : tr::lng_group_call_inactive(tr::now)), _speaking); } @@ -1260,24 +1278,25 @@ void MembersController::rowUpdateRow(not_null row) { void MembersController::rowPaintIcon( Painter &p, QRect rect, - float64 speaking, - float64 active, - float64 muted, - bool mutedByMe) { + IconState state) { const auto &greenIcon = st::groupCallMemberColoredCrossLine.icon; const auto left = rect.x() + (rect.width() - greenIcon.width()) / 2; const auto top = rect.y() + (rect.height() - greenIcon.height()) / 2; - if (speaking == 1. && !mutedByMe) { + if (state.speaking == 1. && !state.mutedByMe) { // Just green icon, no cross, no coloring. greenIcon.paintInCenter(p, rect); return; - } else if (speaking == 0.) { - if (active == 1.) { + } else if (state.speaking == 0.) { + if (state.active == 1.) { // Just gray icon, no cross, no coloring. st::groupCallMemberInactiveCrossLine.icon.paintInCenter(p, rect); return; - } else if (active == 0.) { - if (muted == 1.) { + } else if (state.active == 0.) { + if (state.muted == 1.) { + if (state.raisedHand) { + st::groupCallMemberRaisedHand.paintInCenter(p, rect); + return; + } // Red crossed icon, colorized once, cached as last frame. _coloredCrossLine.paint( p, @@ -1286,7 +1305,7 @@ void MembersController::rowPaintIcon( 1., st::groupCallMemberMutedIcon->c); return; - } else if (muted == 0.) { + } else if (state.muted == 0.) { // Gray crossed icon, no coloring, cached as last frame. _inactiveCrossLine.paint(p, left, top, 1.); return; @@ -1295,17 +1314,18 @@ void MembersController::rowPaintIcon( } const auto activeInactiveColor = anim::color( st::groupCallMemberInactiveIcon, - (mutedByMe + (state.mutedByMe ? st::groupCallMemberMutedIcon : st::groupCallMemberActiveIcon), - speaking); + state.speaking); const auto iconColor = anim::color( activeInactiveColor, st::groupCallMemberMutedIcon, - muted); + state.muted); - // Don't use caching of the last frame, because 'muted' may animate color. - const auto crossProgress = std::min(1. - active, 0.9999); + // Don't use caching of the last frame, + // because 'muted' may animate color. + const auto crossProgress = std::min(1. - state.active, 0.9999); _inactiveCrossLine.paint(p, left, top, crossProgress, iconColor); } @@ -1493,6 +1513,7 @@ void MembersController::addMuteActionsToContextMenu( const auto muteState = row->state(); const auto isMuted = (muteState == Row::State::Muted) + || (muteState == Row::State::RaisedHand) || (muteState == Row::State::MutedByMe); auto mutesFromVolume = rpl::never() | rpl::type_erased(); @@ -1553,7 +1574,7 @@ void MembersController::addMuteActionsToContextMenu( const auto muteAction = [&]() -> QAction* { if (muteState == Row::State::Invited || isMe(participantPeer) - || (muteState == Row::State::Muted + || (muteState == Row::State::Inactive && participantIsCallAdmin && _peer->canManageGroupCall())) { return nullptr; @@ -1561,6 +1582,7 @@ void MembersController::addMuteActionsToContextMenu( auto callback = [=] { const auto state = row->state(); const auto muted = (state == Row::State::Muted) + || (state == Row::State::RaisedHand) || (state == Row::State::MutedByMe); toggleMute(!muted, false); }; diff --git a/Telegram/SourceFiles/data/data_group_call.cpp b/Telegram/SourceFiles/data/data_group_call.cpp index baeb26fb19..2c4e272a49 100644 --- a/Telegram/SourceFiles/data/data_group_call.cpp +++ b/Telegram/SourceFiles/data/data_group_call.cpp @@ -301,10 +301,13 @@ void GroupCall::applyParticipantsSlice( : data.is_muted_by_you(); const auto onlyMinLoaded = data.is_min() && (!was || was->onlyMinLoaded); + const auto raisedHandRating + = data.vraise_hand_rating().value_or_empty(); const auto value = Participant{ .peer = participantPeer, .date = data.vdate().v, .lastActive = lastActive, + .raisedHandRating = raisedHandRating, .ssrc = uint32(data.vsource().v), .volume = volume, .applyVolumeFromMin = applyVolumeFromMin, diff --git a/Telegram/SourceFiles/data/data_group_call.h b/Telegram/SourceFiles/data/data_group_call.h index 854710c41d..9cb779dc41 100644 --- a/Telegram/SourceFiles/data/data_group_call.h +++ b/Telegram/SourceFiles/data/data_group_call.h @@ -24,6 +24,7 @@ struct GroupCallParticipant { not_null peer; TimeId date = 0; TimeId lastActive = 0; + uint64 raisedHandRating = 0; uint32 ssrc = 0; int volume = 0; bool applyVolumeFromMin = true;