diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 875372f31..93b1f741d 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -423,6 +423,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_proxy_settings" = "Proxy settings"; "lng_proxy_use" = "Use proxy"; +"lng_proxy_use_for_calls" = "Use proxy for calls"; +"lng_proxy_about" = "Proxy servers may be helpful in accessing Telegram if there is no connection in a specific region."; "lng_proxy_add" = "Add proxy"; "lng_proxy_share" = "Share"; "lng_proxy_online" = "online"; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 8e0110ef4..de5b576fe 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -117,6 +117,11 @@ boxLabel: FlatLabel(defaultFlatLabel) { align: align(topleft); style: boxLabelStyle; } +boxDividerLabel: FlatLabel(boxLabel) { + minWidth: 245px; + textFg: windowSubTextFg; + style: defaultTextStyle; +} countryRowHeight: 36px; countryRowNameFont: semiboldFont; @@ -712,8 +717,8 @@ sendMediaFileThumbSkip: 10px; sendMediaFileNameTop: 7px; sendMediaFileStatusTop: 37px; -proxyUsePadding: margins(22px, 8px, 22px, 12px); -proxyTryIPv6Padding: margins(22px, 12px, 22px, 8px); +proxyUsePadding: margins(22px, 6px, 22px, 5px); +proxyTryIPv6Padding: margins(22px, 8px, 22px, 5px); proxyRowPadding: margins(22px, 8px, 8px, 8px); proxyRowIconSkip: 32px; proxyRowSkip: 2px; @@ -774,3 +779,5 @@ proxyCheckingAnimation: InfiniteRadialAnimation(defaultInfiniteRadialAnimation) } proxyDropdownDownPosition: point(-2px, 35px); proxyDropdownUpPosition: point(-2px, 20px); + +proxyAboutPadding: margins(22px, 7px, 22px, 14px); diff --git a/Telegram/SourceFiles/boxes/connection_box.cpp b/Telegram/SourceFiles/boxes/connection_box.cpp index 6c7fe5e5b..bb241a5a4 100644 --- a/Telegram/SourceFiles/boxes/connection_box.cpp +++ b/Telegram/SourceFiles/boxes/connection_box.cpp @@ -104,13 +104,17 @@ private: void applyView(View &&view); void setupButtons(int id, not_null button); int rowHeight() const; + void refreshProxyForCalls(); not_null _controller; - object_ptr> _useProxy; - object_ptr> _tryIPv6; + QPointer _tryIPv6; + QPointer _useProxy; + QPointer> _proxyForCalls; + QPointer _about; base::unique_qptr _noRows; object_ptr _initialWrap; QPointer _wrap; + int _currentProxySupportsCallsId = 0; base::flat_map> _rows; @@ -416,7 +420,7 @@ void ProxyRow::showMenu() { addAction(lang(lng_proxy_menu_edit), [=] { _editClicks.fire({}); }); - if (_view.canShare) { + if (_view.supportsShare) { addAction(lang(lng_proxy_edit_share), [=] { _shareClicks.fire({}); }); @@ -465,19 +469,6 @@ ProxiesBox::ProxiesBox( QWidget*, not_null controller) : _controller(controller) -, _useProxy( - this, - object_ptr( - this, - lang(lng_proxy_use)), - st::proxyUsePadding) -, _tryIPv6( - this, - object_ptr( - this, - lang(lng_connection_try_ipv6), - Global::TryIPv6()), - st::proxyTryIPv6Padding) , _initialWrap(this) { _controller->views( ) | rpl::start_with_next([=](View &&view) { @@ -495,59 +486,100 @@ void ProxiesBox::prepare() { } void ProxiesBox::setupContent() { - _useProxy->resizeToWidth(st::boxWideWidth); - _useProxy->moveToLeft(0, 0); - subscribe(_useProxy->entity()->checkedChanged, [=](bool checked) { - if (!_controller->setProxyEnabled(checked)) { - _useProxy->entity()->setChecked(false); - addNewProxy(); - } - }); - subscribe(_tryIPv6->entity()->checkedChanged, [=](bool checked) { - _controller->setTryIPv6(checked); - }); - _controller->proxyEnabledValue( - ) | rpl::start_with_next([=](bool enabled) { - _useProxy->entity()->setChecked(enabled); - }, _useProxy->entity()->lifetime()); - _useProxy->entity()->finishAnimating(); + const auto inner = setInnerWidget(object_ptr(this)); - _tryIPv6->resizeToWidth(st::boxWideWidth); + _tryIPv6 = inner->add( + object_ptr( + inner, + lang(lng_connection_try_ipv6), + Global::TryIPv6()), + st::proxyTryIPv6Padding); + _useProxy = inner->add( + object_ptr( + inner, + lang(lng_proxy_use)), + st::proxyUsePadding); + _proxyForCalls = inner->add( + object_ptr>( + inner, + object_ptr( + inner, + lang(lng_proxy_use_for_calls), + Global::UseProxyForCalls()), + style::margins( + 0, + st::proxyUsePadding.top(), + 0, + st::proxyUsePadding.bottom())), + style::margins( + st::proxyTryIPv6Padding.left(), + 0, + st::proxyTryIPv6Padding.right(), + st::proxyTryIPv6Padding.top())); + + _about = inner->add( + object_ptr( + inner, + object_ptr( + inner, + lang(lng_proxy_about), + Ui::FlatLabel::InitType::Simple, + st::boxDividerLabel), + st::proxyAboutPadding), + style::margins(0, 0, 0, st::proxyRowPadding.top())); - const auto topSkip = _useProxy->heightNoMargins(); - const auto bottomSkip = _tryIPv6->heightNoMargins(); - const auto inner = setInnerWidget( - object_ptr(this), - topSkip, - bottomSkip); - inner->add(object_ptr( - inner, - st::proxyRowPadding.top())); _wrap = inner->add(std::move(_initialWrap)); inner->add(object_ptr( inner, st::proxyRowPadding.bottom())); + subscribe(_useProxy->checkedChanged, [=](bool checked) { + if (!_controller->setProxyEnabled(checked)) { + _useProxy->setChecked(false); + addNewProxy(); + } + refreshProxyForCalls(); + }); + subscribe(_tryIPv6->checkedChanged, [=](bool checked) { + _controller->setTryIPv6(checked); + }); + _controller->proxyEnabledValue( + ) | rpl::start_with_next([=](bool enabled) { + _useProxy->setChecked(enabled); + }, _useProxy->lifetime()); + _useProxy->finishAnimating(); + subscribe(_proxyForCalls->entity()->checkedChanged, [=](bool checked) { + _controller->setProxyForCalls(checked); + }); + if (_rows.empty()) { createNoRowsLabel(); } + refreshProxyForCalls(); + _proxyForCalls->finishAnimating(); inner->resizeToWidth(st::boxWideWidth); inner->heightValue( ) | rpl::map([=](int height) { return std::min( - topSkip + std::max(height, 3 * rowHeight()) + bottomSkip, + std::max(height, _about->y() + + _about->height() + + 3 * rowHeight()), st::boxMaxListHeight); }) | rpl::distinct_until_changed( ) | rpl::start_with_next([=](int height) { setDimensions(st::boxWideWidth, height); }, inner->lifetime()); +} - heightValue( - ) | rpl::start_with_next([=](int height) { - _tryIPv6->moveToLeft(0, height - _tryIPv6->heightNoMargins()); - }, _tryIPv6->lifetime()); +void ProxiesBox::refreshProxyForCalls() { + if (!_proxyForCalls) { + return; + } + _proxyForCalls->toggle( + _useProxy->checked() && _currentProxySupportsCallsId != 0, + anim::type::normal); } int ProxiesBox::rowHeight() const { @@ -563,6 +595,13 @@ void ProxiesBox::addNewProxy() { } void ProxiesBox::applyView(View &&view) { + if (view.selected) { + _currentProxySupportsCallsId = view.supportsCalls ? view.id : 0; + } else if (view.id == _currentProxySupportsCallsId) { + _currentProxySupportsCallsId = 0; + } + refreshProxyForCalls(); + const auto id = view.id; const auto i = _rows.find(id); if (i == _rows.end()) { @@ -652,7 +691,7 @@ void ProxyBox::prepare() { _content->heightValue( ) | rpl::start_with_next([=](int height) { - setDimensions(st::boxWidth, height); + setDimensions(st::boxWideWidth, height); }, _content->lifetime()); } @@ -819,7 +858,7 @@ void ProxyBox::setupControls(const ProxyData &data) { ? Type::Socks5 : data.type)); _content.create(this); - _content->resizeToWidth(st::boxWidth); + _content->resizeToWidth(st::boxWideWidth); _content->moveToLeft(0, 0); setupTypes(); @@ -827,7 +866,7 @@ void ProxyBox::setupControls(const ProxyData &data) { setupCredentials(data); setupMtprotoCredentials(data); - _content->resizeToWidth(st::boxWidth); + _content->resizeToWidth(st::boxWideWidth); const auto handleType = [=](Type type) { _credentials->toggle( @@ -1525,6 +1564,17 @@ bool ProxiesBoxController::setProxyEnabled(bool enabled) { return true; } +void ProxiesBoxController::setProxyForCalls(bool enabled) { + if (Global::UseProxyForCalls() == enabled) { + return; + } + Global::SetUseProxyForCalls(enabled); + if (Global::UseProxy() && Global::SelectedProxy().supportsCalls()) { + Global::RefConnectionTypeChanged().notify(); + } + saveDelayed(); +} + void ProxiesBoxController::setTryIPv6(bool enabled) { if (Global::TryIPv6() == enabled) { return; @@ -1571,8 +1621,9 @@ void ProxiesBoxController::updateView(const Item &item) { } return ItemState::Connecting; }(); - const auto canShare = (item.data.type == Type::Socks5) + const auto supportsShare = (item.data.type == Type::Socks5) || (item.data.type == Type::Mtproto); + const auto supportsCalls = item.data.supportsCalls(); _views.fire({ item.id, type, @@ -1581,7 +1632,8 @@ void ProxiesBoxController::updateView(const Item &item) { item.ping, !deleted && selected, deleted, - !deleted && canShare, + !deleted && supportsShare, + supportsCalls, state }); } diff --git a/Telegram/SourceFiles/boxes/connection_box.h b/Telegram/SourceFiles/boxes/connection_box.h index fd6a2cc72..04b33cc9f 100644 --- a/Telegram/SourceFiles/boxes/connection_box.h +++ b/Telegram/SourceFiles/boxes/connection_box.h @@ -116,7 +116,8 @@ public: int ping = 0; bool selected = false; bool deleted = false; - bool canShare = false; + bool supportsShare = false; + bool supportsCalls = false; ItemState state = ItemState::Checking; }; @@ -128,6 +129,7 @@ public: object_ptr editItemBox(int id); object_ptr addNewItemBox(); bool setProxyEnabled(bool enabled); + void setProxyForCalls(bool enabled); void setTryIPv6(bool enabled); rpl::producer proxyEnabledValue() const; diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 3f74add11..3ca5b5bed 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -40,17 +40,30 @@ constexpr auto kHangupTimeoutMs = 5000; using tgvoip::Endpoint; -void ConvertEndpoint(std::vector &ep, const MTPDphoneConnection &mtc) { +void ConvertEndpoint( + std::vector &ep, + const MTPDphoneConnection &mtc) { if (mtc.vpeer_tag.v.length() != 16) { return; } - auto ipv4 = tgvoip::IPv4Address(std::string(mtc.vip.v.constData(), mtc.vip.v.size())); - auto ipv6 = tgvoip::IPv6Address(std::string(mtc.vipv6.v.constData(), mtc.vipv6.v.size())); - ep.push_back(Endpoint((int64_t)mtc.vid.v, (uint16_t)mtc.vport.v, ipv4, ipv6, EP_TYPE_UDP_RELAY, (unsigned char*)mtc.vpeer_tag.v.data())); + auto ipv4 = tgvoip::IPv4Address(std::string( + mtc.vip.v.constData(), + mtc.vip.v.size())); + auto ipv6 = tgvoip::IPv6Address(std::string( + mtc.vipv6.v.constData(), + mtc.vipv6.v.size())); + ep.push_back(Endpoint( + (int64_t)mtc.vid.v, + (uint16_t)mtc.vport.v, + ipv4, + ipv6, + EP_TYPE_UDP_RELAY, + (unsigned char*)mtc.vpeer_tag.v.data())); } constexpr auto kFingerprintDataSize = 256; -uint64 ComputeFingerprint(const std::array &authKey) { +uint64 ComputeFingerprint( + const std::array &authKey) { auto hash = openssl::Sha1(authKey); return (gsl::to_integer(hash[19]) << 56) | (gsl::to_integer(hash[18]) << 48) @@ -64,7 +77,10 @@ uint64 ComputeFingerprint(const std::array &aut } // namespace -Call::Call(not_null delegate, not_null user, Type type) +Call::Call( + not_null delegate, + not_null user, + Type type) : _delegate(delegate) , _user(user) , _type(type) { @@ -505,6 +521,18 @@ void Call::createAndStartController(const MTPDphoneCall &call) { _controller->SetStateCallback([](tgvoip::VoIPController *controller, int state) { static_cast(controller->implData)->handleControllerStateChange(controller, state); }); + if (Global::UseProxy() && Global::UseProxyForCalls()) { + const auto proxy = Global::SelectedProxy(); + if (proxy.supportsCalls()) { + Assert(proxy.type == ProxyData::Type::Socks5); + _controller->SetProxy( + tgvoip::PROXY_SOCKS5, + proxy.host.toStdString(), + proxy.port, + proxy.user.toStdString(), + proxy.password.toStdString()); + } + } _controller->Start(); _controller->Connect(); } diff --git a/Telegram/SourceFiles/core/crash_report_window.cpp b/Telegram/SourceFiles/core/crash_report_window.cpp index 62365d06c..c43ab21f1 100644 --- a/Telegram/SourceFiles/core/crash_report_window.cpp +++ b/Telegram/SourceFiles/core/crash_report_window.cpp @@ -871,7 +871,8 @@ void LastCrashedWindow::onUpdateSkip() { if (_sendingState == SendingNoReport) { onContinue(); } else { - if (_updatingState == UpdatingCheck || _updatingState == UpdatingDownload) { + if (_updatingState == UpdatingCheck + || _updatingState == UpdatingDownload) { Core::UpdateChecker checker; checker.stop(); setUpdatingState(UpdatingFail); diff --git a/Telegram/SourceFiles/core/utils.cpp b/Telegram/SourceFiles/core/utils.cpp index 4177cf837..b2b0bfee5 100644 --- a/Telegram/SourceFiles/core/utils.cpp +++ b/Telegram/SourceFiles/core/utils.cpp @@ -245,6 +245,10 @@ bool ProxyData::valid() const { return true; } +bool ProxyData::supportsCalls() const { + return (type == Type::Socks5); +} + ProxyData::operator bool() const { return valid(); } diff --git a/Telegram/SourceFiles/core/utils.h b/Telegram/SourceFiles/core/utils.h index d22af06e6..5592b23a2 100644 --- a/Telegram/SourceFiles/core/utils.h +++ b/Telegram/SourceFiles/core/utils.h @@ -434,6 +434,7 @@ struct ProxyData { QString user, password; bool valid() const; + bool supportsCalls() const; explicit operator bool() const; bool operator==(const ProxyData &other) const; bool operator!=(const ProxyData &other) const; diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 90bd0096a..aaed8f099 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -568,6 +568,7 @@ struct Data { std::vector ProxiesList; ProxyData SelectedProxy; bool UseProxy = false; + bool UseProxyForCalls = false; base::Observable ConnectionTypeChanged; int AutoLock = 3600; @@ -692,6 +693,7 @@ DefineVar(Global, bool, TryIPv6); DefineVar(Global, std::vector, ProxiesList); DefineVar(Global, ProxyData, SelectedProxy); DefineVar(Global, bool, UseProxy); +DefineVar(Global, bool, UseProxyForCalls); DefineRefVar(Global, base::Observable, ConnectionTypeChanged); DefineVar(Global, int, AutoLock); diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index 357c28759..add37728c 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -372,10 +372,11 @@ DeclareVar(int, NotificationsCount); DeclareVar(Notify::ScreenCorner, NotificationsCorner); DeclareVar(bool, NotificationsDemoIsShown); +DeclareVar(bool, TryIPv6); DeclareVar(std::vector, ProxiesList); DeclareVar(ProxyData, SelectedProxy); DeclareVar(bool, UseProxy); -DeclareVar(bool, TryIPv6); +DeclareVar(bool, UseProxyForCalls); DeclareRefVar(base::Observable, ConnectionTypeChanged); DeclareVar(int, AutoLock); diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 7d388d659..0e72e2a0b 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -1218,6 +1218,13 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting if (connectionType == dbictProxiesList) { qint32 count = 0, index = 0; stream >> count >> index; + if (std::abs(index) > count) { + Global::SetUseProxyForCalls(true); + index -= (index > 0 ? count : -count); + } else { + Global::SetUseProxyForCalls(false); + } + auto list = std::vector(); for (auto i = 0; i < count; ++i) { const auto proxy = readProxy(); @@ -2485,7 +2492,9 @@ void writeSettings() { data.stream << quint32(dbiConnectionType) << qint32(dbictProxiesList); data.stream << qint32(proxies.size()); - const auto index = qint32(proxyIt - begin(proxies)) + 1; + const auto index = qint32(proxyIt - begin(proxies)) + + qint32(Global::UseProxyForCalls() ? proxies.size() : 0) + + 1; data.stream << (Global::UseProxy() ? index : -index); for (const auto &proxy : proxies) { data.stream << qint32(kProxyTypeShift + int(proxy.type)); diff --git a/Telegram/SourceFiles/ui/widgets/labels.cpp b/Telegram/SourceFiles/ui/widgets/labels.cpp index 494971b0c..d03180c2c 100644 --- a/Telegram/SourceFiles/ui/widgets/labels.cpp +++ b/Telegram/SourceFiles/ui/widgets/labels.cpp @@ -818,4 +818,14 @@ void FlatLabel::paintEvent(QPaintEvent *e) { } } +int DividerLabel::naturalWidth() const { + return -1; +} + +void DividerLabel::resizeEvent(QResizeEvent *e) { + _background->lower(); + _background->setGeometry(rect()); + return PaddingWrap::resizeEvent(e); +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/widgets/labels.h b/Telegram/SourceFiles/ui/widgets/labels.h index 5408fba35..335400c58 100644 --- a/Telegram/SourceFiles/ui/widgets/labels.h +++ b/Telegram/SourceFiles/ui/widgets/labels.h @@ -7,8 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include #include "ui/rp_widget.h" +#include "ui/wrap/padding_wrap.h" +#include "boxes/abstract_box.h" #include "styles/style_widgets.h" namespace Ui { @@ -213,4 +214,19 @@ private: }; +class DividerLabel : public Ui::PaddingWrap { +public: + using PaddingWrap::PaddingWrap; + + int naturalWidth() const override; + +protected: + void resizeEvent(QResizeEvent *e) override; + +private: + object_ptr _background + = object_ptr(this); + +}; + } // namespace Ui diff --git a/Telegram/ThirdParty/libtgvoip b/Telegram/ThirdParty/libtgvoip index 6e0e10261..3d82d03bb 160000 --- a/Telegram/ThirdParty/libtgvoip +++ b/Telegram/ThirdParty/libtgvoip @@ -1 +1 @@ -Subproject commit 6e0e1026147364cfb1234489980a2625ab50b598 +Subproject commit 3d82d03bbb03c0cdb11bcaa399c01a57671044d8