From abb81c764e71820d86e428f334a49cc15b88590d Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 28 Nov 2020 17:07:36 +0300 Subject: [PATCH] Allow discarding group call when leaving. --- Telegram/CMakeLists.txt | 2 + Telegram/Resources/langs/lang.strings | 1 + .../SourceFiles/calls/calls_group_call.cpp | 47 +++++++++-- Telegram/SourceFiles/calls/calls_group_call.h | 8 +- .../SourceFiles/calls/calls_group_members.cpp | 2 +- .../SourceFiles/calls/calls_group_panel.cpp | 79 ++++++++++++++++--- .../SourceFiles/calls/calls_group_panel.h | 15 ++++ .../calls/calls_group_settings.cpp | 34 ++++++++ .../SourceFiles/calls/calls_group_settings.h | 19 +++++ Telegram/SourceFiles/calls/calls_top_bar.cpp | 8 +- Telegram/SourceFiles/data/data_group_call.cpp | 17 ++-- Telegram/SourceFiles/data/data_group_call.h | 4 - Telegram/SourceFiles/mainwidget.cpp | 2 +- Telegram/lib_ui | 2 +- 14 files changed, 204 insertions(+), 36 deletions(-) create mode 100644 Telegram/SourceFiles/calls/calls_group_settings.cpp create mode 100644 Telegram/SourceFiles/calls/calls_group_settings.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index c64e375c1..e8072cf86 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -270,6 +270,8 @@ PRIVATE calls/calls_group_members.h calls/calls_group_panel.cpp calls/calls_group_panel.h + calls/calls_group_settings.cpp + calls/calls_group_settings.h calls/calls_emoji_fingerprint.cpp calls/calls_emoji_fingerprint.h calls/calls_instance.cpp diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 5d609b908..acb95429d 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1824,6 +1824,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_call_leave_sure" = "Are you sure you want to leave this voice chat?"; "lng_group_call_also_end" = "End voice chat"; "lng_group_call_settings_title" = "Settings"; +"lng_group_call_new_muted" = "Mute new members"; "lng_group_call_speakers" = "Speakers"; "lng_group_call_microphone" = "Microphone"; "lng_group_call_share" = "Share Invite Link"; diff --git a/Telegram/SourceFiles/calls/calls_group_call.cpp b/Telegram/SourceFiles/calls/calls_group_call.cpp index f3f35b017..ec6350e40 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/calls_group_call.cpp @@ -81,7 +81,7 @@ void GroupCall::setState(State state) { void GroupCall::start() { const auto randomId = rand_value(); - _api.request(MTPphone_CreateGroupCall( + _createRequestId = _api.request(MTPphone_CreateGroupCall( _channel->inputChannel, MTP_int(randomId) )).done([=](const MTPUpdates &result) { @@ -155,7 +155,9 @@ void GroupCall::rejoin() { MTP_dataJSON(MTP_bytes(json)) )).done([=](const MTPUpdates &updates) { _mySsrc = ssrc; - setState(State::Joined); + setState(_instanceConnected + ? State::Joined + : State::Connecting); applySelfInCallLocally(); if (_muted.current() != muted) { @@ -212,6 +214,24 @@ void GroupCall::hangup() { finish(FinishType::Ended); } +void GroupCall::discard() { + if (!_id) { + _api.request(_createRequestId).cancel(); + hangup(); + return; + } + _api.request(MTPphone_DiscardGroupCall( + inputCall() + )).done([=](const MTPUpdates &result) { + // Here 'this' could be destroyed by updates, so we set Ended after + // updates being handled, but in a guarded way. + crl::on_main(this, [=] { hangup(); }); + _channel->session().api().applyUpdates(result); + }).fail([=](const RPCError &error) { + hangup(); + }).send(); +} + void GroupCall::finish(FinishType type) { Expects(type != FinishType::None); @@ -330,7 +350,7 @@ void GroupCall::handleUpdate(const MTPGroupCall &call) { void GroupCall::handleUpdate(const MTPDupdateGroupCallParticipants &data) { const auto state = _state.current(); - if (state != State::Joined) { + if (state != State::Joined && state != State::Connecting) { return; } @@ -368,7 +388,8 @@ void GroupCall::createAndStartController() { tgcalls::GroupInstanceDescriptor descriptor = { .config = tgcalls::GroupConfig{ }, - .networkStateUpdated = [=](bool) { + .networkStateUpdated = [=](bool connected) { + crl::on_main(weak, [=] { setInstanceConnected(connected); }); }, .audioLevelsUpdated = [=](const AudioLevels &data) { crl::on_main(weak, [=] { audioLevelsUpdated(data); }); @@ -432,6 +453,18 @@ void GroupCall::audioLevelsUpdated( } } +void GroupCall::setInstanceConnected(bool connected) { + if (_instanceConnected == connected) { + return; + } + _instanceConnected = connected; + if (state() == State::Connecting && connected) { + setState(State::Joined); + } else if (state() == State::Joined && !connected) { + setState(State::Connecting); + } +} + void GroupCall::sendMutedUpdate() { _api.request(_updateMuteRequestId).cancel(); _updateMuteRequestId = _api.request(MTPphone_EditGroupCallMember( @@ -446,7 +479,8 @@ void GroupCall::sendMutedUpdate() { }).fail([=](const RPCError &error) { _updateMuteRequestId = 0; if (error.type() == u"GROUP_CALL_FORBIDDEN"_q - && _state.current() == State::Joined) { + && (_state.current() == State::Joined + || _state.current() == State::Connecting)) { setState(State::Joining); rejoin(); } @@ -475,7 +509,8 @@ void GroupCall::toggleMute(not_null user, bool mute) { _channel->session().api().applyUpdates(result); }).fail([=](const RPCError &error) { if (error.type() == u"GROUP_CALL_FORBIDDEN"_q - && _state.current() == State::Joined) { + && (_state.current() == State::Joined + || _state.current() == State::Connecting)) { setState(State::Joining); rejoin(); } diff --git a/Telegram/SourceFiles/calls/calls_group_call.h b/Telegram/SourceFiles/calls/calls_group_call.h index f38f216d9..593c15e43 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.h +++ b/Telegram/SourceFiles/calls/calls_group_call.h @@ -57,6 +57,7 @@ public: void start(); void hangup(); + void discard(); void join(const MTPInputGroupCall &inputCall); void handleUpdate(const MTPGroupCall &call); void handleUpdate(const MTPDupdateGroupCallParticipants &data); @@ -68,13 +69,11 @@ public: [[nodiscard]] rpl::producer mutedValue() const { return _muted.value(); } - [[nodiscard]] bool joined() const { - return (_state.current() == State::Joined); - } enum State { Creating, Joining, + Connecting, Joined, FailedHangingUp, Failed, @@ -123,6 +122,7 @@ private: void myLevelUpdated(float level); void audioLevelsUpdated( const std::vector> &data); + void setInstanceConnected(bool connected); [[nodiscard]] MTPInputGroupCall inputCall() const; @@ -130,6 +130,7 @@ private: const not_null _channel; MTP::Sender _api; rpl::variable _state = State::Creating; + bool _instanceConnected = false; rpl::variable _muted = MuteState::Muted; bool _acceptFields = false; @@ -137,6 +138,7 @@ private: uint64 _id = 0; uint64 _accessHash = 0; uint32 _mySsrc = 0; + mtpRequestId _createRequestId = 0; mtpRequestId _updateMuteRequestId = 0; std::unique_ptr _instance; diff --git a/Telegram/SourceFiles/calls/calls_group_members.cpp b/Telegram/SourceFiles/calls/calls_group_members.cpp index 2550b56cb..fb0cfe011 100644 --- a/Telegram/SourceFiles/calls/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/calls_group_members.cpp @@ -27,7 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Calls { namespace { -constexpr auto kLevelThreshold = 0.01; +constexpr auto kLevelThreshold = 0.2; constexpr auto kLevelActiveTimeout = crl::time(1000); struct UpdateLevelResult { diff --git a/Telegram/SourceFiles/calls/calls_group_panel.cpp b/Telegram/SourceFiles/calls/calls_group_panel.cpp index 7ac1cb75b..634821b1b 100644 --- a/Telegram/SourceFiles/calls/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_group_panel.cpp @@ -8,17 +8,21 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "calls/calls_group_panel.h" #include "calls/calls_group_members.h" +#include "calls/calls_group_settings.h" #include "ui/widgets/buttons.h" #include "ui/widgets/window.h" #include "ui/widgets/call_button.h" #include "ui/widgets/call_mute_button.h" +#include "ui/widgets/checkbox.h" #include "ui/layers/layer_manager.h" -#include "boxes/confirm_box.h" +#include "ui/layers/generic_box.h" #include "core/application.h" #include "lang/lang_keys.h" +#include "data/data_channel.h" #include "base/event_filter.h" #include "app.h" #include "styles/style_calls.h" +#include "styles/style_layers.h" #ifdef Q_OS_WIN #include "ui/platform/win/ui_window_title_win.h" @@ -30,6 +34,44 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Calls { +void LeaveGroupCallBox( + not_null box, + not_null call, + bool discardChecked, + BoxContext context) { + box->setTitle(tr::lng_group_call_leave_title()); + box->addRow(object_ptr( + box.get(), + tr::lng_group_call_leave_sure(), + st::boxLabel)); + const auto discard = call->channel()->canManageCall() + ? box->addRow(object_ptr( + box.get(), + tr::lng_group_call_end(), + discardChecked, + st::defaultBoxCheckbox), + style::margins( + st::boxRowPadding.left(), + st::boxRowPadding.left(), + st::boxRowPadding.right(), + st::boxRowPadding.bottom())) + : nullptr; + const auto weak = base::make_weak(call.get()); + box->addButton(tr::lng_group_call_leave(), [=] { + const auto discardCall = (discard && discard->checked()); + box->closeBox(); + + if (!weak) { + return; + } else if (discardCall) { + call->discard(); + } else { + call->hangup(); + } + }); + box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); +} + GroupPanel::GroupPanel(not_null call) : _call(call) , _channel(call->channel()) @@ -96,7 +138,10 @@ void GroupPanel::initWindow() { return Flag::None | Flag(0); } #endif // Q_OS_WIN - const auto inControls = false; + const auto inControls = _settings->geometry().contains(widgetPoint) + || _mute->innerGeometry().contains(widgetPoint) + || _hangup->geometry().contains(widgetPoint) + || _members->geometry().contains(widgetPoint); return inControls ? Flag::None : (Flag::Move | Flag::Maximize); @@ -117,6 +162,21 @@ void GroupPanel::initWidget() { }, widget()->lifetime()); } +void GroupPanel::copyShareLink() { + +} + +void GroupPanel::hangup(bool discardCallChecked) { + if (!_call) { + return; + } + _layerBg->showBox(Box( + LeaveGroupCallBox, + _call, + discardCallChecked, + BoxContext::GroupCallPanel)); +} + void GroupPanel::initControls() { _mute->clicks( ) | rpl::filter([=](Qt::MouseButton button) { @@ -129,13 +189,12 @@ void GroupPanel::initControls() { } }, _mute->lifetime()); - _hangup->setClickedCallback([=] { - _layerBg->showBox(Box( - tr::lng_group_call_leave_sure(tr::now), - tr::lng_group_call_leave(tr::now), - [=] { if (_call) _call->hangup(); })); - }); + _hangup->setClickedCallback([=] { hangup(false); }); _settings->setClickedCallback([=] { + _layerBg->showBox(Box( + GroupCallSettingsBox, + [=] { copyShareLink(); }, + [=] { hangup(true); })); }); _settings->setText(tr::lng_menu_settings()); @@ -176,7 +235,9 @@ void GroupPanel::initWithCall(GroupCall *call) { rpl::combine( _call->mutedValue(), _call->stateValue() | rpl::map( - _1 == State::Creating || _1 == State::Joining + _1 == State::Creating + || _1 == State::Joining + || _1 == State::Connecting ) ) | rpl::start_with_next([=](MuteState mute, bool connecting) { _mute->setState(Ui::CallMuteButtonState{ diff --git a/Telegram/SourceFiles/calls/calls_group_panel.h b/Telegram/SourceFiles/calls/calls_group_panel.h index cda7c2b9a..6270b2454 100644 --- a/Telegram/SourceFiles/calls/calls_group_panel.h +++ b/Telegram/SourceFiles/calls/calls_group_panel.h @@ -32,6 +32,7 @@ template class PaddingWrap; class Window; class ScrollArea; +class GenericBox; class LayerManager; namespace Platform { class TitleControls; @@ -50,6 +51,17 @@ class SignalBars; class GroupMembers; +enum class BoxContext { + GroupCallPanel, + MainWindow, +}; + +void LeaveGroupCallBox( + not_null box, + not_null call, + bool discardChecked, + BoxContext context); + class GroupPanel final { public: GroupPanel(not_null call); @@ -77,6 +89,9 @@ private: void updateControlsGeometry(); void showControls(); + void copyShareLink(); + void hangup(bool discardCallChecked); + [[nodiscard]] int computeMembersListTop() const; [[nodiscard]] std::optional computeTitleRect() const; void refreshTitle(); diff --git a/Telegram/SourceFiles/calls/calls_group_settings.cpp b/Telegram/SourceFiles/calls/calls_group_settings.cpp new file mode 100644 index 000000000..49bf82c94 --- /dev/null +++ b/Telegram/SourceFiles/calls/calls_group_settings.cpp @@ -0,0 +1,34 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "calls/calls_group_settings.h" + +#include "ui/widgets/checkbox.h" +#include "lang/lang_keys.h" +#include "styles/style_layers.h" + +namespace Calls { + +void GroupCallSettingsBox( + not_null box, + Fn copyShareLink, + Fn discard) { + box->setTitle(tr::lng_group_call_settings_title()); + //box->addRow(object_ptr( + // box.get(), + // tr::lng_group_call_new_muted(), + // newMuted + // )) + box->addButton(tr::lng_settings_save(), [=] { + box->closeBox(); + }); + box->addButton(tr::lng_cancel(), [=] { + box->closeBox(); + }); +} + +} // namespace Calls diff --git a/Telegram/SourceFiles/calls/calls_group_settings.h b/Telegram/SourceFiles/calls/calls_group_settings.h new file mode 100644 index 000000000..51797cc26 --- /dev/null +++ b/Telegram/SourceFiles/calls/calls_group_settings.h @@ -0,0 +1,19 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "ui/layers/generic_box.h" + +namespace Calls { + +void GroupCallSettingsBox( + not_null box, + Fn copyShareLink, + Fn discard); + +} // namespace Calls diff --git a/Telegram/SourceFiles/calls/calls_top_bar.cpp b/Telegram/SourceFiles/calls/calls_top_bar.cpp index e06097ced..e129b20b5 100644 --- a/Telegram/SourceFiles/calls/calls_top_bar.cpp +++ b/Telegram/SourceFiles/calls/calls_top_bar.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" +#include "ui/layers/generic_box.h" #include "ui/wrap/padding_wrap.h" #include "ui/text/format_values.h" #include "lang/lang_keys.h" @@ -16,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "calls/calls_call.h" #include "calls/calls_instance.h" #include "calls/calls_signal_bars.h" +#include "calls/calls_group_panel.h" // LeaveGroupCallBox. #include "data/data_user.h" #include "data/data_channel.h" #include "data/data_changes.h" @@ -174,7 +176,11 @@ void TopBar::initControls() { if (const auto call = _call.get()) { call->hangup(); } else if (const auto group = _groupCall.get()) { - group->hangup(); + Ui::show(Box( + LeaveGroupCallBox, + group, + false, + BoxContext::MainWindow)); } }); _updateDurationTimer.setCallback([this] { updateDurationText(); }); diff --git a/Telegram/SourceFiles/data/data_group_call.cpp b/Telegram/SourceFiles/data/data_group_call.cpp index e30fb9458..f39cf67d0 100644 --- a/Telegram/SourceFiles/data/data_group_call.cpp +++ b/Telegram/SourceFiles/data/data_group_call.cpp @@ -86,9 +86,6 @@ void GroupCall::requestParticipants() { }).fail([=](const RPCError &error) { _fullCount = _participants.size(); _allReceived = true; - _channel->session().changes().peerUpdated( - _channel, - PeerUpdate::Flag::GroupCall); _participantsRequestId = 0; }).send(); } @@ -136,13 +133,13 @@ void GroupCall::applyCall(const MTPGroupCall &call, bool force) { _version = data.vversion().v; _fullCount = data.vparticipants_count().v; }, [&](const MTPDgroupCallDiscarded &data) { - const auto changed = (_duration != data.vduration().v) - || !_finished; - if (!force && !changed) { - return; - } - _finished = true; - _duration = data.vduration().v; + const auto id = _id; + const auto channel = _channel; + crl::on_main(&channel->session(), [=] { + if (channel->call() && channel->call()->id() == id) { + channel->clearCall(); + } + }); }); } diff --git a/Telegram/SourceFiles/data/data_group_call.h b/Telegram/SourceFiles/data/data_group_call.h index 4ccda796c..22cfc0865 100644 --- a/Telegram/SourceFiles/data/data_group_call.h +++ b/Telegram/SourceFiles/data/data_group_call.h @@ -53,8 +53,6 @@ public: [[nodiscard]] rpl::producer fullCountValue() const; void reload(); - [[nodiscard]] bool finished() const; - [[nodiscard]] int duration() const; private: void applyCall(const MTPGroupCall &call, bool force); @@ -80,8 +78,6 @@ private: rpl::event_stream _participantUpdates; rpl::event_stream<> _participantsSliceAdded; - int _duration = 0; - bool _finished = false; bool _allReceived = false; }; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index c0d7423fc..10820639b 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -976,7 +976,7 @@ void MainWidget::setCurrentGroupCall(Calls::GroupCall *call) { _currentGroupCall->stateValue( ) | rpl::start_with_next([=](Calls::GroupCall::State state) { using State = Calls::GroupCall::State; - if (state == State::Joined) { + if (state == State::Joined || state == State::Connecting) { createCallTopBar(); } else { destroyCallTopBar(); diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 962c8d89e..41bae1eba 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 962c8d89e52a8c92bc7987eba4cfaef77a3a9ebf +Subproject commit 41bae1eba67801eb8768887100c17b7e84e7daf7