2019-06-10 15:47:22 +00:00
|
|
|
/*
|
|
|
|
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
|
|
|
|
*/
|
2019-06-12 14:13:49 +00:00
|
|
|
#include "boxes/peers/edit_contact_box.h"
|
2019-06-10 15:47:22 +00:00
|
|
|
|
|
|
|
#include "data/data_user.h"
|
|
|
|
#include "data/data_session.h"
|
|
|
|
#include "ui/wrap/vertical_layout.h"
|
|
|
|
#include "ui/widgets/labels.h"
|
|
|
|
#include "ui/widgets/input_fields.h"
|
2019-06-12 13:26:04 +00:00
|
|
|
#include "ui/text/text_utilities.h"
|
2019-06-10 15:47:22 +00:00
|
|
|
#include "info/profile/info_profile_cover.h"
|
|
|
|
#include "lang/lang_keys.h"
|
|
|
|
#include "window/window_controller.h"
|
2019-06-12 13:26:04 +00:00
|
|
|
#include "ui/toast/toast.h"
|
2019-07-24 11:45:24 +00:00
|
|
|
#include "main/main_session.h"
|
2019-06-10 15:47:22 +00:00
|
|
|
#include "apiwrap.h"
|
2019-09-13 06:06:02 +00:00
|
|
|
#include "app.h"
|
2019-09-18 11:19:05 +00:00
|
|
|
#include "styles/style_layers.h"
|
2019-06-10 15:47:22 +00:00
|
|
|
#include "styles/style_boxes.h"
|
|
|
|
#include "styles/style_info.h"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2019-09-27 16:46:27 +00:00
|
|
|
constexpr auto kMaxUserFirstLastName = 64; // See also add_contact_box.
|
|
|
|
|
2019-06-10 15:47:22 +00:00
|
|
|
QString UserPhone(not_null<UserData*> user) {
|
|
|
|
const auto phone = user->phone();
|
|
|
|
return phone.isEmpty()
|
|
|
|
? user->owner().findContactPhone(user->bareId())
|
|
|
|
: phone;
|
|
|
|
}
|
|
|
|
|
2019-06-24 08:07:32 +00:00
|
|
|
void SendRequest(
|
2019-09-18 11:19:05 +00:00
|
|
|
QPointer<Ui::GenericBox> box,
|
2019-06-24 08:07:32 +00:00
|
|
|
not_null<UserData*> user,
|
|
|
|
bool sharePhone,
|
|
|
|
const QString &first,
|
|
|
|
const QString &last,
|
|
|
|
const QString &phone) {
|
|
|
|
const auto wasContact = user->isContact();
|
|
|
|
using Flag = MTPcontacts_AddContact::Flag;
|
|
|
|
user->session().api().request(MTPcontacts_AddContact(
|
|
|
|
MTP_flags(sharePhone
|
|
|
|
? Flag::f_add_phone_privacy_exception
|
|
|
|
: Flag(0)),
|
|
|
|
user->inputUser,
|
|
|
|
MTP_string(first),
|
|
|
|
MTP_string(last),
|
|
|
|
MTP_string(phone)
|
|
|
|
)).done([=](const MTPUpdates &result) {
|
|
|
|
user->setName(
|
|
|
|
first,
|
|
|
|
last,
|
|
|
|
user->nameOrPhone,
|
|
|
|
user->username);
|
|
|
|
user->session().api().applyUpdates(result);
|
|
|
|
if (const auto settings = user->settings()) {
|
|
|
|
using Flag = MTPDpeerSettings::Flag;
|
|
|
|
const auto flags = Flag::f_add_contact
|
|
|
|
| Flag::f_block_contact
|
|
|
|
| Flag::f_report_spam;
|
|
|
|
user->setSettings(*settings & ~flags);
|
|
|
|
}
|
|
|
|
if (box) {
|
|
|
|
box->closeBox();
|
|
|
|
}
|
|
|
|
if (!wasContact) {
|
|
|
|
Ui::Toast::Show(tr::lng_new_contact_add_done(
|
|
|
|
tr::now,
|
|
|
|
lt_user,
|
|
|
|
first));
|
|
|
|
}
|
|
|
|
}).fail([=](const RPCError &error) {
|
|
|
|
}).send();
|
|
|
|
}
|
|
|
|
|
2019-06-15 14:29:40 +00:00
|
|
|
class Controller {
|
2019-06-12 14:13:49 +00:00
|
|
|
public:
|
2019-06-15 14:29:40 +00:00
|
|
|
Controller(
|
2019-09-18 11:19:05 +00:00
|
|
|
not_null<Ui::GenericBox*> box,
|
2020-06-23 17:21:58 +00:00
|
|
|
not_null<Window::SessionController*> window,
|
2019-06-12 14:13:49 +00:00
|
|
|
not_null<UserData*> user);
|
|
|
|
|
2019-06-15 14:29:40 +00:00
|
|
|
void prepare();
|
2019-06-12 14:13:49 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
void setupContent();
|
|
|
|
void setupCover();
|
|
|
|
void setupNameFields();
|
|
|
|
void setupWarning();
|
2019-06-15 14:29:40 +00:00
|
|
|
void setupSharePhoneNumber();
|
2019-06-12 14:13:49 +00:00
|
|
|
void initNameFields(
|
|
|
|
not_null<Ui::InputField*> first,
|
|
|
|
not_null<Ui::InputField*> last,
|
|
|
|
bool inverted);
|
|
|
|
|
2019-09-18 11:19:05 +00:00
|
|
|
not_null<Ui::GenericBox*> _box;
|
2020-06-23 17:21:58 +00:00
|
|
|
not_null<Window::SessionController*> _window;
|
2019-06-12 14:13:49 +00:00
|
|
|
not_null<UserData*> _user;
|
2019-06-15 14:29:40 +00:00
|
|
|
Ui::Checkbox *_sharePhone = nullptr;
|
2019-06-12 14:13:49 +00:00
|
|
|
QString _phone;
|
|
|
|
Fn<void()> _focus;
|
|
|
|
Fn<void()> _save;
|
2019-06-10 15:47:22 +00:00
|
|
|
|
2019-06-12 14:13:49 +00:00
|
|
|
};
|
|
|
|
|
2019-06-15 14:29:40 +00:00
|
|
|
Controller::Controller(
|
2019-09-18 11:19:05 +00:00
|
|
|
not_null<Ui::GenericBox*> box,
|
2020-06-23 17:21:58 +00:00
|
|
|
not_null<Window::SessionController*> window,
|
2019-06-10 15:47:22 +00:00
|
|
|
not_null<UserData*> user)
|
2019-06-12 14:13:49 +00:00
|
|
|
: _box(box)
|
|
|
|
, _window(window)
|
2019-06-10 15:47:22 +00:00
|
|
|
, _user(user)
|
|
|
|
, _phone(UserPhone(user)) {
|
|
|
|
}
|
|
|
|
|
2019-06-15 14:29:40 +00:00
|
|
|
void Controller::prepare() {
|
2019-06-10 15:47:22 +00:00
|
|
|
setupContent();
|
|
|
|
|
2019-06-18 15:00:55 +00:00
|
|
|
_box->setTitle(_user->isContact()
|
|
|
|
? tr::lng_edit_contact_title()
|
|
|
|
: tr::lng_enter_contact_data());
|
2019-06-10 15:47:22 +00:00
|
|
|
|
2019-06-18 16:53:27 +00:00
|
|
|
_box->addButton(tr::lng_box_done(), _save);
|
|
|
|
_box->addButton(tr::lng_cancel(), [=] { _box->closeBox(); });
|
2019-06-15 14:29:40 +00:00
|
|
|
_box->setFocusCallback(_focus);
|
2019-06-10 15:47:22 +00:00
|
|
|
}
|
|
|
|
|
2019-06-15 14:29:40 +00:00
|
|
|
void Controller::setupContent() {
|
2019-06-12 14:13:49 +00:00
|
|
|
setupCover();
|
|
|
|
setupNameFields();
|
|
|
|
setupWarning();
|
2019-06-15 14:29:40 +00:00
|
|
|
setupSharePhoneNumber();
|
2019-06-10 15:47:22 +00:00
|
|
|
}
|
|
|
|
|
2019-06-15 14:29:40 +00:00
|
|
|
void Controller::setupCover() {
|
2019-06-12 14:13:49 +00:00
|
|
|
_box->addRow(
|
|
|
|
object_ptr<Info::Profile::Cover>(
|
|
|
|
_box,
|
|
|
|
_user,
|
2020-06-23 17:21:58 +00:00
|
|
|
_window,
|
2019-06-12 14:13:49 +00:00
|
|
|
(_phone.isEmpty()
|
2019-06-18 12:16:43 +00:00
|
|
|
? tr::lng_contact_mobile_hidden()
|
2019-06-12 14:13:49 +00:00
|
|
|
: rpl::single(App::formatPhone(_phone)))),
|
|
|
|
style::margins())->setAttribute(Qt::WA_TransparentForMouseEvents);
|
2019-06-10 15:47:22 +00:00
|
|
|
}
|
|
|
|
|
2019-06-15 14:29:40 +00:00
|
|
|
void Controller::setupNameFields() {
|
2019-06-10 15:47:22 +00:00
|
|
|
const auto inverted = langFirstNameGoesSecond();
|
2019-06-12 14:13:49 +00:00
|
|
|
const auto first = _box->addRow(
|
2019-06-10 15:47:22 +00:00
|
|
|
object_ptr<Ui::InputField>(
|
2019-06-12 14:13:49 +00:00
|
|
|
_box,
|
2019-06-10 15:47:22 +00:00
|
|
|
st::defaultInputField,
|
2019-06-18 14:07:45 +00:00
|
|
|
tr::lng_signup_firstname(),
|
2019-06-10 15:47:22 +00:00
|
|
|
_user->firstName),
|
|
|
|
st::addContactFieldMargin);
|
|
|
|
auto preparedLast = object_ptr<Ui::InputField>(
|
2019-06-12 14:13:49 +00:00
|
|
|
_box,
|
2019-06-10 15:47:22 +00:00
|
|
|
st::defaultInputField,
|
2019-06-18 14:07:45 +00:00
|
|
|
tr::lng_signup_lastname(),
|
2019-06-10 15:47:22 +00:00
|
|
|
_user->lastName);
|
|
|
|
const auto last = inverted
|
2019-06-12 14:13:49 +00:00
|
|
|
? _box->insertRow(
|
|
|
|
_box->rowsCount() - 1,
|
2019-06-10 15:47:22 +00:00
|
|
|
std::move(preparedLast),
|
|
|
|
st::addContactFieldMargin)
|
2019-06-12 14:13:49 +00:00
|
|
|
: _box->addRow(std::move(preparedLast), st::addContactFieldMargin);
|
2019-06-10 15:47:22 +00:00
|
|
|
|
|
|
|
initNameFields(first, last, inverted);
|
|
|
|
}
|
|
|
|
|
2019-06-15 14:29:40 +00:00
|
|
|
void Controller::initNameFields(
|
2019-06-10 15:47:22 +00:00
|
|
|
not_null<Ui::InputField*> first,
|
|
|
|
not_null<Ui::InputField*> last,
|
|
|
|
bool inverted) {
|
2019-06-12 14:13:49 +00:00
|
|
|
const auto getValue = [](not_null<Ui::InputField*> field) {
|
|
|
|
return TextUtilities::SingleLine(field->getLastText()).trimmed();
|
2019-06-10 15:47:22 +00:00
|
|
|
};
|
|
|
|
|
2019-06-12 14:13:49 +00:00
|
|
|
if (inverted) {
|
2019-06-15 14:29:40 +00:00
|
|
|
_box->setTabOrder(last, first);
|
2019-06-12 14:13:49 +00:00
|
|
|
}
|
2019-06-15 14:29:40 +00:00
|
|
|
_focus = [=] {
|
2019-06-12 14:13:49 +00:00
|
|
|
const auto firstValue = getValue(first);
|
|
|
|
const auto lastValue = getValue(last);
|
2019-06-10 15:47:22 +00:00
|
|
|
const auto empty = firstValue.isEmpty() && lastValue.isEmpty();
|
|
|
|
const auto focusFirst = (inverted != empty);
|
|
|
|
(focusFirst ? first : last)->setFocusFast();
|
|
|
|
};
|
2019-06-15 14:29:40 +00:00
|
|
|
_save = [=] {
|
2019-06-12 14:13:49 +00:00
|
|
|
const auto firstValue = getValue(first);
|
|
|
|
const auto lastValue = getValue(last);
|
2019-06-10 15:47:22 +00:00
|
|
|
const auto empty = firstValue.isEmpty() && lastValue.isEmpty();
|
|
|
|
if (empty) {
|
2019-06-15 14:29:40 +00:00
|
|
|
_focus();
|
2019-06-10 15:47:22 +00:00
|
|
|
(inverted ? last : first)->showError();
|
|
|
|
return;
|
|
|
|
}
|
2019-06-24 08:07:32 +00:00
|
|
|
SendRequest(
|
2019-09-13 12:22:54 +00:00
|
|
|
Ui::MakeWeak(_box),
|
2019-06-24 08:07:32 +00:00
|
|
|
_user,
|
|
|
|
_sharePhone && _sharePhone->checked(),
|
|
|
|
firstValue,
|
|
|
|
lastValue,
|
|
|
|
_phone);
|
2019-06-10 15:47:22 +00:00
|
|
|
};
|
2019-06-12 14:13:49 +00:00
|
|
|
const auto submit = [=] {
|
|
|
|
const auto firstValue = first->getLastText().trimmed();
|
|
|
|
const auto lastValue = last->getLastText().trimmed();
|
|
|
|
const auto empty = firstValue.isEmpty() && lastValue.isEmpty();
|
|
|
|
if (inverted ? last->hasFocus() : empty) {
|
|
|
|
first->setFocus();
|
|
|
|
} else if (inverted ? empty : first->hasFocus()) {
|
|
|
|
last->setFocus();
|
|
|
|
} else {
|
|
|
|
_save();
|
|
|
|
}
|
|
|
|
};
|
2019-06-15 14:29:40 +00:00
|
|
|
QObject::connect(first, &Ui::InputField::submitted, submit);
|
|
|
|
QObject::connect(last, &Ui::InputField::submitted, submit);
|
2019-09-27 16:46:27 +00:00
|
|
|
first->setMaxLength(kMaxUserFirstLastName);
|
|
|
|
first->setMaxLength(kMaxUserFirstLastName);
|
2019-06-15 14:29:40 +00:00
|
|
|
}
|
2019-06-12 14:13:49 +00:00
|
|
|
|
2019-06-15 14:29:40 +00:00
|
|
|
void Controller::setupWarning() {
|
|
|
|
if (_user->isContact() || !_phone.isEmpty()) {
|
2019-06-12 14:13:49 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_box->addRow(
|
2019-06-10 15:47:22 +00:00
|
|
|
object_ptr<Ui::FlatLabel>(
|
2019-06-12 14:13:49 +00:00
|
|
|
_box,
|
2019-06-19 16:39:25 +00:00
|
|
|
tr::lng_contact_phone_after(tr::now, lt_user, _user->shortName()),
|
2019-06-10 15:47:22 +00:00
|
|
|
st::changePhoneLabel),
|
|
|
|
st::addContactWarningMargin);
|
2019-06-12 14:13:49 +00:00
|
|
|
}
|
|
|
|
|
2019-06-15 14:29:40 +00:00
|
|
|
void Controller::setupSharePhoneNumber() {
|
|
|
|
const auto settings = _user->settings();
|
|
|
|
using Setting = MTPDpeerSettings::Flag;
|
|
|
|
if (!settings
|
|
|
|
|| !((*settings) & Setting::f_need_contacts_exception)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_sharePhone = _box->addRow(
|
|
|
|
object_ptr<Ui::Checkbox>(
|
|
|
|
_box,
|
2019-06-19 15:09:03 +00:00
|
|
|
tr::lng_contact_share_phone(tr::now),
|
2019-06-15 14:29:40 +00:00
|
|
|
true,
|
|
|
|
st::defaultBoxCheckbox),
|
|
|
|
st::addContactWarningMargin);
|
|
|
|
_box->addRow(
|
|
|
|
object_ptr<Ui::FlatLabel>(
|
|
|
|
_box,
|
2019-06-19 16:39:25 +00:00
|
|
|
tr::lng_contact_phone_will_be_shared(tr::now, lt_user, _user->shortName()),
|
2019-06-15 14:29:40 +00:00
|
|
|
st::changePhoneLabel),
|
|
|
|
st::addContactWarningMargin);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-12 14:13:49 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
void EditContactBox(
|
2019-09-18 11:19:05 +00:00
|
|
|
not_null<Ui::GenericBox*> box,
|
2020-06-23 17:21:58 +00:00
|
|
|
not_null<Window::SessionController*> window,
|
2019-06-12 14:13:49 +00:00
|
|
|
not_null<UserData*> user) {
|
2019-06-15 14:29:40 +00:00
|
|
|
box->lifetime().make_state<Controller>(box, window, user)->prepare();
|
2019-06-12 14:13:49 +00:00
|
|
|
}
|