From c4ca180745300e3d1ac755341e9879fca9087b74 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 12 Sep 2018 20:02:30 +0300 Subject: [PATCH] Add call peer-to-peer setting in Privacy&Security. --- Telegram/Resources/langs/lang.strings | 3 + Telegram/SourceFiles/auth_session.cpp | 18 +++++- Telegram/SourceFiles/auth_session.h | 16 +++++ Telegram/SourceFiles/boxes/autolock_box.h | 2 - .../SourceFiles/boxes/edit_privacy_box.cpp | 62 ++++++++++++++++++ Telegram/SourceFiles/boxes/edit_privacy_box.h | 21 +++++++ Telegram/SourceFiles/calls/calls_call.cpp | 15 ++++- Telegram/SourceFiles/calls/calls_instance.h | 8 +++ Telegram/SourceFiles/mtproto/mtp_instance.cpp | 13 ++++ .../settings/settings_privacy_security.cpp | 63 +++++++++++++++---- 10 files changed, 206 insertions(+), 15 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index ba52c162f..4a47a022b 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -350,6 +350,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_settings_phone_label" = "Phone number"; "lng_settings_username_add" = "Add username"; "lng_settings_close_sure" = "Are you sure you want to close this page? You didn't save your changes."; +"lng_settings_calls_title" = "Calls"; +"lng_settings_peer_to_peer" = "Peer-to-Peer"; +"lng_settings_peer_to_peer_about" = "Disabling peer-to-peer will relay all calls through Telegram servers to avoid revealing your IP address, but may slightly decrease audio quality."; "lng_backgrounds_header" = "Choose your new chat background"; "lng_theme_sure_keep" = "Keep this theme?"; diff --git a/Telegram/SourceFiles/auth_session.cpp b/Telegram/SourceFiles/auth_session.cpp index e4bdfb06b..bce05b7d2 100644 --- a/Telegram/SourceFiles/auth_session.cpp +++ b/Telegram/SourceFiles/auth_session.cpp @@ -73,6 +73,7 @@ QByteArray AuthSessionSettings::serialize() const { stream << qint32(_variables.thirdColumnWidth.current()); stream << qint32(_variables.thirdSectionExtendedBy); stream << qint32(_variables.sendFilesWay); + stream << qint32(_variables.callsPeerToPeer.current()); } return result; } @@ -98,6 +99,7 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized) int thirdColumnWidth = _variables.thirdColumnWidth.current(); int thirdSectionExtendedBy = _variables.thirdSectionExtendedBy; qint32 sendFilesWay = static_cast(_variables.sendFilesWay); + qint32 callsPeerToPeer = qint32(_variables.callsPeerToPeer.current()); stream >> selectorTab; stream >> lastSeenWarningSeen; if (!stream.atEnd()) { @@ -146,6 +148,12 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized) stream >> value; thirdSectionExtendedBy = value; } + if (!stream.atEnd()) { + stream >> sendFilesWay; + } + if (!stream.atEnd()) { + stream >> callsPeerToPeer; + } if (stream.status() != QDataStream::Ok) { LOG(("App Error: " "Bad data for AuthSessionSettings::constructFromSerialized()")); @@ -188,7 +196,15 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized) switch (uncheckedSendFilesWay) { case SendFilesWay::Album: case SendFilesWay::Photos: - case SendFilesWay::Files: _variables.sendFilesWay = uncheckedSendFilesWay; + case SendFilesWay::Files: _variables.sendFilesWay = uncheckedSendFilesWay; break; + } + auto uncheckedCallsPeerToPeer = static_cast(callsPeerToPeer); + switch (uncheckedCallsPeerToPeer) { + case Calls::PeerToPeer::DefaultContacts: + case Calls::PeerToPeer::DefaultEveryone: + case Calls::PeerToPeer::Everyone: + case Calls::PeerToPeer::Contacts: + case Calls::PeerToPeer::Nobody: _variables.callsPeerToPeer = uncheckedCallsPeerToPeer; break; } } diff --git a/Telegram/SourceFiles/auth_session.h b/Telegram/SourceFiles/auth_session.h index 4acc88573..90e0e6db3 100644 --- a/Telegram/SourceFiles/auth_session.h +++ b/Telegram/SourceFiles/auth_session.h @@ -19,6 +19,10 @@ namespace Data { class Session; } // namespace Data +namespace Calls { +enum class PeerToPeer; +} // namespace Calls + namespace Storage { class Downloader; class Uploader; @@ -144,6 +148,16 @@ public: _variables.groupStickersSectionHidden.remove(peerId); } + rpl::producer callsPeerToPeerValue() const { + return _variables.callsPeerToPeer.value(); + } + Calls::PeerToPeer callsPeerToPeer() const { + return _variables.callsPeerToPeer.current(); + } + void setCallsPeerToPeer(Calls::PeerToPeer value) { + _variables.callsPeerToPeer = value; + } + private: struct Variables { Variables(); @@ -167,6 +181,8 @@ private: = kDefaultDialogsWidthRatio; // per-window rpl::variable thirdColumnWidth = kDefaultThirdColumnWidth; // per-window + rpl::variable callsPeerToPeer + = Calls::PeerToPeer(); }; rpl::event_stream _thirdSectionInfoEnabledValue; diff --git a/Telegram/SourceFiles/boxes/autolock_box.h b/Telegram/SourceFiles/boxes/autolock_box.h index 82e34af81..c0bbd8e0f 100644 --- a/Telegram/SourceFiles/boxes/autolock_box.h +++ b/Telegram/SourceFiles/boxes/autolock_box.h @@ -14,8 +14,6 @@ class Radiobutton; } // namespace Ui class AutoLockBox : public BoxContent { - Q_OBJECT - public: AutoLockBox(QWidget*) { } diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp index 3a25b9a6f..686e82e87 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/slide_wrap.h" #include "history/history.h" #include "boxes/peer_list_controllers.h" +#include "calls/calls_instance.h" #include "base/binary_guard.h" #include "lang/lang_keys.h" #include "apiwrap.h" @@ -347,3 +348,64 @@ void EditPrivacyBox::dataReady(Value &&value) { createWidgets(); } } + +void EditCallsPeerToPeer::prepare() { + setTitle(langFactory(lng_settings_peer_to_peer)); + + addButton(langFactory(lng_box_ok), [=] { closeBox(); }); + + const auto options = { + PeerToPeer::Everyone, + PeerToPeer::Contacts, + PeerToPeer::Nobody + }; + + const auto value = Auth().settings().callsPeerToPeer(); + const auto adjusted = [&] { + if (value == PeerToPeer::DefaultContacts) { + return PeerToPeer::Contacts; + } else if (value == PeerToPeer::DefaultEveryone) { + return PeerToPeer::Everyone; + } + return value; + }(); + const auto label = [](PeerToPeer value) { + switch (value) { + case PeerToPeer::Everyone: return lang(lng_edit_privacy_everyone); + case PeerToPeer::Contacts: return lang(lng_edit_privacy_contacts); + case PeerToPeer::Nobody: return lang(lng_edit_privacy_nobody); + } + Unexpected("Adjusted Calls::PeerToPeer value."); + }; + auto group = std::make_shared>(adjusted); + auto y = st::boxOptionListPadding.top() + st::langsButton.margin.top(); + auto count = int(options.size()); + _options.reserve(count); + for (const auto option : options) { + _options.emplace_back( + this, + group, + option, + label(option), + st::langsButton); + _options.back()->moveToLeft( + st::boxPadding.left() + st::boxOptionListPadding.left(), + y); + y += _options.back()->heightNoMargins() + st::boxOptionListSkip; + } + group->setChangedCallback([=](PeerToPeer value) { chosen(value); }); + + setDimensions( + st::langsWidth, + (st::boxOptionListPadding.top() + + count * _options.back()->heightNoMargins() + + (count - 1) * st::boxOptionListSkip + + st::boxOptionListPadding.bottom() + + st::boxPadding.bottom())); +} + +void EditCallsPeerToPeer::chosen(PeerToPeer value) { + Auth().settings().setCallsPeerToPeer(value); + Auth().saveSettingsDelayed(); + closeBox(); +} diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.h b/Telegram/SourceFiles/boxes/edit_privacy_box.h index 7c1b4fe60..1e9d86f9b 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.h +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.h @@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/sender.h" #include "apiwrap.h" +namespace Calls { +enum class PeerToPeer; +} // namespace Calls + namespace Ui { class FlatLabel; class LinkButton; @@ -114,3 +118,20 @@ private: object_ptr _exceptionsDescription = { nullptr }; }; + +class EditCallsPeerToPeer : public BoxContent { +public: + EditCallsPeerToPeer(QWidget*) { + } + +protected: + void prepare() override; + +private: + using PeerToPeer = Calls::PeerToPeer; + + void chosen(PeerToPeer value); + + std::vector>> _options; + +}; diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 106b47b26..598a20184 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -572,7 +572,20 @@ void Call::createAndStartController(const MTPDphoneCall &call) { _controller->SetMicMute(_mute); } _controller->implData = static_cast(this); - _controller->SetRemoteEndpoints(endpoints, true, protocol.vmax_layer.v); + const auto p2p = [&] { + switch (Auth().settings().callsPeerToPeer()) { + case PeerToPeer::DefaultContacts: + case PeerToPeer::Contacts: + return _user->isContact(); + case PeerToPeer::DefaultEveryone: + case PeerToPeer::Everyone: + return true; + case PeerToPeer::Nobody: + return false; + } + Unexpected("Calls::PeerToPeer value in Auth().settings()."); + }(); + _controller->SetRemoteEndpoints(endpoints, p2p, protocol.vmax_layer.v); _controller->SetConfig(config); _controller->SetEncryptionKey(reinterpret_cast(_authKey.data()), (_type == Type::Outgoing)); _controller->SetCallbacks(callbacks); diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index d19e7b544..29e7aa6fc 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -18,6 +18,14 @@ class Track; namespace Calls { +enum class PeerToPeer { + DefaultContacts, + DefaultEveryone, + Everyone, + Contacts, + Nobody, +}; + class Panel; class Instance : private MTP::Sender, private Call::Delegate, private base::Subscriber { diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.cpp b/Telegram/SourceFiles/mtproto/mtp_instance.cpp index adac1e111..23b233cea 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_instance.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/sender.h" #include "mtproto/rsa_public_key.h" #include "storage/localstorage.h" +#include "calls/calls_instance.h" #include "auth_session.h" #include "application.h" #include "apiwrap.h" @@ -782,6 +783,18 @@ void Instance::Private::configLoadDone(const MTPConfig &result) { + (data.vexpires.v - unixtime()) * TimeMs(1000); requestConfigIfExpired(); + if (AuthSession::Exists()) { + using PeerToPeer = Calls::PeerToPeer; + const auto current = Auth().settings().callsPeerToPeer(); + if (current == PeerToPeer::DefaultContacts + || current == PeerToPeer::DefaultEveryone) { + Auth().settings().setCallsPeerToPeer( + (data.is_default_p2p_contacts() + ? PeerToPeer::DefaultContacts + : PeerToPeer::DefaultEveryone)); + } + } + emit _instance->configLoaded(); } diff --git a/Telegram/SourceFiles/settings/settings_privacy_security.cpp b/Telegram/SourceFiles/settings/settings_privacy_security.cpp index 51117ad98..13010da57 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_security.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_security.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/slide_wrap.h" #include "ui/widgets/shadow.h" #include "ui/widgets/labels.h" +#include "calls/calls_instance.h" #include "core/core_cloud_password.h" #include "core/update_checker.h" #include "info/profile/info_profile_button.h" @@ -42,6 +43,19 @@ rpl::producer<> PasscodeChanges() { )); } +QString PrivacyBase(ApiWrap::Privacy::Option option) { + const auto key = [&] { + using Option = ApiWrap::Privacy::Option; + switch (option) { + case Option::Everyone: return lng_edit_privacy_everyone; + case Option::Contacts: return lng_edit_privacy_contacts; + case Option::Nobody: return lng_edit_privacy_nobody; + } + Unexpected("Value in Privacy::Option."); + }(); + return lang(key); +} + void SetupPrivacy(not_null container) { AddDivider(container); AddSkip(container); @@ -71,15 +85,6 @@ void SetupPrivacy(not_null container) { return Auth().api().privacyValue( key ) | rpl::map([](const Privacy &value) { - const auto base = [&] { - using Option = Privacy::Option; - switch (value.option) { - case Option::Everyone: return lng_edit_privacy_everyone; - case Option::Contacts: return lng_edit_privacy_contacts; - case Option::Nobody: return lng_edit_privacy_nobody; - } - Unexpected("Value in Privacy::Option."); - }(); auto add = QStringList(); if (const auto never = value.never.size()) { add.push_back("-" + QString::number(never)); @@ -88,9 +93,9 @@ void SetupPrivacy(not_null container) { add.push_back("+" + QString::number(always)); } if (!add.isEmpty()) { - return lang(base) + " (" + add.join(", ") + ")"; + return PrivacyBase(value.option) + " (" + add.join(", ") + ")"; } else { - return lang(base); + return PrivacyBase(value.option); } }); }; @@ -413,6 +418,41 @@ void SetupSecurity(not_null container) { Lang::Viewer(lng_settings_sessions_about)); } +void SetupCalls(not_null container) { + AddSkip(container); + + AddSubsectionTitle(container, lng_settings_calls_title); + + using Privacy = ApiWrap::Privacy; + using PeerToPeer = Calls::PeerToPeer; + auto text = Auth().settings().callsPeerToPeerValue( + ) | rpl::map([](PeerToPeer value) { + switch (value) { + case PeerToPeer::DefaultContacts: return Privacy::Option::Contacts; + case PeerToPeer::DefaultEveryone: return Privacy::Option::Everyone; + case PeerToPeer::Everyone: return Privacy::Option::Everyone; + case PeerToPeer::Contacts: return Privacy::Option::Contacts; + case PeerToPeer::Nobody: return Privacy::Option::Nobody; + } + Unexpected("Calls::PeerToPeer value."); + }) | rpl::map([](Privacy::Option option) { + return PrivacyBase(option); + }); + AddButtonWithLabel( + container, + lng_settings_peer_to_peer, + std::move(text), + st::settingsButton + )->addClickHandler([=] { + Ui::show(Box()); + }); + + AddSkip(container, st::settingsPrivacySecurityPadding); + AddDividerText( + container, + Lang::Viewer(lng_settings_peer_to_peer_about)); +} + void SetupExport(not_null container) { AddSkip(container); @@ -445,6 +485,7 @@ void PrivacySecurity::setupContent() { AddSkip(content, st::settingsFirstDividerSkip); SetupPrivacy(content); SetupSecurity(content); + SetupCalls(content); SetupExport(content); Ui::ResizeFitChild(this, content);