Save data from EditPeerInfoBox.

This commit is contained in:
John Preston 2017-11-10 21:15:37 +04:00
parent 8ff0120642
commit dd3ae22e08
5 changed files with 282 additions and 3 deletions

View file

@ -84,6 +84,12 @@ void BoxContent::finishScrollCreate() {
connect(_scroll, SIGNAL(innerResized()), this, SLOT(onInnerResize())); connect(_scroll, SIGNAL(innerResized()), this, SLOT(onInnerResize()));
} }
void BoxContent::scrollToWidget(not_null<QWidget*> widget) {
if (_scroll) {
_scroll->scrollToWidget(widget);
}
}
void BoxContent::onScrollToY(int top, int bottom) { void BoxContent::onScrollToY(int top, int bottom) {
if (_scroll) { if (_scroll) {
_scroll->scrollToY(top, bottom); _scroll->scrollToY(top, bottom);

View file

@ -89,6 +89,8 @@ public:
getDelegate()->setAdditionalTitle(std::move(additional)); getDelegate()->setAdditionalTitle(std::move(additional));
} }
void scrollToWidget(not_null<QWidget*> widget);
void clearButtons() { void clearButtons() {
getDelegate()->clearButtons(); getDelegate()->clearButtons();
} }

View file

@ -93,6 +93,13 @@ private:
std::shared_ptr<Ui::RadioenumGroup<Invites>> invites; std::shared_ptr<Ui::RadioenumGroup<Invites>> invites;
Ui::Checkbox *signatures = nullptr; Ui::Checkbox *signatures = nullptr;
}; };
struct Saving {
base::optional<QString> username;
base::optional<QString> title;
base::optional<QString> description;
base::optional<bool> signatures;
base::optional<bool> everyoneInvites;
};
base::lambda<QString()> computeTitle() const; base::lambda<QString()> computeTitle() const;
object_ptr<Ui::RpWidget> createPhotoAndTitleEdit(); object_ptr<Ui::RpWidget> createPhotoAndTitleEdit();
@ -110,7 +117,6 @@ private:
void refreshInitialPhotoImage(); void refreshInitialPhotoImage();
void submitTitle(); void submitTitle();
void submitDescription(); void submitDescription();
void save();
void deleteWithConfirmation(); void deleteWithConfirmation();
void choosePhotoDelayed(); void choosePhotoDelayed();
void choosePhoto(); void choosePhoto();
@ -136,6 +142,23 @@ private:
void revokeInviteLink(); void revokeInviteLink();
void exportInviteLink(const QString &confirmation); void exportInviteLink(const QString &confirmation);
base::optional<Saving> validate() const;
bool validateUsername(Saving &to) const;
bool validateTitle(Saving &to) const;
bool validateDescription(Saving &to) const;
bool validateInvites(Saving &to) const;
bool validateSignatures(Saving &to) const;
void save();
void saveUsername();
void saveTitle();
void saveDescription();
void saveInvites();
void saveSignatures();
void pushSaveStage(base::lambda_once<void()> &&lambda);
void continueSave();
void cancelSave();
not_null<BoxContent*> _box; not_null<BoxContent*> _box;
not_null<ChannelData*> _channel; not_null<ChannelData*> _channel;
bool _isGroup; bool _isGroup;
@ -147,6 +170,9 @@ private:
UsernameState _usernameState = UsernameState::Normal; UsernameState _usernameState = UsernameState::Normal;
rpl::event_stream<rpl::producer<QString>> _usernameResultTexts; rpl::event_stream<rpl::producer<QString>> _usernameResultTexts;
std::deque<base::lambda_once<void()>> _saveStagesQueue;
Saving _savingData;
}; };
Controller::Controller( Controller::Controller(
@ -453,6 +479,7 @@ void Controller::privacyChanged(Privacy value) {
refreshVisibilities(); refreshVisibilities();
_controls.username->setDisplayFocused(true); _controls.username->setDisplayFocused(true);
_controls.username->setFocus(); _controls.username->setFocus();
_box->scrollToWidget(_controls.username);
} else { } else {
request(base::take(_checkUsernameRequestId)).cancel(); request(base::take(_checkUsernameRequestId)).cancel();
_checkUsernameTimer.cancel(); _checkUsernameTimer.cancel();
@ -496,7 +523,7 @@ void Controller::checkUsernameAvailability() {
if (type == qstr("CHANNEL_PUBLIC_GROUP_NA")) { if (type == qstr("CHANNEL_PUBLIC_GROUP_NA")) {
_usernameState = UsernameState::NotAvailable; _usernameState = UsernameState::NotAvailable;
_controls.privacy->setValue(Privacy::Private); _controls.privacy->setValue(Privacy::Private);
} else if (rand() % 10 < 2 || type == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) { } else if (type == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) {
_usernameState = UsernameState::TooMany; _usernameState = UsernameState::TooMany;
if (_controls.privacy->value() == Privacy::Public) { if (_controls.privacy->value() == Privacy::Public) {
askUsernameRevoke(); askUsernameRevoke();
@ -505,6 +532,7 @@ void Controller::checkUsernameAvailability() {
if (_controls.privacy->value() == Privacy::Public) { if (_controls.privacy->value() == Privacy::Public) {
_controls.usernameResult = nullptr; _controls.usernameResult = nullptr;
_controls.username->setFocus(); _controls.username->setFocus();
_box->scrollToWidget(_controls.username);
} }
} else if (type == qstr("USERNAME_INVALID")) { } else if (type == qstr("USERNAME_INVALID")) {
showUsernameError( showUsernameError(
@ -840,8 +868,10 @@ void Controller::submitTitle() {
if (_controls.title->getLastText().isEmpty()) { if (_controls.title->getLastText().isEmpty()) {
_controls.title->showError(); _controls.title->showError();
_box->scrollToWidget(_controls.title);
} else { } else {
_controls.description->setFocus(); _controls.description->setFocus();
_box->scrollToWidget(_controls.description);
} }
} }
@ -851,15 +881,245 @@ void Controller::submitDescription() {
if (_controls.title->getLastText().isEmpty()) { if (_controls.title->getLastText().isEmpty()) {
_controls.title->showError(); _controls.title->showError();
_controls.title->setFocus(); _box->scrollToWidget(_controls.title);
} else { } else {
save(); save();
} }
} }
base::optional<Controller::Saving> Controller::validate() const {
auto result = Saving();
if (validateUsername(result)
&& validateTitle(result)
&& validateDescription(result)
&& validateInvites(result)
&& validateSignatures(result)) {
return result;
}
return {};
}
bool Controller::validateUsername(Saving &to) const {
if (!_controls.privacy) {
return true;
} else if (_controls.privacy->value() == Privacy::Private) {
to.username = QString();
return true;
}
auto username = _controls.username->getLastText().trimmed();
if (username.isEmpty()) {
_controls.username->showError();
_box->scrollToWidget(_controls.username);
return false;
}
to.username = username;
return true;
}
bool Controller::validateTitle(Saving &to) const {
if (!_controls.title) {
return true;
}
auto title = _controls.title->getLastText().trimmed();
if (title.isEmpty()) {
_controls.title->showError();
_box->scrollToWidget(_controls.title);
return false;
}
to.title = title;
return true;
}
bool Controller::validateDescription(Saving &to) const {
if (!_controls.description) {
return true;
}
to.description = _controls.description->getLastText().trimmed();
return true;
}
bool Controller::validateInvites(Saving &to) const {
if (!_controls.invites) {
return true;
}
to.everyoneInvites
= (_controls.invites->value() == Invites::Everyone);
return true;
}
bool Controller::validateSignatures(Saving &to) const {
if (!_controls.signatures) {
return true;
}
to.signatures = _controls.signatures->checked();
return true;
}
void Controller::save() { void Controller::save() {
Expects(_wrap != nullptr); Expects(_wrap != nullptr);
if (!_saveStagesQueue.empty()) {
return;
}
if (auto saving = validate()) {
_savingData = *saving;
pushSaveStage([this] { saveUsername(); });
pushSaveStage([this] { saveTitle(); });
pushSaveStage([this] { saveDescription(); });
pushSaveStage([this] { saveInvites(); });
pushSaveStage([this] { saveSignatures(); });
pushSaveStage([this] { _box->closeBox(); });
continueSave();
}
}
void Controller::pushSaveStage(base::lambda_once<void()> &&lambda) {
_saveStagesQueue.push_back(std::move(lambda));
}
void Controller::continueSave() {
if (!_saveStagesQueue.empty()) {
auto next = std::move(_saveStagesQueue.front());
_saveStagesQueue.pop_front();
next();
}
}
void Controller::cancelSave() {
_saveStagesQueue.clear();
}
void Controller::saveUsername() {
if (!_savingData.username
|| *_savingData.username == _channel->username) {
return continueSave();
}
request(MTPchannels_UpdateUsername(
_channel->inputChannel,
MTP_string(*_savingData.username)
)).done([this](const MTPBool &result) {
_channel->setName(
TextUtilities::SingleLine(_channel->name),
*_savingData.username);
continueSave();
}).fail([this](const RPCError &error) {
auto type = error.type();
if (type == qstr("USERNAME_NOT_MODIFIED")) {
_channel->setName(
TextUtilities::SingleLine(_channel->name),
TextUtilities::SingleLine(*_savingData.username));
continueSave();
return;
}
auto errorKey = [&] {
if (type == qstr("USERNAME_INVALID")) {
return lng_create_channel_link_invalid;
} else if (type == qstr("USERNAME_OCCUPIED")
|| type == qstr("USERNAMES_UNAVAILABLE")) {
return lng_create_channel_link_invalid;
}
return lng_create_channel_link_invalid;
}();
_controls.username->showError();
_box->scrollToWidget(_controls.username);
showUsernameError(Lang::Viewer(errorKey));
cancelSave();
}).send();
}
void Controller::saveTitle() {
if (!_savingData.title || *_savingData.title == _channel->name) {
return continueSave();
}
request(MTPchannels_EditTitle(
_channel->inputChannel,
MTP_string(*_savingData.title)
)).done([this](const MTPUpdates &result) {
Auth().api().applyUpdates(result);
continueSave();
}).fail([this](const RPCError &error) {
auto type = error.type();
if (type == qstr("CHAT_NOT_MODIFIED")
|| type == qstr("CHAT_TITLE_NOT_MODIFIED")) {
_channel->setName(*_savingData.title, _channel->username);
continueSave();
return;
}
if (type == qstr("NO_CHAT_TITLE")) {
_controls.title->showError();
_box->scrollToWidget(_controls.title);
} else {
_controls.title->setFocus();
}
cancelSave();
}).send();
}
void Controller::saveDescription() {
if (!_savingData.description
|| *_savingData.description == _channel->about()) {
return continueSave();
}
auto successCallback = [this] {
if (_channel->setAbout(*_savingData.description)) {
Auth().api().fullPeerUpdated().notify(_channel);
}
continueSave();
};
request(MTPchannels_EditAbout(
_channel->inputChannel,
MTP_string(*_savingData.description)
)).done([=](const MTPBool &result) {
successCallback();
}).fail([=](const RPCError &error) {
auto type = error.type();
if (type == qstr("CHAT_ABOUT_NOT_MODIFIED")) {
successCallback();
return;
}
_controls.description->setFocus();
cancelSave();
}).send();
}
void Controller::saveInvites() {
if (!_savingData.everyoneInvites
|| *_savingData.everyoneInvites == _channel->anyoneCanAddMembers()) {
return continueSave();
}
request(MTPchannels_ToggleInvites(
_channel->inputChannel,
MTP_bool(*_savingData.everyoneInvites)
)).done([this](const MTPUpdates &result) {
Auth().api().applyUpdates(result);
continueSave();
}).fail([this](const RPCError &error) {
if (error.type() == qstr("CHAT_NOT_MODIFIED")) {
continueSave();
} else {
cancelSave();
}
}).send();
}
void Controller::saveSignatures() {
if (!_savingData.signatures
|| *_savingData.signatures == _channel->addsSignature()) {
return continueSave();
}
request(MTPchannels_ToggleSignatures(
_channel->inputChannel,
MTP_bool(*_savingData.signatures)
)).done([this](const MTPUpdates &result) {
Auth().api().applyUpdates(result);
continueSave();
}).fail([this](const RPCError &error) {
if (error.type() == qstr("CHAT_NOT_MODIFIED")) {
continueSave();
} else {
cancelSave();
}
}).send();
} }
void Controller::deleteWithConfirmation() { void Controller::deleteWithConfirmation() {

View file

@ -689,6 +689,16 @@ void ScrollArea::scrollTo(ScrollToRequest request) {
scrollToY(request.ymin, request.ymax); scrollToY(request.ymin, request.ymax);
} }
void ScrollArea::scrollToWidget(not_null<QWidget*> widget) {
if (auto local = this->widget()) {
auto globalPosition = widget->mapToGlobal(QPoint(0, 0));
auto localPosition = local->mapFromGlobal(globalPosition);
auto localTop = localPosition.y();
auto localBottom = localTop + widget->height();
scrollToY(localTop, localBottom);
}
}
void ScrollArea::scrollToY(int toTop, int toBottom) { void ScrollArea::scrollToY(int toTop, int toBottom) {
myEnsureResized(widget()); myEnsureResized(widget());
myEnsureResized(this); myEnsureResized(this);

View file

@ -219,6 +219,7 @@ public:
} }
void scrollTo(ScrollToRequest request); void scrollTo(ScrollToRequest request);
void scrollToWidget(not_null<QWidget*> widget);
protected: protected:
bool eventFilter(QObject *obj, QEvent *e) override; bool eventFilter(QObject *obj, QEvent *e) override;