diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 1f6cd9ff8d..9aae07adba 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -5266,6 +5266,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_call_invite_search_results" = "Search results"; "lng_group_call_invite_limit" = "This is currently the maximum allowed number of participants."; "lng_group_call_new_muted" = "Mute new participants"; +"lng_group_call_enable_messages" = "Enable messages"; "lng_group_call_speakers" = "Speakers"; "lng_group_call_microphone" = "Microphone"; "lng_group_call_push_to_talk" = "Push-to-Talk Shortcut"; diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp index beb33ee1f2..b5749d0faa 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp @@ -958,6 +958,10 @@ void GroupCall::setScheduledDate(TimeId date) { } } +void GroupCall::setMessagesEnabled(bool enabled) { + _messagesEnabled = enabled && !_rtmp; +} + void GroupCall::subscribeToReal(not_null real) { _listenersHidden = real->listenersHidden(); @@ -966,6 +970,11 @@ void GroupCall::subscribeToReal(not_null real) { setScheduledDate(date); }, _lifetime); + real->messagesEnabledValue( + ) | rpl::start_with_next([=](bool enabled) { + setMessagesEnabled(enabled); + }, _lifetime); + // Postpone creating video tracks, so that we know if Panel // supports OpenGL and we don't need ARGB32 frames at all. Ui::PostponeCall(this, [=] { @@ -2305,6 +2314,7 @@ void GroupCall::handlePossibleCreateOrJoinResponse( const auto rtmp = data.is_rtmp_stream(); _rtmp = rtmp; setScheduledDate(scheduleDate); + setMessagesEnabled(data.is_messages_enabled()); if (const auto chat = _peer->asChat()) { chat->setGroupCall(input, scheduleDate, rtmp); } else if (const auto group = _peer->asChannel()) { @@ -2320,6 +2330,7 @@ void GroupCall::handlePossibleCreateOrJoinResponse( return; } setScheduledDate(data.vschedule_date().value_or_empty()); + setMessagesEnabled(data.is_messages_enabled()); if (const auto streamDcId = data.vstream_dc_id()) { _broadcastDcId = MTP::BareDcId(streamDcId->v); } diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.h b/Telegram/SourceFiles/calls/group/calls_group_call.h index 741a03655d..22de681c1c 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.h +++ b/Telegram/SourceFiles/calls/group/calls_group_call.h @@ -422,6 +422,12 @@ public: [[nodiscard]] rpl::producer videoIsWorkingValue() const { return _videoIsWorking.value(); } + [[nodiscard]] bool messagesEnabled() const { + return _messagesEnabled.current(); + } + [[nodiscard]] rpl::producer messagesEnabledValue() const { + return _messagesEnabled.value(); + } [[nodiscard]] bool isSharingScreen() const; [[nodiscard]] rpl::producer isSharingScreenValue() const; @@ -591,6 +597,7 @@ private: void saveDefaultJoinAs(not_null as); void subscribeToReal(not_null real); void setScheduledDate(TimeId date); + void setMessagesEnabled(bool enabled); void rejoinPresentation(); void leavePresentation(); void checkNextJoinAction(); @@ -711,6 +718,7 @@ private: rpl::variable _canManage = false; rpl::variable _videoIsWorking = false; rpl::variable _emptyRtmp = false; + rpl::variable _messagesEnabled = false; bool _initialMuteStateSent = false; bool _acceptFields = false; diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index ee05b31e5d..7fbfc53c65 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -726,12 +726,12 @@ rpl::producer Panel::toggleableOverrides( void Panel::refreshVideoButtons(std::optional overrideWideMode) { const auto create = overrideWideMode.value_or(mode() == PanelMode::Wide) || (!_call->scheduleDate() && _call->videoIsWorking()); - const auto created = _video != nullptr/*&& _screenShare*/; + const auto created = _video && _screenShare; if (created == create) { return; } else if (created) { _video.destroy(); - //_screenShare.destroy(); + _screenShare.destroy(); if (!overrideWideMode) { updateButtonsGeometry(); } @@ -761,19 +761,19 @@ void Panel::refreshVideoButtons(std::optional overrideWideMode) { _video->setProgress(sharing ? 1. : 0.); }, _video->lifetime()); } - //if (!_screenShare) { - // _screenShare.create(widget(), st::groupCallScreenShareSmall); - // _screenShare->show(); - // _screenShare->setClickedCallback([=] { - // chooseShareScreenSource(); - // }); - // _screenShare->setColorOverrides( - // toggleableOverrides(_call->isSharingScreenValue())); - // _call->isSharingScreenValue( - // ) | rpl::start_with_next([=](bool sharing) { - // _screenShare->setProgress(sharing ? 1. : 0.); - // }, _screenShare->lifetime()); - //} + if (!_screenShare) { + _screenShare.create(widget(), st::groupCallScreenShareSmall); + _screenShare->show(); + _screenShare->setClickedCallback([=] { + chooseShareScreenSource(); + }); + _screenShare->setColorOverrides( + toggleableOverrides(_call->isSharingScreenValue())); + _call->isSharingScreenValue( + ) | rpl::start_with_next([=](bool sharing) { + _screenShare->setProgress(sharing ? 1. : 0.); + }, _screenShare->lifetime()); + } if (!_wideMenu) { _wideMenu.create(widget(), st::groupCallMenuToggleSmall); _wideMenu->show(); @@ -1142,7 +1142,7 @@ void Panel::raiseControls() { const auto buttons = { &_settings, &_callShare, - //&_screenShare, + &_screenShare, &_wideMenu, &_video, &_message, @@ -1367,6 +1367,11 @@ void Panel::subscribeToChanges(not_null real) { showStickedTooltip(); }, lifetime()); + _call->messagesEnabledValue() | rpl::start_with_next([=] { + updateButtonsGeometry(); + raiseControls(); + }, lifetime()); + rpl::combine( _call->videoIsWorkingValue(), _call->isSharingScreenValue() @@ -2177,12 +2182,12 @@ void Panel::showNiceTooltip( not_null control, NiceTooltipType type) { auto text = [&]() -> rpl::producer { - /*if (control == _screenShare.data()) { + if (control == _screenShare.data()) { if (_call->mutedByAdmin()) { return nullptr; } - return tr::lng_group_call_tooltip_screen(); #TODO remove lang key - } else */if (control == _video.data()) { + return tr::lng_group_call_tooltip_screen(); + } else if (control == _video.data()) { if (_call->mutedByAdmin()) { return nullptr; } @@ -2337,7 +2342,7 @@ void Panel::trackControls(bool track, bool force) { trackOne(_mute->outer()); trackOne(_video); trackOne(_message); - //trackOne(_screenShare); + trackOne(_screenShare); trackOne(_wideMenu); trackOne(_settings); trackOne(_hangup); @@ -2394,11 +2399,12 @@ void Panel::updateButtonsGeometry() { widget->setVisible(shown); } }; + const auto messagesEnabled = _call->messagesEnabled(); auto messagesBottomSkip = 0; if (mode() == PanelMode::Wide) { Assert(_video != nullptr); Assert(_message != nullptr); - //Assert(_screenShare != nullptr); + Assert(_screenShare != nullptr); Assert(_wideMenu != nullptr); Assert(_settings != nullptr); Assert(_callShare == nullptr); @@ -2464,39 +2470,41 @@ void Panel::updateButtonsGeometry() { forMessagesWidth, forMessagesHeight); - //toggle(_screenShare, !hidden && !rtmp); - toggle(_message, !hidden && !rtmp); - //if (!rtmp) { - // _screenShare->moveToLeft(left, buttonsTop); - // left += _screenShare->width() + skip; - //} + toggle(_screenShare, !hidden && !rtmp && !messagesEnabled); + toggle(_message, !hidden && !rtmp && messagesEnabled); + if (!rtmp && !messagesEnabled) { + _screenShare->moveToLeft(left, buttonsTop); + left += _screenShare->width() + skip; + } else if (!rtmp) { + _wideMenu->moveToLeft(left, buttonsTop); + _settings->moveToLeft(left, buttonsTop); + left += _settings->width() + skip; + } - _wideMenu->moveToLeft(left, buttonsTop); - _settings->moveToLeft(left, buttonsTop); - left += _settings->width() + skip; + const auto wideMenuShown = _call->canManage() + || _call->showChooseJoinAs(); + toggle(_settings, !hidden && !wideMenuShown); + toggle(_wideMenu, !hidden && wideMenuShown); toggle(_video, !hidden && !rtmp); if (!rtmp) { _video->moveToLeft(left, buttonsTop); left += _video->width() + skip; - //} else { - // _wideMenu->moveToLeft(left, buttonsTop); - // _settings->moveToLeft(left, buttonsTop); - // left += _settings->width() + skip; + } else { + _wideMenu->moveToLeft(left, buttonsTop); + _settings->moveToLeft(left, buttonsTop); + left += _settings->width() + skip; } toggle(_mute, !hidden); _mute->moveInner({ left + addSkip, muteTop }); left += muteSize + skip; - const auto wideMenuShown = _call->canManage() - || _call->showChooseJoinAs(); - toggle(_settings, !hidden && !wideMenuShown); - toggle(_wideMenu, !hidden && wideMenuShown); - if (!rtmp) { - //_wideMenu->moveToLeft(left, buttonsTop); - //_settings->moveToLeft(left, buttonsTop); - //left += _settings->width() + skip; + if (!rtmp && messagesEnabled) { _message->moveToLeft(left, buttonsTop); left += _message->width() + skip; + } else if (!rtmp) { + _wideMenu->moveToLeft(left, buttonsTop); + _settings->moveToLeft(left, buttonsTop); + left += _settings->width() + skip; } toggle(_hangup, !hidden); _hangup->moveToLeft(left, buttonsTop); @@ -2518,8 +2526,8 @@ void Panel::updateButtonsGeometry() { const auto muteSize = _mute->innerSize().width(); const auto single = (_settings ? _settings : _callShare)->width(); const auto showVideoButton = videoButtonInNarrowMode(); - const auto four = !_callShare && !showVideoButton && _message; - const auto five = !four && !_callShare && _message; + const auto four = !_callShare && !showVideoButton && messagesEnabled; + const auto five = !four && !_callShare && messagesEnabled; const auto buttonSkip = four ? (st::groupCallButtonSkip / 2) : five @@ -2577,7 +2585,7 @@ void Panel::updateButtonsGeometry() { ? (nextButtonLeft + addSkip) : ((widget()->width() - muteSize) / 2); _mute->moveInner({ muteButtonLeft, muteTop }); - //toggle(_screenShare, false); + toggle(_screenShare, false); toggle(_wideMenu, false); toggle(_callShare, true); if (_callShare) { @@ -2594,7 +2602,7 @@ void Panel::updateButtonsGeometry() { four ? leftButtonLeft : nextButtonLeft, buttonsTop); } - toggle(_message, !_callShare); + toggle(_message, !_callShare && messagesEnabled); if (_message) { _message->moveToRight(nextButtonLeft, buttonsTop); } diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.h b/Telegram/SourceFiles/calls/group/calls_group_panel.h index d601e57d11..6f2fa17533 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.h +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.h @@ -251,7 +251,7 @@ private: object_ptr _wideMenu = { nullptr }; object_ptr _callShare = { nullptr }; object_ptr _video = { nullptr }; - //object_ptr _screenShare = { nullptr }; + object_ptr _screenShare = { nullptr }; object_ptr _message = { nullptr }; std::unique_ptr _mute; object_ptr _hangup; diff --git a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp index 007908d117..e0a0fff5f8 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp @@ -80,15 +80,38 @@ void SaveCallJoinMuted( || call->joinMuted() == joinMuted) { return; } + using Flag = MTPphone_ToggleGroupCallSettings::Flag; call->setJoinMutedLocally(joinMuted); peer->session().api().request(MTPphone_ToggleGroupCallSettings( - MTP_flags(MTPphone_ToggleGroupCallSettings::Flag::f_join_muted), + MTP_flags(Flag::f_join_muted), call->input(), MTP_bool(joinMuted), MTPBool() // messages_enabled )).send(); } +void SaveCallMessagesEnabled( + not_null peer, + CallId callId, + bool messagesEnabled) { + const auto call = peer->groupCall(); + if (!call + || call->id() != callId + || !peer->canManageGroupCall() + || !call->canChangeJoinMuted() + || call->messagesEnabled() == messagesEnabled) { + return; + } + using Flag = MTPphone_ToggleGroupCallSettings::Flag; + call->setMessagesEnabledLocally(messagesEnabled); + peer->session().api().request(MTPphone_ToggleGroupCallSettings( + MTP_flags(Flag::f_messages_enabled), + call->input(), + MTPBool(), // join_muted + MTP_bool(messagesEnabled) + )).send(); +} + [[nodiscard]] crl::time DelayByIndex(int index) { return index * crl::time(10); } @@ -243,10 +266,16 @@ void SettingsBox( const auto &settings = Core::App().settings(); const auto joinMuted = goodReal ? real->joinMuted() : false; + const auto messagesEnabled = goodReal ? real->messagesEnabled() : false; const auto canChangeJoinMuted = !rtmp && goodReal && real->canChangeJoinMuted(); - const auto addCheck = (peer->canManageGroupCall() && canChangeJoinMuted); + const auto canChangeMessagesEnabled = !rtmp + && goodReal + && real->canChangeMessagesEnabled(); + const auto addCheck = peer->canManageGroupCall() && canChangeJoinMuted; + const auto addMessages = peer->canManageGroupCall() + && canChangeMessagesEnabled; const auto addDivider = [&] { layout->add(object_ptr( @@ -255,7 +284,7 @@ void SettingsBox( st::groupCallDividerBg)); }; - if (addCheck) { + if (addCheck || addMessages) { Ui::AddSkip(layout); } const auto muteJoined = addCheck @@ -264,7 +293,14 @@ void SettingsBox( tr::lng_group_call_new_muted(), st::groupCallSettingsButton))->toggleOn(rpl::single(joinMuted)) : nullptr; - if (addCheck) { + const auto enableMessages = addMessages + ? layout->add(object_ptr( + layout, + tr::lng_group_call_enable_messages(), + st::groupCallSettingsButton))->toggleOn( + rpl::single(messagesEnabled)) + : nullptr; + if (addCheck || addMessages) { Ui::AddSkip(layout); } @@ -811,6 +847,11 @@ void SettingsBox( && muteJoined->toggled() != joinMuted) { SaveCallJoinMuted(peer, id, muteJoined->toggled()); } + if (canChangeMessagesEnabled + && enableMessages + && enableMessages->toggled() != messagesEnabled) { + SaveCallMessagesEnabled(peer, id, enableMessages->toggled()); + } }, box->lifetime()); box->addButton(tr::lng_box_done(), [=] { box->closeBox(); diff --git a/Telegram/SourceFiles/data/data_group_call.cpp b/Telegram/SourceFiles/data/data_group_call.cpp index f17e64aeb7..1d50a40dcf 100644 --- a/Telegram/SourceFiles/data/data_group_call.cpp +++ b/Telegram/SourceFiles/data/data_group_call.cpp @@ -522,6 +522,8 @@ void GroupCall::applyCallFields(const MTPDgroupCall &data) { _scheduleDate = data.vschedule_date().value_or_empty(); _scheduleStartSubscribed = data.is_schedule_start_subscribed(); _unmutedVideoLimit = data.vunmuted_video_limit().v; + _messagesEnabled = data.is_messages_enabled(); + _canChangeMessagesEnabled = data.is_can_change_messages_enabled(); _allParticipantsLoaded = (_serverParticipantsCount == _participants.size()); _conferenceInviteLink = qs(data.vinvite_link().value_or_empty()); @@ -1098,6 +1100,10 @@ bool GroupCall::joinedToTop() const { return _joinedToTop; } +void GroupCall::setMessagesEnabledLocally(bool enabled) { + _messagesEnabled = enabled; +} + ApiWrap &GroupCall::api() const { return session().api(); } diff --git a/Telegram/SourceFiles/data/data_group_call.h b/Telegram/SourceFiles/data/data_group_call.h index ef2cf38b7b..23e347f174 100644 --- a/Telegram/SourceFiles/data/data_group_call.h +++ b/Telegram/SourceFiles/data/data_group_call.h @@ -118,7 +118,7 @@ public: return _unmutedVideoLimit.current(); } [[nodiscard]] bool recordVideo() const { - return _recordVideo.current(); + return _recordVideo; } void setPeer(not_null peer); @@ -189,6 +189,17 @@ public: [[nodiscard]] bool canChangeJoinMuted() const; [[nodiscard]] bool joinedToTop() const; + void setMessagesEnabledLocally(bool enabled); + [[nodiscard]] bool canChangeMessagesEnabled() const { + return _canChangeMessagesEnabled; + } + [[nodiscard]] bool messagesEnabled() const { + return _messagesEnabled.current(); + } + [[nodiscard]] rpl::producer messagesEnabledValue() const { + return _messagesEnabled.value(); + } + private: enum class ApplySliceSource { FullReloaded, @@ -250,7 +261,7 @@ private: int _serverParticipantsCount = 0; rpl::variable _fullCount = 0; rpl::variable _unmutedVideoLimit = 0; - rpl::variable _recordVideo = 0; + rpl::variable _messagesEnabled = false; rpl::variable _recordStartDate = 0; rpl::variable _scheduleDate = 0; rpl::variable _scheduleStartSubscribed = false; @@ -273,7 +284,9 @@ private: bool _creator : 1 = false; bool _joinMuted : 1 = false; + bool _recordVideo : 1 = false; bool _canChangeJoinMuted : 1 = true; + bool _canChangeMessagesEnabled : 1 = true; bool _allParticipantsLoaded : 1 = false; bool _joinedToTop : 1 = false; bool _applyingQueuedUpdates : 1 = false;