mirror of
https://github.com/telegramdesktop/tdesktop
synced 2024-12-27 00:53:22 +00:00
Save value without closing the passport panel.
This commit is contained in:
parent
d0e854e9d8
commit
35dcbe0aa0
@ -1520,8 +1520,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_passport_phone_description" = "Enter your phone number";
|
||||
"lng_passport_email_title" = "Email";
|
||||
"lng_passport_email_description" = "Enter your email address";
|
||||
"lng_passport_accept_allow" = "You accept {policy} and allow their {bot} to send messages to you.";
|
||||
"lng_passport_allow" = "You allow {bot} to send messages to you.";
|
||||
"lng_passport_accept_allow" = "You accept {policy} and allow their {bot} to send you messages.";
|
||||
"lng_passport_allow" = "You allow {bot} to send you messages.";
|
||||
"lng_passport_policy" = "{bot} privacy policy";
|
||||
"lng_passport_authorize" = "Authorize";
|
||||
"lng_passport_form_error" = "Could not get authorization form.";
|
||||
|
@ -836,6 +836,25 @@ bool Messenger::openLocalUrl(const QString &url) {
|
||||
}
|
||||
auto command = urlTrimmed.midRef(qstr("tg://").size());
|
||||
|
||||
const auto showPassportForm = [](const QMap<QString, QString> ¶ms) {
|
||||
if (const auto botId = params.value("bot_id", QString()).toInt()) {
|
||||
const auto scope = params.value("scope", QString());
|
||||
const auto callback = params.value("callback_url", QString());
|
||||
const auto publicKey = params.value("public_key", QString());
|
||||
if (const auto window = App::wnd()) {
|
||||
if (const auto controller = window->controller()) {
|
||||
controller->showPassportForm(Passport::FormRequest(
|
||||
botId,
|
||||
scope,
|
||||
callback,
|
||||
publicKey));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
using namespace qthelp;
|
||||
auto matchOptions = RegExOption::CaseInsensitive;
|
||||
if (auto joinChatMatch = regex_match(qsl("^join/?\\?invite=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"), command, matchOptions)) {
|
||||
@ -871,7 +890,9 @@ bool Messenger::openLocalUrl(const QString &url) {
|
||||
if (auto main = App::main()) {
|
||||
auto params = url_parse_params(usernameMatch->captured(1), UrlParamNameTransform::ToLower);
|
||||
auto domain = params.value(qsl("domain"));
|
||||
if (regex_match(qsl("^[a-zA-Z0-9\\.\\_]+$"), domain, matchOptions)) {
|
||||
if (domain == qsl("telegrampassport")) {
|
||||
return showPassportForm(params);
|
||||
} else if (regex_match(qsl("^[a-zA-Z0-9\\.\\_]+$"), domain, matchOptions)) {
|
||||
auto start = qsl("start");
|
||||
auto startToken = params.value(start);
|
||||
if (startToken.isEmpty()) {
|
||||
@ -909,25 +930,10 @@ bool Messenger::openLocalUrl(const QString &url) {
|
||||
auto params = url_parse_params(proxyMatch->captured(1), UrlParamNameTransform::ToLower);
|
||||
ProxiesBoxController::ShowApplyConfirmation(ProxyData::Type::Mtproto, params);
|
||||
return true;
|
||||
} else if (auto authMatch = regex_match(qsl("^secureid/?\\?(.+)(#|$)"), command, matchOptions)) {
|
||||
const auto params = url_parse_params(
|
||||
} else if (auto authMatch = regex_match(qsl("^passport/?\\?(.+)(#|$)"), command, matchOptions)) {
|
||||
return showPassportForm(url_parse_params(
|
||||
authMatch->captured(1),
|
||||
UrlParamNameTransform::ToLower);
|
||||
if (const auto botId = params.value("bot_id", QString()).toInt()) {
|
||||
const auto scope = params.value("scope", QString());
|
||||
const auto callback = params.value("callback_url", QString());
|
||||
const auto publicKey = params.value("public_key", QString());
|
||||
if (const auto window = App::wnd()) {
|
||||
if (const auto controller = window->controller()) {
|
||||
controller->showAuthForm(Passport::FormRequest(
|
||||
botId,
|
||||
scope,
|
||||
callback,
|
||||
publicKey));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
UrlParamNameTransform::ToLower));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -200,36 +200,36 @@ void FormController::decryptValues() {
|
||||
Expects(!_secret.empty());
|
||||
|
||||
for (auto &[type, value] : _form.values) {
|
||||
if (value.data.original.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
decryptValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
void FormController::decryptValue(Value &value) {
|
||||
Expects(!_secret.empty());
|
||||
Expects(!value.data.original.isEmpty());
|
||||
|
||||
if (!validateValueSecrets(value)) {
|
||||
resetValue(value);
|
||||
return;
|
||||
}
|
||||
value.data.parsed.fields = DeserializeData(DecryptData(
|
||||
bytes::make_span(value.data.original),
|
||||
value.data.hash,
|
||||
value.data.secret));
|
||||
if (!value.data.original.isEmpty()) {
|
||||
value.data.parsed.fields = DeserializeData(DecryptData(
|
||||
bytes::make_span(value.data.original),
|
||||
value.data.hash,
|
||||
value.data.secret));
|
||||
}
|
||||
}
|
||||
|
||||
bool FormController::validateValueSecrets(Value &value) {
|
||||
value.data.secret = DecryptValueSecret(
|
||||
value.data.encryptedSecret,
|
||||
_secret,
|
||||
value.data.hash);
|
||||
if (value.data.secret.empty()) {
|
||||
LOG(("API Error: Could not decrypt data secret. "
|
||||
"Forgetting files and data :("));
|
||||
return false;
|
||||
if (!value.data.original.isEmpty()) {
|
||||
value.data.secret = DecryptValueSecret(
|
||||
value.data.encryptedSecret,
|
||||
_secret,
|
||||
value.data.hash);
|
||||
if (value.data.secret.empty()) {
|
||||
LOG(("API Error: Could not decrypt data secret. "
|
||||
"Forgetting files and data :("));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (auto &file : value.files) {
|
||||
file.secret = DecryptValueSecret(
|
||||
@ -451,6 +451,16 @@ auto FormController::scanUpdated() const
|
||||
return _scanUpdated.events();
|
||||
}
|
||||
|
||||
auto FormController::valueSaved() const
|
||||
->rpl::producer<not_null<const Value*>> {
|
||||
return _valueSaved.events();
|
||||
}
|
||||
|
||||
auto FormController::verificationNeeded() const
|
||||
->rpl::producer<not_null<const Value*>> {
|
||||
return _verificationNeeded.events();
|
||||
}
|
||||
|
||||
const Form &FormController::form() const {
|
||||
return _form;
|
||||
}
|
||||
@ -465,6 +475,9 @@ not_null<Value*> FormController::findValue(not_null<const Value*> value) {
|
||||
}
|
||||
|
||||
void FormController::startValueEdit(not_null<const Value*> value) {
|
||||
if (value->saveRequestId) {
|
||||
return;
|
||||
}
|
||||
const auto nonconst = findValue(value);
|
||||
loadFiles(nonconst->files);
|
||||
nonconst->filesInEdit = ranges::view::all(
|
||||
@ -472,6 +485,7 @@ void FormController::startValueEdit(not_null<const Value*> value) {
|
||||
) | ranges::view::transform([=](const File &file) {
|
||||
return EditFile(value, file, nullptr);
|
||||
}) | ranges::to_vector;
|
||||
nonconst->data.parsedInEdit = nonconst->data.parsed;
|
||||
}
|
||||
|
||||
void FormController::loadFiles(std::vector<File> &files) {
|
||||
@ -557,8 +571,14 @@ void FormController::fileLoadFail(FileKey key) {
|
||||
}
|
||||
|
||||
void FormController::cancelValueEdit(not_null<const Value*> value) {
|
||||
if (value->saveRequestId) {
|
||||
return;
|
||||
}
|
||||
const auto nonconst = findValue(value);
|
||||
nonconst->filesInEdit.clear();
|
||||
nonconst->data.encryptedSecretInEdit.clear();
|
||||
nonconst->data.hashInEdit.clear();
|
||||
nonconst->data.parsedInEdit = ValueMap();
|
||||
}
|
||||
|
||||
bool FormController::isEncryptedValue(Value::Type type) const {
|
||||
@ -568,8 +588,11 @@ bool FormController::isEncryptedValue(Value::Type type) const {
|
||||
void FormController::saveValueEdit(
|
||||
not_null<const Value*> value,
|
||||
ValueMap &&data) {
|
||||
if (value->saveRequestId) {
|
||||
return;
|
||||
}
|
||||
const auto nonconst = findValue(value);
|
||||
nonconst->data.parsed = std::move(data);
|
||||
nonconst->data.parsedInEdit = std::move(data);
|
||||
|
||||
if (isEncryptedValue(nonconst->type)) {
|
||||
saveEncryptedValue(nonconst);
|
||||
@ -616,13 +639,13 @@ void FormController::saveEncryptedValue(not_null<Value*> value) {
|
||||
value->data.secret = GenerateSecretBytes();
|
||||
}
|
||||
const auto encryptedData = EncryptData(
|
||||
SerializeData(value->data.parsed.fields),
|
||||
SerializeData(value->data.parsedInEdit.fields),
|
||||
value->data.secret);
|
||||
value->data.hash = encryptedData.hash;
|
||||
value->data.encryptedSecret = EncryptValueSecret(
|
||||
value->data.hashInEdit = encryptedData.hash;
|
||||
value->data.encryptedSecretInEdit = EncryptValueSecret(
|
||||
value->data.secret,
|
||||
_secret,
|
||||
value->data.hash);
|
||||
value->data.hashInEdit);
|
||||
|
||||
const auto selfie = value->selfieInEdit
|
||||
? inputFile(*value->selfieInEdit)
|
||||
@ -650,7 +673,7 @@ void FormController::saveEncryptedValue(not_null<Value*> value) {
|
||||
Unexpected("Value type in saveEncryptedValue().");
|
||||
}();
|
||||
const auto flags = ((value->filesInEdit.empty()
|
||||
&& value->data.parsed.fields.empty())
|
||||
&& value->data.parsedInEdit.fields.empty())
|
||||
? MTPDinputSecureValue::Flag(0)
|
||||
: MTPDinputSecureValue::Flag::f_data)
|
||||
| (value->filesInEdit.empty()
|
||||
@ -659,26 +682,24 @@ void FormController::saveEncryptedValue(not_null<Value*> value) {
|
||||
| (value->selfieInEdit
|
||||
? MTPDinputSecureValue::Flag::f_selfie
|
||||
: MTPDinputSecureValue::Flag(0));
|
||||
if (!flags) {
|
||||
request(MTPaccount_DeleteSecureValue(MTP_vector<MTPSecureValueType>(1, type))).send();
|
||||
} else {
|
||||
sendSaveRequest(value, MTP_inputSecureValue(
|
||||
MTP_flags(flags),
|
||||
type,
|
||||
MTP_secureData(
|
||||
MTP_bytes(encryptedData.bytes),
|
||||
MTP_bytes(value->data.hash),
|
||||
MTP_bytes(value->data.encryptedSecret)),
|
||||
MTP_vector<MTPInputSecureFile>(inputFiles),
|
||||
MTPSecurePlainData(),
|
||||
selfie));
|
||||
}
|
||||
Assert(flags != MTPDinputSecureValue::Flags(0));
|
||||
|
||||
sendSaveRequest(value, MTP_inputSecureValue(
|
||||
MTP_flags(flags),
|
||||
type,
|
||||
MTP_secureData(
|
||||
MTP_bytes(encryptedData.bytes),
|
||||
MTP_bytes(value->data.hashInEdit),
|
||||
MTP_bytes(value->data.encryptedSecretInEdit)),
|
||||
MTP_vector<MTPInputSecureFile>(inputFiles),
|
||||
MTPSecurePlainData(),
|
||||
selfie));
|
||||
}
|
||||
|
||||
void FormController::savePlainTextValue(not_null<Value*> value) {
|
||||
Expects(!isEncryptedValue(value->type));
|
||||
|
||||
const auto text = value->data.parsed.fields[QString("value")];
|
||||
const auto text = value->data.parsedInEdit.fields["value"];
|
||||
const auto type = [&] {
|
||||
switch (value->type) {
|
||||
case Value::Type::Phone: return MTP_secureValueTypePhone();
|
||||
@ -705,7 +726,9 @@ void FormController::savePlainTextValue(not_null<Value*> value) {
|
||||
void FormController::sendSaveRequest(
|
||||
not_null<Value*> value,
|
||||
const MTPInputSecureValue &data) {
|
||||
request(MTPaccount_SaveSecureValue(
|
||||
Expects(value->saveRequestId == 0);
|
||||
|
||||
value->saveRequestId = request(MTPaccount_SaveSecureValue(
|
||||
data,
|
||||
MTP_long(_secretId)
|
||||
)).done([=](const MTPSecureValue &result) {
|
||||
@ -715,9 +738,27 @@ void FormController::sendSaveRequest(
|
||||
value->files = parseFiles(
|
||||
data.vfiles.v,
|
||||
base::take(value->filesInEdit));
|
||||
value->data.encryptedSecret = std::move(
|
||||
value->data.encryptedSecretInEdit);
|
||||
value->data.parsed = std::move(value->data.parsedInEdit);
|
||||
value->data.hash = std::move(value->data.hashInEdit);
|
||||
|
||||
_view->show(Box<InformBox>("Saved"));
|
||||
value->saveRequestId = 0;
|
||||
|
||||
_valueSaved.fire_copy(value);
|
||||
}).fail([=](const RPCError &error) {
|
||||
value->saveRequestId = 0;
|
||||
if (error.type() == qstr("PHONE_VERIFICATION_NEEDED")) {
|
||||
if (value->type == Value::Type::Phone) {
|
||||
_verificationNeeded.fire_copy(value);
|
||||
return;
|
||||
}
|
||||
} else if (error.type() == qstr("EMAIL_VERIFICATION_NEEDED")) {
|
||||
if (value->type == Value::Type::Email) {
|
||||
_verificationNeeded.fire_copy(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_view->show(Box<InformBox>("Error saving value:\n" + error.type()));
|
||||
}).send();
|
||||
}
|
||||
@ -1019,7 +1060,7 @@ void FormController::cancel() {
|
||||
if (!_cancelled) {
|
||||
_cancelled = true;
|
||||
crl::on_main(this, [=] {
|
||||
_controller->clearAuthForm();
|
||||
_controller->clearPassportForm();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -102,10 +102,13 @@ struct ValueMap {
|
||||
|
||||
struct ValueData {
|
||||
QByteArray original;
|
||||
bytes::vector secret;
|
||||
ValueMap parsed;
|
||||
bytes::vector hash;
|
||||
bytes::vector secret;
|
||||
bytes::vector encryptedSecret;
|
||||
ValueMap parsedInEdit;
|
||||
bytes::vector hashInEdit;
|
||||
bytes::vector encryptedSecretInEdit;
|
||||
};
|
||||
|
||||
struct Value {
|
||||
@ -132,6 +135,8 @@ struct Value {
|
||||
std::vector<EditFile> filesInEdit;
|
||||
base::optional<File> selfie;
|
||||
base::optional<EditFile> selfieInEdit;
|
||||
mtpRequestId saveRequestId = 0;
|
||||
|
||||
};
|
||||
|
||||
struct Form {
|
||||
@ -200,6 +205,8 @@ public:
|
||||
QString defaultPhoneNumber() const;
|
||||
|
||||
rpl::producer<not_null<const EditFile*>> scanUpdated() const;
|
||||
rpl::producer<not_null<const Value*>> valueSaved() const;
|
||||
rpl::producer<not_null<const Value*>> verificationNeeded() const;
|
||||
|
||||
const Form &form() const;
|
||||
void startValueEdit(not_null<const Value*> value);
|
||||
@ -288,6 +295,8 @@ private:
|
||||
std::map<FileKey, std::unique_ptr<mtpFileLoader>> _fileLoaders;
|
||||
|
||||
rpl::event_stream<not_null<const EditFile*>> _scanUpdated;
|
||||
rpl::event_stream<not_null<const Value*>> _valueSaved;
|
||||
rpl::event_stream<not_null<const Value*>> _verificationNeeded;
|
||||
|
||||
bytes::vector _secret;
|
||||
uint64 _secretId = 0;
|
||||
|
@ -423,42 +423,77 @@ void PanelController::editScope(int index) {
|
||||
_panel.get(),
|
||||
this,
|
||||
std::move(GetDocumentScheme(_editScope->type)),
|
||||
_editScope->fields->data.parsed,
|
||||
_editScope->files[_editScopeFilesIndex]->data.parsed,
|
||||
_editScope->fields->data.parsedInEdit,
|
||||
_editScope->files[_editScopeFilesIndex]->data.parsedInEdit,
|
||||
valueFiles(*_editScope->files[_editScopeFilesIndex]))
|
||||
: object_ptr<PanelEditDocument>(
|
||||
_panel.get(),
|
||||
this,
|
||||
std::move(GetDocumentScheme(_editScope->type)),
|
||||
_editScope->fields->data.parsed);
|
||||
_editScope->fields->data.parsedInEdit);
|
||||
case Scope::Type::Phone:
|
||||
case Scope::Type::Email: {
|
||||
const auto &fields = _editScope->fields->data.parsed.fields;
|
||||
const auto valueIt = fields.find("value");
|
||||
const auto &parsed = _editScope->fields->data.parsedInEdit;
|
||||
const auto valueIt = parsed.fields.find("value");
|
||||
return object_ptr<PanelEditContact>(
|
||||
_panel.get(),
|
||||
this,
|
||||
std::move(GetContactScheme(_editScope->type)),
|
||||
(valueIt == end(fields)) ? QString() : valueIt->second,
|
||||
(valueIt == end(parsed.fields)
|
||||
? QString()
|
||||
: valueIt->second),
|
||||
getDefaultContactValue(_editScope->type));
|
||||
} break;
|
||||
}
|
||||
Unexpected("Type in PanelController::editScope().");
|
||||
}();
|
||||
if (content) {
|
||||
_panel->setBackAllowed(true);
|
||||
_panel->backRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
cancelValueEdit(index);
|
||||
|
||||
_panel->setBackAllowed(true);
|
||||
|
||||
_panel->backRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
_panel->showForm();
|
||||
}, content->lifetime());
|
||||
|
||||
content->lifetime().add([=] {
|
||||
cancelValueEdit();
|
||||
});
|
||||
|
||||
_form->valueSaved(
|
||||
) | rpl::start_with_next([=](not_null<const Value*> value) {
|
||||
processValueSaved(value);
|
||||
}, content->lifetime());
|
||||
|
||||
_form->verificationNeeded(
|
||||
) | rpl::start_with_next([=](not_null<const Value*> value) {
|
||||
processVerificationNeeded(value);
|
||||
}, content->lifetime());
|
||||
|
||||
_panel->showEditValue(std::move(content));
|
||||
}
|
||||
|
||||
void PanelController::processValueSaved(not_null<const Value*> value) {
|
||||
Expects(_editScope != nullptr);
|
||||
|
||||
const auto value1 = _editScope->fields;
|
||||
const auto value2 = (_editScopeFilesIndex >= 0)
|
||||
? _editScope->files[_editScopeFilesIndex].get()
|
||||
: nullptr;
|
||||
if (value == value1 || value == value2) {
|
||||
if (!value1->saveRequestId && (!value2 || !value2->saveRequestId)) {
|
||||
_panel->showForm();
|
||||
}, content->lifetime());
|
||||
_panel->showEditValue(std::move(content));
|
||||
} else {
|
||||
cancelValueEdit(index);
|
||||
show(Box<InformBox>("Saved"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ScanInfo> PanelController::valueFiles(const Value &value) const {
|
||||
void PanelController::processVerificationNeeded(
|
||||
not_null<const Value*> value) {
|
||||
show(Box<InformBox>("Verification needed :("));
|
||||
}
|
||||
|
||||
std::vector<ScanInfo> PanelController::valueFiles(
|
||||
const Value &value) const {
|
||||
auto result = std::vector<ScanInfo>();
|
||||
for (const auto &file : value.filesInEdit) {
|
||||
result.push_back(collectScanInfo(file));
|
||||
@ -466,12 +501,12 @@ std::vector<ScanInfo> PanelController::valueFiles(const Value &value) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
void PanelController::cancelValueEdit(int index) {
|
||||
void PanelController::cancelValueEdit() {
|
||||
if (const auto scope = base::take(_editScope)) {
|
||||
_form->startValueEdit(scope->fields);
|
||||
_form->cancelValueEdit(scope->fields);
|
||||
const auto index = std::exchange(_editScopeFilesIndex, -1);
|
||||
if (index >= 0) {
|
||||
_form->startValueEdit(scope->files[index]);
|
||||
_form->cancelValueEdit(scope->files[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -480,16 +515,14 @@ void PanelController::saveScope(ValueMap &&data, ValueMap &&filesData) {
|
||||
Expects(_panel != nullptr);
|
||||
Expects(_editScope != nullptr);
|
||||
|
||||
const auto scope = base::take(_editScope);
|
||||
_form->saveValueEdit(scope->fields, std::move(data));
|
||||
const auto index = std::exchange(_editScopeFilesIndex, -1);
|
||||
if (index >= 0) {
|
||||
_form->saveValueEdit(scope->files[index], std::move(filesData));
|
||||
_form->saveValueEdit(_editScope->fields, std::move(data));
|
||||
if (_editScopeFilesIndex >= 0) {
|
||||
_form->saveValueEdit(
|
||||
_editScope->files[_editScopeFilesIndex],
|
||||
std::move(filesData));
|
||||
} else {
|
||||
Assert(filesData.fields.empty());
|
||||
}
|
||||
|
||||
_panel->showForm();
|
||||
}
|
||||
|
||||
void PanelController::cancelAuth() {
|
||||
|
@ -81,8 +81,10 @@ public:
|
||||
private:
|
||||
void ensurePanelCreated();
|
||||
|
||||
void cancelValueEdit(int index);
|
||||
void cancelValueEdit();
|
||||
std::vector<ScanInfo> valueFiles(const Value &value) const;
|
||||
void processValueSaved(not_null<const Value*> value);
|
||||
void processVerificationNeeded(not_null<const Value*> value);
|
||||
|
||||
ScanInfo collectScanInfo(const EditFile &file) const;
|
||||
QString getDefaultContactValue(Scope::Type type) const;
|
||||
|
@ -115,14 +115,15 @@ not_null<Ui::RpWidget*> PanelEditDocument::setupContent(
|
||||
return QString();
|
||||
};
|
||||
|
||||
for (const auto &row : _scheme.rows) {
|
||||
for (auto i = 0, count = int(_scheme.rows.size()); i != count; ++i) {
|
||||
const auto &row = _scheme.rows[i];
|
||||
auto fields = (row.type == Scheme::ValueType::Fields)
|
||||
? &data
|
||||
: scanData;
|
||||
if (!fields) {
|
||||
continue;
|
||||
}
|
||||
_details.push_back(inner->add(object_ptr<PanelDetailsRow>(
|
||||
_details.emplace(i, inner->add(object_ptr<PanelDetailsRow>(
|
||||
inner,
|
||||
row.label,
|
||||
valueOrEmpty(*fields, row.key))));
|
||||
@ -132,7 +133,7 @@ not_null<Ui::RpWidget*> PanelEditDocument::setupContent(
|
||||
}
|
||||
|
||||
void PanelEditDocument::focusInEvent(QFocusEvent *e) {
|
||||
for (const auto row : _details) {
|
||||
for (const auto [index, row] : _details) {
|
||||
if (row->setFocusFast()) {
|
||||
return;
|
||||
}
|
||||
@ -157,11 +158,9 @@ void PanelEditDocument::updateControlsGeometry() {
|
||||
}
|
||||
|
||||
void PanelEditDocument::save() {
|
||||
Expects(_details.size() == _scheme.rows.size());
|
||||
|
||||
auto data = ValueMap();
|
||||
auto scanData = ValueMap();
|
||||
for (auto i = 0, count = int(_details.size()); i != count; ++i) {
|
||||
for (const auto [i, field] : _details) {
|
||||
const auto &row = _scheme.rows[i];
|
||||
auto &fields = (row.type == Scheme::ValueType::Fields)
|
||||
? data
|
||||
|
@ -81,7 +81,7 @@ private:
|
||||
object_ptr<Ui::PlainShadow> _bottomShadow;
|
||||
|
||||
QPointer<EditScans> _editScans;
|
||||
std::vector<QPointer<PanelDetailsRow>> _details;
|
||||
std::map<int, QPointer<PanelDetailsRow>> _details;
|
||||
|
||||
object_ptr<Ui::RoundButton> _done;
|
||||
|
||||
|
@ -405,13 +405,15 @@ void Controller::showJumpToDate(Dialogs::Key chat, QDate requestedDate) {
|
||||
Ui::show(std::move(box));
|
||||
}
|
||||
|
||||
void Controller::showAuthForm(const Passport::FormRequest &request) {
|
||||
_authForm = std::make_unique<Passport::FormController>(this, request);
|
||||
_authForm->show();
|
||||
void Controller::showPassportForm(const Passport::FormRequest &request) {
|
||||
_passportForm = std::make_unique<Passport::FormController>(
|
||||
this,
|
||||
request);
|
||||
_passportForm->show();
|
||||
}
|
||||
|
||||
void Controller::clearAuthForm() {
|
||||
_authForm = nullptr;
|
||||
void Controller::clearPassportForm() {
|
||||
_passportForm = nullptr;
|
||||
}
|
||||
|
||||
void Controller::updateColumnLayout() {
|
||||
|
@ -205,8 +205,8 @@ public:
|
||||
Dialogs::Key chat,
|
||||
QDate requestedDate);
|
||||
|
||||
void showAuthForm(const Passport::FormRequest &request);
|
||||
void clearAuthForm();
|
||||
void showPassportForm(const Passport::FormRequest &request);
|
||||
void clearPassportForm();
|
||||
|
||||
base::Variable<bool> &dialogsListFocused() {
|
||||
return _dialogsListFocused;
|
||||
@ -254,7 +254,7 @@ private:
|
||||
|
||||
not_null<MainWindow*> _window;
|
||||
|
||||
std::unique_ptr<Passport::FormController> _authForm;
|
||||
std::unique_ptr<Passport::FormController> _passportForm;
|
||||
|
||||
GifPauseReasons _gifPauseReasons = 0;
|
||||
base::Observable<void> _gifPauseLevelChanged;
|
||||
|
Loading…
Reference in New Issue
Block a user