diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 4859d3065e..df03deaf63 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -699,6 +699,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_settings_reset_sure" = "Are you sure you want to terminate\nall other sessions?"; "lng_settings_reset_one_sure" = "Do you want to terminate this session?"; "lng_settings_reset_button" = "Terminate"; +"lng_settings_rename_device" = "Rename"; +"lng_settings_device_name" = "Device name ({device})"; +"lng_settings_rename_device_title" = "Rename current device"; "lng_settings_manage_local_storage" = "Manage local storage"; "lng_settings_ask_question" = "Ask a Question"; "lng_settings_ask_sure" = "Please note that Telegram Support is run by volunteers. We try to respond as quickly as possible, but it may take a while.\n\nPlease take a look at the Telegram FAQ: it has important troubleshooting tips and answers to most questions."; diff --git a/Telegram/SourceFiles/api/api_authorizations.cpp b/Telegram/SourceFiles/api/api_authorizations.cpp index 2293c1e8ae..c645cb8cd5 100644 --- a/Telegram/SourceFiles/api/api_authorizations.cpp +++ b/Telegram/SourceFiles/api/api_authorizations.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "base/unixtime.h" #include "core/changelogs.h" +#include "core/application.h" #include "lang/lang_keys.h" namespace Api { @@ -46,7 +47,9 @@ Authorizations::Entry ParseEntry(const MTPDauthorization &data) { return version; }(); - result.name = qs(data.vdevice_model()); + result.name = result.hash + ? qs(data.vdevice_model()) + : Core::App().settings().deviceModel(); const auto country = qs(data.vcountry()); //const auto platform = qs(data.vplatform()); @@ -91,6 +94,19 @@ Authorizations::Entry ParseEntry(const MTPDauthorization &data) { Authorizations::Authorizations(not_null api) : _api(&api->instance()) { + Core::App().settings().deviceModelChanges( + ) | rpl::start_with_next([=](const QString &model) { + auto changed = false; + for (auto &entry : _list) { + if (!entry.hash) { + entry.name = model; + changed = true; + } + } + if (changed) { + _listChanges.fire({}); + } + }, _lifetime); } void Authorizations::reload() { diff --git a/Telegram/SourceFiles/api/api_authorizations.h b/Telegram/SourceFiles/api/api_authorizations.h index f571402d02..d84de71157 100644 --- a/Telegram/SourceFiles/api/api_authorizations.h +++ b/Telegram/SourceFiles/api/api_authorizations.h @@ -48,6 +48,7 @@ private: rpl::event_stream<> _listChanges; crl::time _lastReceived = 0; + rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/boxes/sessions_box.cpp b/Telegram/SourceFiles/boxes/sessions_box.cpp index 0d4242a337..3941c58028 100644 --- a/Telegram/SourceFiles/boxes/sessions_box.cpp +++ b/Telegram/SourceFiles/boxes/sessions_box.cpp @@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_authorizations.h" #include "base/timer.h" #include "base/unixtime.h" +#include "base/algorithm.h" +#include "base/platform/base_platform_info.h" #include "ui/boxes/confirm_box.h" #include "lang/lang_keys.h" #include "main/main_session.h" @@ -19,15 +21,46 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_layers.h" #include "styles/style_settings.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/input_fields.h" #include "ui/widgets/labels.h" #include "ui/widgets/scroll_area.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" +#include "ui/layers/generic_box.h" +#include "core/application.h" +#include "core/core_settings.h" #include "window/window_session_controller.h" namespace { constexpr auto kSessionsShortPollTimeout = 60 * crl::time(1000); +constexpr auto kMaxDeviceModelLength = 16; + +void RenameBox(not_null box) { + box->setTitle(tr::lng_settings_rename_device_title()); + + const auto name = box->addRow(object_ptr( + box, + st::defaultInputField, + tr::lng_settings_device_name( + lt_device, + rpl::single(Platform::DeviceModelPretty())), + Core::App().settings().customDeviceModel())); + name->setMaxLength(kMaxDeviceModelLength); + box->setFocusCallback([=] { + name->setFocusFast(); + }); + const auto submit = [=] { + const auto result = base::CleanAndSimplify( + name->getLastText()); + box->closeBox(); + Core::App().settings().setCustomDeviceModel(result); + Core::App().saveSettingsDelayed(); + }; + QObject::connect(name, &Ui::InputField::submitted, submit); + box->addButton(tr::lng_settings_save(), submit); + box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); +} } // namespace @@ -107,10 +140,11 @@ private: int available = 0; int info = 0; }; - RowWidth _rowWidth; + void subscribeToCustomDeviceModel(); void computeRowWidth(); + RowWidth _rowWidth; std::vector _items; std::map> _terminateButtons; rpl::event_stream _terminate; @@ -125,6 +159,7 @@ public: void showData(const Full &data); rpl::producer terminateOne() const; rpl::producer<> terminateAll() const; + rpl::producer<> renameCurrentRequests() const; void terminatingOne(uint64 hash, bool terminating); @@ -312,7 +347,28 @@ void SessionsContent::Inner::setupContent() { const auto content = Ui::CreateChild(this); - AddSubsectionTitle(content, tr::lng_sessions_header()); + const auto header = AddSubsectionTitle( + content, + tr::lng_sessions_header()); + const auto rename = Ui::CreateChild( + content, + tr::lng_settings_rename_device(tr::now), + st::defaultLinkButton); + rpl::combine( + content->sizeValue(), + header->positionValue() + ) | rpl::start_with_next([=](QSize outer, QPoint position) { + const auto x = st::sessionTerminateSkip + + st::sessionTerminate.iconPosition.x(); + const auto y = st::settingsSubsectionTitlePadding.top() + + st::settingsSubsectionTitle.style.font->ascent + - st::defaultLinkButton.font->ascent; + rename->moveToRight(x, y, outer.width()); + }, rename->lifetime()); + rename->setClickedCallback([=] { + Ui::show(Box(RenameBox), Ui::LayerOption::KeepOther); + }); + _current = content->add(object_ptr(content)); const auto terminateWrap = content->add( object_ptr>( @@ -400,6 +456,18 @@ void SessionsContent::List::resizeEvent(QResizeEvent *e) { computeRowWidth(); } +void SessionsContent::List::subscribeToCustomDeviceModel() { + Core::App().settings().deviceModelChanges( + ) | rpl::start_with_next([=](const QString &model) { + for (auto &entry : _items) { + if (!entry.hash) { + entry.name.setText(st::sessionNameStyle, model); + } + } + update(); + }, lifetime()); +} + void SessionsContent::List::showData(gsl::span items) { computeRowWidth(); diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index a0124b6a6a..05eeab2548 100644 --- a/Telegram/SourceFiles/core/core_settings.cpp +++ b/Telegram/SourceFiles/core/core_settings.cpp @@ -124,7 +124,8 @@ QByteArray Settings::serialize() const { + Serialize::bytearraySize(proxy) + sizeof(qint32) * 2 + Serialize::bytearraySize(_photoEditorBrush) - + sizeof(qint32); + + sizeof(qint32) * 3 + + Serialize::stringSize(_customDeviceModel.current()); auto result = QByteArray(); result.reserve(size); @@ -221,7 +222,8 @@ QByteArray Settings::serialize() const { << _photoEditorBrush << qint32(_groupCallNoiseSuppression ? 1 : 0) << qint32(_voicePlaybackSpeed * 100) - << qint32(_closeToTaskbar.current() ? 1 : 0); + << qint32(_closeToTaskbar.current() ? 1 : 0) + << _customDeviceModel.current(); } return result; } @@ -305,6 +307,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) { qint32 hiddenGroupCallTooltips = qint32(_hiddenGroupCallTooltips.value()); QByteArray photoEditorBrush = _photoEditorBrush; qint32 closeToTaskbar = _closeToTaskbar.current() ? 1 : 0; + QString customDeviceModel = _customDeviceModel.current(); stream >> themesAccentColors; if (!stream.atEnd()) { @@ -465,6 +468,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) { if (!stream.atEnd()) { stream >> closeToTaskbar; } + if (!stream.atEnd()) { + stream >> customDeviceModel; + } if (stream.status() != QDataStream::Ok) { LOG(("App Error: " "Bad data for Core::Settings::constructFromSerialized()")); @@ -606,6 +612,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) { }(); _photoEditorBrush = photoEditorBrush; _closeToTaskbar = (closeToTaskbar == 1); + _customDeviceModel = customDeviceModel; } QString Settings::getSoundPath(const QString &key) const { @@ -672,6 +679,23 @@ void Settings::setThirdColumnWidth(int width) { _thirdColumnWidth = width; } +QString Settings::deviceModel() const { + const auto custom = customDeviceModel(); + return custom.isEmpty() ? Platform::DeviceModelPretty() : custom; +} + +rpl::producer Settings::deviceModelChanges() const { + return customDeviceModelChanges() | rpl::map([=] { + return deviceModel(); + }); +} + +rpl::producer Settings::deviceModelValue() const { + return customDeviceModelValue() | rpl::map([=] { + return deviceModel(); + }); +} + int Settings::thirdColumnWidth() const { return _thirdColumnWidth.current(); } diff --git a/Telegram/SourceFiles/core/core_settings.h b/Telegram/SourceFiles/core/core_settings.h index f8a26f04d1..8de40b6a31 100644 --- a/Telegram/SourceFiles/core/core_settings.h +++ b/Telegram/SourceFiles/core/core_settings.h @@ -614,6 +614,22 @@ public: return _closeToTaskbar.changes(); } + void setCustomDeviceModel(const QString &model) { + _customDeviceModel = model; + } + [[nodiscard]] QString customDeviceModel() const { + return _customDeviceModel.current(); + } + [[nodiscard]] rpl::producer customDeviceModelChanges() const { + return _customDeviceModel.changes(); + } + [[nodiscard]] rpl::producer customDeviceModelValue() const { + return _customDeviceModel.value(); + } + [[nodiscard]] QString deviceModel() const; + [[nodiscard]] rpl::producer deviceModelChanges() const; + [[nodiscard]] rpl::producer deviceModelValue() const; + [[nodiscard]] static bool ThirdColumnByDefault(); [[nodiscard]] static float64 DefaultDialogsWidthRatio(); [[nodiscard]] static qint32 SerializePlaybackSpeed(float64 speed) { @@ -714,6 +730,7 @@ private: rpl::variable _workMode = WorkMode::WindowAndTray; base::flags _hiddenGroupCallTooltips; rpl::variable _closeToTaskbar = false; + rpl::variable _customDeviceModel; bool _tabbedReplacedWithInfo = false; // per-window rpl::event_stream _tabbedReplacedWithInfoValue; // per-window diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.cpp b/Telegram/SourceFiles/mtproto/mtp_instance.cpp index 3d8439d613..457a60a76b 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_instance.cpp @@ -224,9 +224,12 @@ private: std::unique_ptr _otherSessionsThread; std::vector> _fileSessionThreads; - QString _deviceModel; + QString _deviceModelDefault; QString _systemVersion; + mutable QMutex _deviceModelMutex; + QString _customDeviceModel; + rpl::variable _mainDcId = Fields::kDefaultMainDc; bool _mainDcIdForced = false; base::flat_map> _dcenters; @@ -321,9 +324,19 @@ Instance::Private::Private( restart(); }, _lifetime); - _deviceModel = std::move(fields.deviceModel); + _deviceModelDefault = std::move(fields.deviceModel); _systemVersion = std::move(fields.systemVersion); + _customDeviceModel = Core::App().settings().customDeviceModel(); + Core::App().settings().customDeviceModelChanges( + ) | rpl::start_with_next([=](const QString &value) { + QMutexLocker lock(&_deviceModelMutex); + _customDeviceModel = value; + lock.unlock(); + + reInitConnection(mainDcId()); + }, _lifetime); + for (auto &key : fields.keys) { auto dcId = key->dcId(); auto shiftedDcId = dcId; @@ -874,7 +887,10 @@ bool Instance::Private::isTestMode() const { } QString Instance::Private::deviceModel() const { - return _deviceModel; + QMutexLocker lock(&_deviceModelMutex); + return _customDeviceModel.isEmpty() + ? _deviceModelDefault + : _customDeviceModel; } QString Instance::Private::systemVersion() const {