@@ -80,6 +80,8 @@ class Members::Controller final
8080 }
8181 [[nodiscard]] rpl::producer<MuteRequest> toggleMuteRequests () const ;
8282 [[nodiscard]] rpl::producer<VolumeRequest> changeVolumeRequests () const ;
83+ [[nodiscard]] rpl::producer<MuteRequest> toggleScreenMuteRequests () const ;
84+ [[nodiscard]] rpl::producer<VolumeRequest> changeScreenVolumeRequests () const ;
8385 [[nodiscard]] auto kickParticipantRequests () const
8486 -> rpl::producer<not_null<PeerData*>>;
8587
@@ -188,6 +190,8 @@ class Members::Controller final
188190
189191 rpl::event_stream<MuteRequest> _toggleMuteRequests;
190192 rpl::event_stream<VolumeRequest> _changeVolumeRequests;
193+ rpl::event_stream<MuteRequest> _toggleScreenMuteRequests;
194+ rpl::event_stream<VolumeRequest> _changeScreenVolumeRequests;
191195 rpl::event_stream<not_null<PeerData*>> _kickParticipantRequests;
192196 rpl::variable<int > _fullCount = 1 ;
193197
@@ -1047,6 +1051,16 @@ auto Members::Controller::changeVolumeRequests() const
10471051 return _changeVolumeRequests.events ();
10481052}
10491053
1054+ auto Members::Controller::toggleScreenMuteRequests () const
1055+ -> rpl::producer<MuteRequest> {
1056+ return _toggleScreenMuteRequests.events ();
1057+ }
1058+
1059+ auto Members::Controller::changeScreenVolumeRequests () const
1060+ -> rpl::producer<VolumeRequest> {
1061+ return _changeScreenVolumeRequests.events ();
1062+ }
1063+
10501064bool Members::Controller::rowIsMe (not_null<PeerData*> participantPeer) {
10511065 return isMe (participantPeer);
10521066}
@@ -1581,11 +1595,40 @@ void Members::Controller::addMuteActionsToContextMenu(
15811595 .locallyOnly = local,
15821596 });
15831597 });
1598+ const auto toggleScreenMute = crl::guard (this , [=](bool mute) {
1599+ _toggleScreenMuteRequests.fire (Group::MuteRequest{
1600+ .peer = participantPeer,
1601+ .mute = mute,
1602+ .locallyOnly = true ,
1603+ });
1604+ });
1605+ const auto changeScreenVolume = crl::guard (this , [=](int volume) {
1606+ _changeScreenVolumeRequests.fire (Group::VolumeRequest{
1607+ .peer = participantPeer,
1608+ .volume = std::clamp (volume, 1 , Group::kMaxVolume ),
1609+ .locallyOnly = true ,
1610+ });
1611+ });
1612+ const auto addSectionLabel = [=](const QString &text) {
1613+ const auto action = menu->addAction (text, [] {});
1614+ action->setEnabled (false );
1615+ };
1616+ const auto screenMuteActionText = [=](bool muted) {
1617+ return tr::lng_group_call_screen_share_audio (tr::now)
1618+ + u" : " _q
1619+ + (muted
1620+ ? tr::lng_call_unmute_audio (tr::now)
1621+ : tr::lng_call_mute_audio (tr::now));
1622+ };
15841623
15851624 const auto muteState = row->state ();
15861625 const auto muted = (muteState == Row::State::Muted)
15871626 || (muteState == Row::State::RaisedHand);
15881627 const auto mutedByMe = row->mutedByMe ();
1628+ const auto addScreenVolumeItem = !_call->rtmp ()
1629+ && !_call->videoStream ()
1630+ && !isMe (participantPeer)
1631+ && _call->hasScreenShareAudio (participantPeer);
15891632
15901633 auto mutesFromVolume = rpl::never<bool >() | rpl::type_erased;
15911634
@@ -1643,16 +1686,70 @@ void Members::Controller::addMuteActionsToContextMenu(
16431686 if (menu->actions ().size () > 1 ) { // First - cover.
16441687 menu->addSeparator ();
16451688 }
1689+ if (addScreenVolumeItem) {
1690+ addSectionLabel (tr::lng_group_call_microphone (tr::now));
1691+ }
16461692
16471693 menu->addAction (std::move (volumeItem));
16481694
1649- if (!_call->rtmp ()
1650- && !_call->videoStream ()
1651- && !isMe (participantPeer)) {
1695+ if (!addScreenVolumeItem && !isMe (participantPeer)) {
16521696 menu->addSeparator ();
16531697 }
16541698 };
16551699
1700+ if (addScreenVolumeItem) {
1701+ auto otherParticipantScreenStateValue = rpl::merge (
1702+ _call->otherParticipantScreenStateValue (
1703+ ) | rpl::filter ([=](const Group::ParticipantState &data) {
1704+ return data.peer == participantPeer;
1705+ }),
1706+ _call->otherParticipantStateValue (
1707+ ) | rpl::filter ([=](const Group::ParticipantState &data) {
1708+ return data.peer == participantPeer;
1709+ }) | rpl::map ([=](const Group::ParticipantState &) {
1710+ return _call->participantScreenState (participantPeer);
1711+ }));
1712+
1713+ const auto state = _call->participantScreenState (participantPeer);
1714+ auto volumeItem = base::make_unique_q<MenuVolumeItem>(
1715+ menu->menu (),
1716+ st::groupCallPopupVolumeMenu,
1717+ st::groupCallMenuVolumeSlider,
1718+ std::move (otherParticipantScreenStateValue),
1719+ state.volume .value_or (Group::kDefaultVolume ),
1720+ Group::kMaxVolume ,
1721+ state.mutedByMe ,
1722+ st::groupCallMenuVolumePadding);
1723+
1724+ volumeItem->toggleMuteRequests (
1725+ ) | rpl::on_next ([=](bool muted) {
1726+ toggleScreenMute (muted);
1727+ }, volumeItem->lifetime ());
1728+
1729+ volumeItem->toggleMuteLocallyRequests (
1730+ ) | rpl::on_next ([=](bool muted) {
1731+ toggleScreenMute (muted);
1732+ }, volumeItem->lifetime ());
1733+
1734+ volumeItem->changeVolumeRequests (
1735+ ) | rpl::on_next ([=](int volume) {
1736+ changeScreenVolume (volume);
1737+ }, volumeItem->lifetime ());
1738+
1739+ volumeItem->changeVolumeLocallyRequests (
1740+ ) | rpl::on_next ([=](int volume) {
1741+ changeScreenVolume (volume);
1742+ }, volumeItem->lifetime ());
1743+
1744+ if (menu->actions ().size () > 1 ) {
1745+ menu->addSeparator ();
1746+ }
1747+ addSectionLabel (tr::lng_group_call_screen_share_audio (tr::now));
1748+
1749+ menu->addAction (std::move (volumeItem));
1750+ menu->addSeparator ();
1751+ }
1752+
16561753 const auto muteAction = [&]() -> QAction* {
16571754 if (muteState == Row::State::Invited
16581755 || muteState == Row::State::Calling
@@ -1696,6 +1793,29 @@ void Members::Controller::addMuteActionsToContextMenu(
16961793 muteAction->setText (muteUnmuteString (muted, mutedByMe));
16971794 }, menu->lifetime ());
16981795 }
1796+ if (addScreenVolumeItem) {
1797+ const auto initial = _call->participantScreenState (participantPeer);
1798+ const auto screenMuteAction = menu->addAction (
1799+ screenMuteActionText (initial.mutedByMe ),
1800+ [=] {
1801+ const auto state = _call->participantScreenState (participantPeer);
1802+ toggleScreenMute (!state.mutedByMe );
1803+ });
1804+ rpl::merge (
1805+ _call->otherParticipantScreenStateValue (
1806+ ) | rpl::filter ([=](const Group::ParticipantState &data) {
1807+ return data.peer == participantPeer;
1808+ }),
1809+ _call->otherParticipantStateValue (
1810+ ) | rpl::filter ([=](const Group::ParticipantState &data) {
1811+ return data.peer == participantPeer;
1812+ }) | rpl::map ([=](const Group::ParticipantState &) {
1813+ return _call->participantScreenState (participantPeer);
1814+ })
1815+ ) | rpl::on_next ([=](const Group::ParticipantState &state) {
1816+ screenMuteAction->setText (screenMuteActionText (state.mutedByMe ));
1817+ }, menu->lifetime ());
1818+ }
16991819}
17001820
17011821std::unique_ptr<Row> Members::Controller::createRowForMe () {
@@ -1782,6 +1902,16 @@ auto Members::changeVolumeRequests() const
17821902 return _listController->changeVolumeRequests ();
17831903}
17841904
1905+ auto Members::toggleScreenMuteRequests () const
1906+ -> rpl::producer<Group::MuteRequest> {
1907+ return _listController->toggleScreenMuteRequests ();
1908+ }
1909+
1910+ auto Members::changeScreenVolumeRequests () const
1911+ -> rpl::producer<Group::VolumeRequest> {
1912+ return _listController->changeScreenVolumeRequests ();
1913+ }
1914+
17851915auto Members::kickParticipantRequests () const
17861916-> rpl::producer<not_null<PeerData*>> {
17871917 return _listController->kickParticipantRequests ();
0 commit comments