mirror of https://github.com/procxx/kepka.git
Add call peer-to-peer setting in Privacy&Security.
This commit is contained in:
parent
673fea47bd
commit
c4ca180745
|
@ -350,6 +350,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_settings_phone_label" = "Phone number";
|
"lng_settings_phone_label" = "Phone number";
|
||||||
"lng_settings_username_add" = "Add username";
|
"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_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_backgrounds_header" = "Choose your new chat background";
|
||||||
"lng_theme_sure_keep" = "Keep this theme?";
|
"lng_theme_sure_keep" = "Keep this theme?";
|
||||||
|
|
|
@ -73,6 +73,7 @@ QByteArray AuthSessionSettings::serialize() const {
|
||||||
stream << qint32(_variables.thirdColumnWidth.current());
|
stream << qint32(_variables.thirdColumnWidth.current());
|
||||||
stream << qint32(_variables.thirdSectionExtendedBy);
|
stream << qint32(_variables.thirdSectionExtendedBy);
|
||||||
stream << qint32(_variables.sendFilesWay);
|
stream << qint32(_variables.sendFilesWay);
|
||||||
|
stream << qint32(_variables.callsPeerToPeer.current());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -98,6 +99,7 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized)
|
||||||
int thirdColumnWidth = _variables.thirdColumnWidth.current();
|
int thirdColumnWidth = _variables.thirdColumnWidth.current();
|
||||||
int thirdSectionExtendedBy = _variables.thirdSectionExtendedBy;
|
int thirdSectionExtendedBy = _variables.thirdSectionExtendedBy;
|
||||||
qint32 sendFilesWay = static_cast<qint32>(_variables.sendFilesWay);
|
qint32 sendFilesWay = static_cast<qint32>(_variables.sendFilesWay);
|
||||||
|
qint32 callsPeerToPeer = qint32(_variables.callsPeerToPeer.current());
|
||||||
stream >> selectorTab;
|
stream >> selectorTab;
|
||||||
stream >> lastSeenWarningSeen;
|
stream >> lastSeenWarningSeen;
|
||||||
if (!stream.atEnd()) {
|
if (!stream.atEnd()) {
|
||||||
|
@ -146,6 +148,12 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized)
|
||||||
stream >> value;
|
stream >> value;
|
||||||
thirdSectionExtendedBy = value;
|
thirdSectionExtendedBy = value;
|
||||||
}
|
}
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
stream >> sendFilesWay;
|
||||||
|
}
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
stream >> callsPeerToPeer;
|
||||||
|
}
|
||||||
if (stream.status() != QDataStream::Ok) {
|
if (stream.status() != QDataStream::Ok) {
|
||||||
LOG(("App Error: "
|
LOG(("App Error: "
|
||||||
"Bad data for AuthSessionSettings::constructFromSerialized()"));
|
"Bad data for AuthSessionSettings::constructFromSerialized()"));
|
||||||
|
@ -188,7 +196,15 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized)
|
||||||
switch (uncheckedSendFilesWay) {
|
switch (uncheckedSendFilesWay) {
|
||||||
case SendFilesWay::Album:
|
case SendFilesWay::Album:
|
||||||
case SendFilesWay::Photos:
|
case SendFilesWay::Photos:
|
||||||
case SendFilesWay::Files: _variables.sendFilesWay = uncheckedSendFilesWay;
|
case SendFilesWay::Files: _variables.sendFilesWay = uncheckedSendFilesWay; break;
|
||||||
|
}
|
||||||
|
auto uncheckedCallsPeerToPeer = static_cast<Calls::PeerToPeer>(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,10 @@ namespace Data {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
|
namespace Calls {
|
||||||
|
enum class PeerToPeer;
|
||||||
|
} // namespace Calls
|
||||||
|
|
||||||
namespace Storage {
|
namespace Storage {
|
||||||
class Downloader;
|
class Downloader;
|
||||||
class Uploader;
|
class Uploader;
|
||||||
|
@ -144,6 +148,16 @@ public:
|
||||||
_variables.groupStickersSectionHidden.remove(peerId);
|
_variables.groupStickersSectionHidden.remove(peerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<Calls::PeerToPeer> callsPeerToPeerValue() const {
|
||||||
|
return _variables.callsPeerToPeer.value();
|
||||||
|
}
|
||||||
|
Calls::PeerToPeer callsPeerToPeer() const {
|
||||||
|
return _variables.callsPeerToPeer.current();
|
||||||
|
}
|
||||||
|
void setCallsPeerToPeer(Calls::PeerToPeer value) {
|
||||||
|
_variables.callsPeerToPeer = value;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Variables {
|
struct Variables {
|
||||||
Variables();
|
Variables();
|
||||||
|
@ -167,6 +181,8 @@ private:
|
||||||
= kDefaultDialogsWidthRatio; // per-window
|
= kDefaultDialogsWidthRatio; // per-window
|
||||||
rpl::variable<int> thirdColumnWidth
|
rpl::variable<int> thirdColumnWidth
|
||||||
= kDefaultThirdColumnWidth; // per-window
|
= kDefaultThirdColumnWidth; // per-window
|
||||||
|
rpl::variable<Calls::PeerToPeer> callsPeerToPeer
|
||||||
|
= Calls::PeerToPeer();
|
||||||
};
|
};
|
||||||
|
|
||||||
rpl::event_stream<bool> _thirdSectionInfoEnabledValue;
|
rpl::event_stream<bool> _thirdSectionInfoEnabledValue;
|
||||||
|
|
|
@ -14,8 +14,6 @@ class Radiobutton;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
class AutoLockBox : public BoxContent {
|
class AutoLockBox : public BoxContent {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AutoLockBox(QWidget*) {
|
AutoLockBox(QWidget*) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
|
#include "calls/calls_instance.h"
|
||||||
#include "base/binary_guard.h"
|
#include "base/binary_guard.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
@ -347,3 +348,64 @@ void EditPrivacyBox::dataReady(Value &&value) {
|
||||||
createWidgets();
|
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<Ui::RadioenumGroup<PeerToPeer>>(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();
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
|
||||||
|
namespace Calls {
|
||||||
|
enum class PeerToPeer;
|
||||||
|
} // namespace Calls
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class FlatLabel;
|
class FlatLabel;
|
||||||
class LinkButton;
|
class LinkButton;
|
||||||
|
@ -114,3 +118,20 @@ private:
|
||||||
object_ptr<Ui::FlatLabel> _exceptionsDescription = { nullptr };
|
object_ptr<Ui::FlatLabel> _exceptionsDescription = { nullptr };
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EditCallsPeerToPeer : public BoxContent {
|
||||||
|
public:
|
||||||
|
EditCallsPeerToPeer(QWidget*) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void prepare() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using PeerToPeer = Calls::PeerToPeer;
|
||||||
|
|
||||||
|
void chosen(PeerToPeer value);
|
||||||
|
|
||||||
|
std::vector<object_ptr<Ui::Radioenum<PeerToPeer>>> _options;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -572,7 +572,20 @@ void Call::createAndStartController(const MTPDphoneCall &call) {
|
||||||
_controller->SetMicMute(_mute);
|
_controller->SetMicMute(_mute);
|
||||||
}
|
}
|
||||||
_controller->implData = static_cast<void*>(this);
|
_controller->implData = static_cast<void*>(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->SetConfig(config);
|
||||||
_controller->SetEncryptionKey(reinterpret_cast<char*>(_authKey.data()), (_type == Type::Outgoing));
|
_controller->SetEncryptionKey(reinterpret_cast<char*>(_authKey.data()), (_type == Type::Outgoing));
|
||||||
_controller->SetCallbacks(callbacks);
|
_controller->SetCallbacks(callbacks);
|
||||||
|
|
|
@ -18,6 +18,14 @@ class Track;
|
||||||
|
|
||||||
namespace Calls {
|
namespace Calls {
|
||||||
|
|
||||||
|
enum class PeerToPeer {
|
||||||
|
DefaultContacts,
|
||||||
|
DefaultEveryone,
|
||||||
|
Everyone,
|
||||||
|
Contacts,
|
||||||
|
Nobody,
|
||||||
|
};
|
||||||
|
|
||||||
class Panel;
|
class Panel;
|
||||||
|
|
||||||
class Instance : private MTP::Sender, private Call::Delegate, private base::Subscriber {
|
class Instance : private MTP::Sender, private Call::Delegate, private base::Subscriber {
|
||||||
|
|
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "mtproto/rsa_public_key.h"
|
#include "mtproto/rsa_public_key.h"
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
|
#include "calls/calls_instance.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
@ -782,6 +783,18 @@ void Instance::Private::configLoadDone(const MTPConfig &result) {
|
||||||
+ (data.vexpires.v - unixtime()) * TimeMs(1000);
|
+ (data.vexpires.v - unixtime()) * TimeMs(1000);
|
||||||
requestConfigIfExpired();
|
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();
|
emit _instance->configLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
#include "ui/widgets/shadow.h"
|
#include "ui/widgets/shadow.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "calls/calls_instance.h"
|
||||||
#include "core/core_cloud_password.h"
|
#include "core/core_cloud_password.h"
|
||||||
#include "core/update_checker.h"
|
#include "core/update_checker.h"
|
||||||
#include "info/profile/info_profile_button.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<Ui::VerticalLayout*> container) {
|
void SetupPrivacy(not_null<Ui::VerticalLayout*> container) {
|
||||||
AddDivider(container);
|
AddDivider(container);
|
||||||
AddSkip(container);
|
AddSkip(container);
|
||||||
|
@ -71,15 +85,6 @@ void SetupPrivacy(not_null<Ui::VerticalLayout*> container) {
|
||||||
return Auth().api().privacyValue(
|
return Auth().api().privacyValue(
|
||||||
key
|
key
|
||||||
) | rpl::map([](const Privacy &value) {
|
) | 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();
|
auto add = QStringList();
|
||||||
if (const auto never = value.never.size()) {
|
if (const auto never = value.never.size()) {
|
||||||
add.push_back("-" + QString::number(never));
|
add.push_back("-" + QString::number(never));
|
||||||
|
@ -88,9 +93,9 @@ void SetupPrivacy(not_null<Ui::VerticalLayout*> container) {
|
||||||
add.push_back("+" + QString::number(always));
|
add.push_back("+" + QString::number(always));
|
||||||
}
|
}
|
||||||
if (!add.isEmpty()) {
|
if (!add.isEmpty()) {
|
||||||
return lang(base) + " (" + add.join(", ") + ")";
|
return PrivacyBase(value.option) + " (" + add.join(", ") + ")";
|
||||||
} else {
|
} else {
|
||||||
return lang(base);
|
return PrivacyBase(value.option);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -413,6 +418,41 @@ void SetupSecurity(not_null<Ui::VerticalLayout*> container) {
|
||||||
Lang::Viewer(lng_settings_sessions_about));
|
Lang::Viewer(lng_settings_sessions_about));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetupCalls(not_null<Ui::VerticalLayout*> 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<EditCallsPeerToPeer>());
|
||||||
|
});
|
||||||
|
|
||||||
|
AddSkip(container, st::settingsPrivacySecurityPadding);
|
||||||
|
AddDividerText(
|
||||||
|
container,
|
||||||
|
Lang::Viewer(lng_settings_peer_to_peer_about));
|
||||||
|
}
|
||||||
|
|
||||||
void SetupExport(not_null<Ui::VerticalLayout*> container) {
|
void SetupExport(not_null<Ui::VerticalLayout*> container) {
|
||||||
AddSkip(container);
|
AddSkip(container);
|
||||||
|
|
||||||
|
@ -445,6 +485,7 @@ void PrivacySecurity::setupContent() {
|
||||||
AddSkip(content, st::settingsFirstDividerSkip);
|
AddSkip(content, st::settingsFirstDividerSkip);
|
||||||
SetupPrivacy(content);
|
SetupPrivacy(content);
|
||||||
SetupSecurity(content);
|
SetupSecurity(content);
|
||||||
|
SetupCalls(content);
|
||||||
SetupExport(content);
|
SetupExport(content);
|
||||||
|
|
||||||
Ui::ResizeFitChild(this, content);
|
Ui::ResizeFitChild(this, content);
|
||||||
|
|
Loading…
Reference in New Issue