Moved usernames data management to separated class.

This commit is contained in:
23rd 2022-10-14 18:49:40 +03:00 committed by John Preston
parent c8ae7c7402
commit ad70942d0e
12 changed files with 179 additions and 69 deletions

View file

@ -549,6 +549,7 @@ PRIVATE
data/data_user.h data/data_user.h
data/data_user_photos.cpp data/data_user_photos.cpp
data/data_user_photos.h data/data_user_photos.h
data/data_user_names.cpp
data/data_user_names.h data/data_user_names.h
data/data_wall_paper.cpp data/data_wall_paper.cpp
data/data_wall_paper.h data/data_wall_paper.h

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_updates.h" #include "api/api_updates.h"
#include "api/api_authorizations.h" #include "api/api_authorizations.h"
#include "api/api_user_names.h"
#include "api/api_chat_participants.h" #include "api/api_chat_participants.h"
#include "api/api_ringtones.h" #include "api/api_ringtones.h"
#include "api/api_text_entities.h" #include "api/api_text_entities.h"
@ -1888,6 +1889,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
TextUtilities::SingleLine(last), TextUtilities::SingleLine(last),
user->nameOrPhone, user->nameOrPhone,
TextUtilities::SingleLine(username)); TextUtilities::SingleLine(username));
user->setUsernames(Api::Usernames::FromTL(d.vusernames()));
} }
} break; } break;

View file

@ -723,7 +723,7 @@ void Controller::fillPrivacyTypeButton() {
? Privacy::HasUsername ? Privacy::HasUsername
: Privacy::NoUsername), : Privacy::NoUsername),
.username = (_peer->isChannel() .username = (_peer->isChannel()
? _peer->asChannel()->username() ? _peer->asChannel()->editableUsername()
: QString()), : QString()),
.noForwards = !_peer->allowsForwarding(), .noForwards = !_peer->allowsForwarding(),
.joinToWrite = (_peer->isMegagroup() .joinToWrite = (_peer->isMegagroup()
@ -1452,10 +1452,10 @@ void Controller::saveUsernamesOrder() {
_api.request(MTPchannels_DeactivateAllUsernames( _api.request(MTPchannels_DeactivateAllUsernames(
channel->inputChannel channel->inputChannel
)).done([=] { )).done([=] {
channel->setUsernames(channel->username().isEmpty() channel->setUsernames(channel->editableUsername().isEmpty()
? Data::Usernames() ? Data::Usernames()
: Data::Usernames{ : Data::Usernames{
{ channel->username(), true, true } { channel->editableUsername(), true, true }
}); });
continueSave(); continueSave();
}).send(); }).send();
@ -1470,7 +1470,7 @@ void Controller::saveUsernamesOrder() {
newUsernames newUsernames
) | ranges::views::transform([&](QString username) { ) | ranges::views::transform([&](QString username) {
const auto editable = const auto editable =
(channel->username() == username); (channel->editableUsername() == username);
return Data::Username{ return Data::Username{
.username = std::move(username), .username = std::move(username),
.active = true, .active = true,
@ -1485,7 +1485,7 @@ void Controller::saveUsernamesOrder() {
void Controller::saveUsername() { void Controller::saveUsername() {
const auto channel = _peer->asChannel(); const auto channel = _peer->asChannel();
const auto username = (channel ? channel->username() : QString()); const auto username = (channel ? channel->editableUsername() : QString());
if (!_savingData.username || *_savingData.username == username) { if (!_savingData.username || *_savingData.username == username) {
return continueSave(); return continueSave();
} else if (!channel) { } else if (!channel) {
@ -1583,7 +1583,9 @@ void Controller::saveTitle() {
if (type == qstr("CHAT_NOT_MODIFIED") if (type == qstr("CHAT_NOT_MODIFIED")
|| type == qstr("CHAT_TITLE_NOT_MODIFIED")) { || type == qstr("CHAT_TITLE_NOT_MODIFIED")) {
if (const auto channel = _peer->asChannel()) { if (const auto channel = _peer->asChannel()) {
channel->setName(*_savingData.title, channel->username()); channel->setName(
*_savingData.title,
channel->editableUsername());
} else if (const auto chat = _peer->asChat()) { } else if (const auto chat = _peer->asChat()) {
chat->setName(*_savingData.title); chat->setName(*_savingData.title);
} }

View file

@ -176,7 +176,7 @@ Controller::Controller(
, _isGroup(_peer->isChat() || _peer->isMegagroup()) , _isGroup(_peer->isChat() || _peer->isMegagroup())
, _goodUsername(_dataSavedValue , _goodUsername(_dataSavedValue
? !_dataSavedValue->username.isEmpty() ? !_dataSavedValue->username.isEmpty()
: (_peer->isChannel() && !_peer->asChannel()->username().isEmpty())) : (_peer->isChannel() && !_peer->asChannel()->editableUsername().isEmpty()))
, _wrap(container) , _wrap(container)
, _checkUsernameTimer([=] { checkUsernameAvailability(); }) { , _checkUsernameTimer([=] { checkUsernameAvailability(); }) {
_peer->updateFull(); _peer->updateFull();
@ -400,7 +400,7 @@ object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
const auto channel = _peer->asChannel(); const auto channel = _peer->asChannel();
const auto username = (!_dataSavedValue || !channel) const auto username = (!_dataSavedValue || !channel)
? QString() ? QString()
: channel->username(); : channel->editableUsername();
auto result = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>( auto result = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
_wrap, _wrap,
@ -530,7 +530,7 @@ void Controller::checkUsernameAvailability() {
_api.request(_checkUsernameRequestId).cancel(); _api.request(_checkUsernameRequestId).cancel();
} }
const auto channel = _peer->migrateToOrMe()->asChannel(); const auto channel = _peer->migrateToOrMe()->asChannel();
const auto username = channel ? channel->username() : QString(); const auto username = channel ? channel->editableUsername() : QString();
_checkUsernameRequestId = _api.request(MTPchannels_CheckUsername( _checkUsernameRequestId = _api.request(MTPchannels_CheckUsername(
channel ? channel->inputChannel : MTP_inputChannelEmpty(), channel ? channel->inputChannel : MTP_inputChannelEmpty(),
MTP_string(checking) MTP_string(checking)

View file

@ -79,10 +79,10 @@ UsernameEditor::UsernameEditor(
this, this,
st::defaultInputField, st::defaultInputField,
rpl::single(qsl("@username")), rpl::single(qsl("@username")),
session->user()->username(), session->user()->editableUsername(),
QString()) QString())
, _checkTimer([=] { check(); }) { , _checkTimer([=] { check(); }) {
_goodText = _session->user()->username().isEmpty() _goodText = _session->user()->editableUsername().isEmpty()
? QString() ? QString()
: tr::lng_username_available(tr::now); : tr::lng_username_available(tr::now);
@ -183,7 +183,7 @@ void UsernameEditor::check() {
_checkRequestId = 0; _checkRequestId = 0;
_errorText = (mtpIsTrue(result) _errorText = (mtpIsTrue(result)
|| _checkUsername == _session->user()->username()) || _checkUsername == _session->user()->editableUsername())
? QString() ? QString()
: tr::lng_username_occupied(tr::now); : tr::lng_username_occupied(tr::now);
_goodText = _errorText.isEmpty() _goodText = _errorText.isEmpty()
@ -241,7 +241,7 @@ void UsernameEditor::changed() {
void UsernameEditor::updateFail(const QString &error) { void UsernameEditor::updateFail(const QString &error) {
const auto self = _session->user(); const auto self = _session->user();
if ((error == qstr("USERNAME_NOT_MODIFIED")) if ((error == qstr("USERNAME_NOT_MODIFIED"))
|| (_sentUsername == self->username())) { || (_sentUsername == self->editableUsername())) {
self->setName( self->setName(
TextUtilities::SingleLine(self->firstName), TextUtilities::SingleLine(self->firstName),
TextUtilities::SingleLine(self->lastName), TextUtilities::SingleLine(self->lastName),
@ -269,7 +269,7 @@ void UsernameEditor::checkFail(const QString &error) {
_errorText = tr::lng_username_invalid(tr::now); _errorText = tr::lng_username_invalid(tr::now);
update(); update();
} else if ((error == qstr("USERNAME_OCCUPIED")) } else if ((error == qstr("USERNAME_OCCUPIED"))
&& (_checkUsername != _session->user()->username())) { && (_checkUsername != _session->user()->editableUsername())) {
_errorText = tr::lng_username_occupied(tr::now); _errorText = tr::lng_username_occupied(tr::now);
update(); update();
} else { } else {

View file

@ -103,32 +103,36 @@ void ChannelData::setName(
} }
void ChannelData::setUsername(const QString &username) { void ChannelData::setUsername(const QString &username) {
if (_username != username) { _username.setUsername(username);
_username = username;
}
} }
void ChannelData::setUsernames(const Data::Usernames &usernames) { void ChannelData::setUsernames(const Data::Usernames &newUsernames) {
auto newUsernames = ranges::views::all( const auto wasUsername = username();
usernames const auto wasUsernames = usernames();
) | ranges::views::filter([&](const Data::Username &username) { _username.setUsernames(newUsernames);
return username.active; const auto nowUsername = username();
}) | ranges::views::transform([&](const Data::Username &username) { const auto nowUsernames = usernames();
return username.username; session().changes().peerUpdated(
}) | ranges::to_vector; this,
UpdateFlag()
if (!ranges::equal(_usernames, newUsernames)) { | ((wasUsername != nowUsername)
_usernames = std::move(newUsernames); ? UpdateFlag::Username
session().changes().peerUpdated(this, UpdateFlag::Usernames); : UpdateFlag())
} | (!ranges::equal(wasUsernames, nowUsernames)
? UpdateFlag::Usernames
: UpdateFlag()));
} }
QString ChannelData::username() const { QString ChannelData::username() const {
return _username; return _username.username();
}
QString ChannelData::editableUsername() const {
return _username.editableUsername();
} }
const std::vector<QString> &ChannelData::usernames() const { const std::vector<QString> &ChannelData::usernames() const {
return _usernames; return _username.usernames();
} }
void ChannelData::setAccessHash(uint64 accessHash) { void ChannelData::setAccessHash(uint64 accessHash) {

View file

@ -12,10 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_location.h" #include "data/data_location.h"
#include "data/data_chat_participant_status.h" #include "data/data_chat_participant_status.h"
#include "data/data_peer_bot_commands.h" #include "data/data_peer_bot_commands.h"
#include "data/data_user_names.h"
namespace Data {
struct Username;
} // namespace Data
struct ChannelLocation { struct ChannelLocation {
QString address; QString address;
@ -151,7 +148,7 @@ public:
void setName(const QString &name, const QString &username); void setName(const QString &name, const QString &username);
void setUsername(const QString &username); void setUsername(const QString &username);
void setUsernames(const std::vector<Data::Username> &usernames); void setUsernames(const Data::Usernames &newUsernames);
void setPhoto(const MTPChatPhoto &photo); void setPhoto(const MTPChatPhoto &photo);
void setAccessHash(uint64 accessHash); void setAccessHash(uint64 accessHash);
@ -166,6 +163,7 @@ public:
} }
[[nodiscard]] QString username() const; [[nodiscard]] QString username() const;
[[nodiscard]] QString editableUsername() const;
[[nodiscard]] const std::vector<QString> &usernames() const; [[nodiscard]] const std::vector<QString> &usernames() const;
[[nodiscard]] int membersCount() const { [[nodiscard]] int membersCount() const {
@ -466,8 +464,7 @@ private:
PtsWaiter _ptsWaiter; PtsWaiter _ptsWaiter;
QString _username; Data::UsernamesInfo _username;
std::vector<QString> _usernames;
int _membersCount = -1; int _membersCount = -1;
int _adminsCount = 1; int _adminsCount = 1;

View file

@ -198,11 +198,11 @@ void PeerData::updateNameDelayed(
if (_name == newName && _nameVersion > 1) { if (_name == newName && _nameVersion > 1) {
if (isUser()) { if (isUser()) {
if (asUser()->nameOrPhone == newNameOrPhone if (asUser()->nameOrPhone == newNameOrPhone
&& asUser()->username() == newUsername) { && asUser()->editableUsername() == newUsername) {
return; return;
} }
} else if (isChannel()) { } else if (isChannel()) {
if (asChannel()->username() == newUsername) { if (asChannel()->editableUsername() == newUsername) {
return; return;
} }
} else if (isChat()) { } else if (isChat()) {
@ -220,15 +220,15 @@ void PeerData::updateNameDelayed(
flags |= UpdateFlag::Name; flags |= UpdateFlag::Name;
} }
if (isUser()) { if (isUser()) {
if (asUser()->username() != newUsername) { if (asUser()->editableUsername() != newUsername) {
asUser()->setUsername(newUsername); asUser()->setUsername(newUsername);
flags |= UpdateFlag::Username; flags |= UpdateFlag::Username;
} }
asUser()->setNameOrPhone(newNameOrPhone); asUser()->setNameOrPhone(newNameOrPhone);
} else if (isChannel()) { } else if (isChannel()) {
if (asChannel()->username() != newUsername) { if (asChannel()->editableUsername() != newUsername) {
asChannel()->setUsername(newUsername); asChannel()->setUsername(newUsername);
if (newUsername.isEmpty()) { if (asChannel()->username().isEmpty()) {
asChannel()->removeFlags(ChannelDataFlag::Username); asChannel()->removeFlags(ChannelDataFlag::Username);
} else { } else {
asChannel()->addFlags(ChannelDataFlag::Username); asChannel()->addFlags(ChannelDataFlag::Username);

View file

@ -120,25 +120,25 @@ void UserData::setName(const QString &newFirstName, const QString &newLastName,
updateNameDelayed(newFullName, newPhoneName, newUsername); updateNameDelayed(newFullName, newPhoneName, newUsername);
} }
void UserData::setUsernames(const Data::Usernames &usernames) { void UserData::setUsernames(const Data::Usernames &newUsernames) {
auto newUsernames = ranges::views::all( const auto wasUsername = username();
usernames const auto wasUsernames = usernames();
) | ranges::views::filter([&](const Data::Username &username) { _username.setUsernames(newUsernames);
return username.active; const auto nowUsername = username();
}) | ranges::views::transform([&](const Data::Username &username) { const auto nowUsernames = usernames();
return username.username; session().changes().peerUpdated(
}) | ranges::to_vector; this,
UpdateFlag()
if (!ranges::equal(_usernames, newUsernames)) { | ((wasUsername != nowUsername)
_usernames = std::move(newUsernames); ? UpdateFlag::Username
session().changes().peerUpdated(this, UpdateFlag::Usernames); : UpdateFlag())
} | (!ranges::equal(wasUsernames, nowUsernames)
? UpdateFlag::Usernames
: UpdateFlag()));
} }
void UserData::setUsername(const QString &username) { void UserData::setUsername(const QString &username) {
if (_username != username) { _username.setUsername(username);
_username = username;
}
} }
void UserData::setPhone(const QString &newPhone) { void UserData::setPhone(const QString &newPhone) {
@ -303,12 +303,16 @@ bool UserData::canShareThisContactFast() const {
return !_phone.isEmpty(); return !_phone.isEmpty();
} }
const QString &UserData::username() const { QString UserData::username() const {
return _username; return _username.username();
}
QString UserData::editableUsername() const {
return _username.editableUsername();;
} }
const std::vector<QString> &UserData::usernames() const { const std::vector<QString> &UserData::usernames() const {
return _usernames; return _username.usernames();
} }
const QString &UserData::phone() const { const QString &UserData::phone() const {

View file

@ -9,11 +9,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer.h" #include "data/data_peer.h"
#include "data/data_chat_participant_status.h" #include "data/data_chat_participant_status.h"
#include "data/data_user_names.h"
#include "dialogs/dialogs_key.h" #include "dialogs/dialogs_key.h"
namespace Data { namespace Data {
struct BotCommand; struct BotCommand;
struct Username;
} // namespace Data } // namespace Data
struct BotInfo { struct BotInfo {
@ -74,7 +74,7 @@ public:
const QString &newLastName, const QString &newLastName,
const QString &newPhoneName, const QString &newPhoneName,
const QString &newUsername); const QString &newUsername);
void setUsernames(const std::vector<Data::Username> &usernames); void setUsernames(const Data::Usernames &newUsernames);
void setEmojiStatus(DocumentId emojiStatusId, TimeId until = 0); void setEmojiStatus(DocumentId emojiStatusId, TimeId until = 0);
[[nodiscard]] DocumentId emojiStatusId() const; [[nodiscard]] DocumentId emojiStatusId() const;
@ -130,7 +130,8 @@ public:
QString firstName; QString firstName;
QString lastName; QString lastName;
[[nodiscard]] const QString &phone() const; [[nodiscard]] const QString &phone() const;
[[nodiscard]] const QString &username() const; [[nodiscard]] QString username() const;
[[nodiscard]] QString editableUsername() const;
[[nodiscard]] const std::vector<QString> &usernames() const; [[nodiscard]] const std::vector<QString> &usernames() const;
QString nameOrPhone; QString nameOrPhone;
TimeId onlineTill = 0; TimeId onlineTill = 0;
@ -168,15 +169,14 @@ private:
Flags _flags; Flags _flags;
Data::UsernamesInfo _username;
std::vector<Data::UnavailableReason> _unavailableReasons; std::vector<Data::UnavailableReason> _unavailableReasons;
QString _username;
QString _phone; QString _phone;
ContactStatus _contactStatus = ContactStatus::Unknown; ContactStatus _contactStatus = ContactStatus::Unknown;
CallsStatus _callsStatus = CallsStatus::Unknown; CallsStatus _callsStatus = CallsStatus::Unknown;
int _commonChatsCount = 0; int _commonChatsCount = 0;
std::vector<QString> _usernames;
uint64 _accessHash = 0; uint64 _accessHash = 0;
static constexpr auto kInaccessibleAccessHashOld static constexpr auto kInaccessibleAccessHashOld
= 0xFFFFFFFFFFFFFFFFULL; = 0xFFFFFFFFFFFFFFFFULL;

View file

@ -0,0 +1,83 @@
/*
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 "data/data_user_names.h"
namespace Data {
UsernamesInfo::UsernamesInfo() = default;
void UsernamesInfo::setUsername(const QString &username) {
if (_usernames.empty()) {
if (username.isEmpty()) {
_indexEditableUsername = -1;
} else {
_usernames.push_back(username);
_indexEditableUsername = 0;
}
} else if ((_indexEditableUsername < 0)
|| (_indexEditableUsername >= _usernames.size())) {
if (username.isEmpty()) {
_indexEditableUsername = -1;
} else {
_usernames.push_back(username);
_indexEditableUsername = 0;
}
} else if (_usernames[_indexEditableUsername] != username) {
if (username.isEmpty()) {
_usernames.erase(begin(_usernames) + _indexEditableUsername);
_indexEditableUsername = -1;
} else {
_usernames[_indexEditableUsername] = username;
}
}
}
void UsernamesInfo::setUsernames(const Usernames &usernames) {
auto editableUsername = QString();
auto newUsernames = ranges::views::all(
usernames
) | ranges::views::filter([&](const Data::Username &username) {
if (username.editable) {
editableUsername = username.username;
return true;
}
return username.active;
}) | ranges::views::transform([](const Data::Username &username) {
return username.username;
}) | ranges::to_vector;
if (!ranges::equal(_usernames, newUsernames)) {
_usernames = std::move(newUsernames);
}
if (!editableUsername.isEmpty()) {
for (auto i = 0; i < _usernames.size(); i++) {
if (_usernames[i] == editableUsername) {
_indexEditableUsername = i;
break;
}
}
} else {
_indexEditableUsername = -1;
}
}
QString UsernamesInfo::username() const {
return _usernames.empty() ? QString() : _usernames.front();
}
QString UsernamesInfo::editableUsername() const {
return (_indexEditableUsername < 0)
? QString()
: _usernames[_indexEditableUsername];
}
const std::vector<QString> &UsernamesInfo::usernames() const {
return _usernames;
}
} // namespace Data

View file

@ -17,4 +17,21 @@ struct Username final {
using Usernames = std::vector<Username>; using Usernames = std::vector<Username>;
class UsernamesInfo final {
public:
UsernamesInfo();
void setUsername(const QString &username);
void setUsernames(const Usernames &usernames);
[[nodiscard]] QString username() const;
[[nodiscard]] QString editableUsername() const;
[[nodiscard]] const std::vector<QString> &usernames() const;
private:
std::vector<QString> _usernames;
short _indexEditableUsername = -1;
};
} // namespace Data } // namespace Data