mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 07:07:08 +02:00
Respected new error for occupied usernames in manage channel.
This commit is contained in:
parent
2acedca6b7
commit
3fdb807a1e
7 changed files with 126 additions and 114 deletions
Telegram
|
@ -1386,6 +1386,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_create_channel_link_too_short" = "Sorry, this link is too short";
|
||||
"lng_create_channel_link_bad_symbols" = "Only 0-9, a-z, and underscores allowed.";
|
||||
"lng_create_channel_link_available" = "This link is available";
|
||||
"lng_create_channel_link_pending" = "Checking name...";
|
||||
"lng_create_channel_link_copied" = "Link copied to clipboard";
|
||||
|
||||
"lng_create_group_crop" = "Select an area for group photo";
|
||||
|
|
|
@ -1225,6 +1225,8 @@ SetupChannelBox::UsernameResult SetupChannelBox::parseError(
|
|||
return UsernameResult::Invalid;
|
||||
} else if (error == u"USERNAME_OCCUPIED"_q) {
|
||||
return UsernameResult::Occupied;
|
||||
} else if (error == u"USERNAME_PURCHASE_AVAILABLE"_q) {
|
||||
return UsernameResult::Occupied;
|
||||
} else if (error == u"USERNAMES_UNAVAILABLE"_q) {
|
||||
return UsernameResult::Occupied;
|
||||
} else if (error == u"CHANNEL_PUBLIC_GROUP_NA"_q) {
|
||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/peers/edit_peer_invite_link.h"
|
||||
#include "boxes/peers/edit_peer_invite_links.h"
|
||||
#include "boxes/peers/edit_peer_usernames_list.h"
|
||||
#include "boxes/username_box.h"
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
|
@ -103,8 +104,7 @@ private:
|
|||
Ui::SlideWrap<Ui::RpWidget> *usernameWrap = nullptr;
|
||||
Ui::UsernameInput *usernameInput = nullptr;
|
||||
UsernamesList *usernamesList = nullptr;
|
||||
base::unique_qptr<Ui::FlatLabel> usernameResult;
|
||||
const style::FlatLabel *usernameResultStyle = nullptr;
|
||||
base::unique_qptr<Ui::FlatLabel> usernameCheckResult;
|
||||
|
||||
Ui::SlideWrap<> *inviteLinkWrap = nullptr;
|
||||
Ui::FlatLabel *inviteLink = nullptr;
|
||||
|
@ -127,9 +127,8 @@ private:
|
|||
void usernameChanged();
|
||||
void showUsernameError(rpl::producer<QString> &&error);
|
||||
void showUsernameGood();
|
||||
void showUsernameResult(
|
||||
rpl::producer<QString> &&text,
|
||||
not_null<const style::FlatLabel*> st);
|
||||
void showUsernamePending();
|
||||
void showUsernameEmpty();
|
||||
|
||||
void fillPrivaciesButtons(
|
||||
not_null<Ui::VerticalLayout*> parent,
|
||||
|
@ -157,7 +156,9 @@ private:
|
|||
base::Timer _checkUsernameTimer;
|
||||
mtpRequestId _checkUsernameRequestId = 0;
|
||||
UsernameState _usernameState = UsernameState::Normal;
|
||||
rpl::event_stream<rpl::producer<QString>> _usernameResultTexts;
|
||||
|
||||
rpl::event_stream<UsernameCheckInfo> _usernameCheckInfo;
|
||||
rpl::lifetime _usernameCheckInfoLifetime;
|
||||
|
||||
rpl::event_stream<int> _scrollToRequests;
|
||||
|
||||
|
@ -450,6 +451,8 @@ object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
|
|||
}, placeholder->lifetime());
|
||||
_controls.usernameInput->move(placeholder->pos());
|
||||
|
||||
AddUsernameCheckLabel(container, _usernameCheckInfo.events());
|
||||
|
||||
AddDividerText(
|
||||
container,
|
||||
tr::lng_create_channel_link_about());
|
||||
|
@ -506,7 +509,7 @@ void Controller::privacyChanged(Privacy value) {
|
|||
toggleEditUsername();
|
||||
toggleWhoSendWrap();
|
||||
|
||||
_controls.usernameResult = nullptr;
|
||||
showUsernameEmpty();
|
||||
checkUsernameAvailability();
|
||||
} else {
|
||||
toggleWhoSendWrap();
|
||||
|
@ -575,11 +578,16 @@ void Controller::checkUsernameAvailability() {
|
|||
}
|
||||
} else if (initial) {
|
||||
if (_controls.privacy->value() == Privacy::HasUsername) {
|
||||
_controls.usernameResult = nullptr;
|
||||
showUsernameEmpty();
|
||||
setFocusUsername();
|
||||
}
|
||||
} else if (type == u"USERNAME_INVALID"_q) {
|
||||
showUsernameError(tr::lng_create_channel_link_invalid());
|
||||
} else if (type == u"USERNAME_PURCHASE_AVAILABLE"_q) {
|
||||
_goodUsername = false;
|
||||
_usernameCheckInfo.fire({
|
||||
.type = UsernameCheckInfo::Type::PurchaseAvailable,
|
||||
});
|
||||
} else if (type == u"USERNAME_OCCUPIED"_q && checking != username) {
|
||||
showUsernameError(tr::lng_create_channel_link_occupied());
|
||||
}
|
||||
|
@ -602,7 +610,7 @@ void Controller::usernameChanged() {
|
|||
_goodUsername = false;
|
||||
const auto username = getUsernameInput();
|
||||
if (username.isEmpty()) {
|
||||
_controls.usernameResult = nullptr;
|
||||
showUsernameEmpty();
|
||||
_checkUsernameTimer.cancel();
|
||||
return;
|
||||
}
|
||||
|
@ -617,43 +625,44 @@ void Controller::usernameChanged() {
|
|||
} else if (username.size() < Ui::EditPeer::kMinUsernameLength) {
|
||||
showUsernameError(tr::lng_create_channel_link_too_short());
|
||||
} else {
|
||||
_controls.usernameResult = nullptr;
|
||||
showUsernamePending();
|
||||
_checkUsernameTimer.callOnce(Ui::EditPeer::kUsernameCheckTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::showUsernameError(rpl::producer<QString> &&error) {
|
||||
_goodUsername = false;
|
||||
showUsernameResult(std::move(error), &st::editPeerUsernameError);
|
||||
_usernameCheckInfoLifetime.destroy();
|
||||
std::move(
|
||||
error
|
||||
) | rpl::map([](QString s) {
|
||||
return UsernameCheckInfo{
|
||||
.type = UsernameCheckInfo::Type::Error,
|
||||
.text = { std::move(s) },
|
||||
};
|
||||
}) | rpl::start_to_stream(_usernameCheckInfo, _usernameCheckInfoLifetime);
|
||||
}
|
||||
|
||||
void Controller::showUsernameGood() {
|
||||
_goodUsername = true;
|
||||
showUsernameResult(
|
||||
tr::lng_create_channel_link_available(),
|
||||
&st::editPeerUsernameGood);
|
||||
_usernameCheckInfoLifetime.destroy();
|
||||
_usernameCheckInfo.fire({
|
||||
.type = UsernameCheckInfo::Type::Good,
|
||||
.text = { tr::lng_create_channel_link_available(tr::now) },
|
||||
});
|
||||
}
|
||||
|
||||
void Controller::showUsernameResult(
|
||||
rpl::producer<QString> &&text,
|
||||
not_null<const style::FlatLabel*> st) {
|
||||
if (!_controls.usernameResult
|
||||
|| _controls.usernameResultStyle != st) {
|
||||
_controls.usernameResultStyle = st;
|
||||
_controls.usernameResult = base::make_unique_q<Ui::FlatLabel>(
|
||||
_controls.usernameWrap,
|
||||
_usernameResultTexts.events() | rpl::flatten_latest(),
|
||||
*st);
|
||||
const auto label = _controls.usernameResult.get();
|
||||
label->show();
|
||||
label->widthValue(
|
||||
) | rpl::start_with_next([label] {
|
||||
label->moveToRight(
|
||||
st::editPeerUsernamePosition.x(),
|
||||
st::editPeerUsernamePosition.y());
|
||||
}, label->lifetime());
|
||||
}
|
||||
_usernameResultTexts.fire(std::move(text));
|
||||
void Controller::showUsernamePending() {
|
||||
_usernameCheckInfoLifetime.destroy();
|
||||
_usernameCheckInfo.fire({
|
||||
.type = UsernameCheckInfo::Type::Default,
|
||||
.text = { .text = tr::lng_create_channel_link_pending(tr::now) },
|
||||
});
|
||||
}
|
||||
|
||||
void Controller::showUsernameEmpty() {
|
||||
_usernameCheckInfoLifetime.destroy();
|
||||
_usernameCheckInfo.fire({ .type = UsernameCheckInfo::Type::Default });
|
||||
}
|
||||
|
||||
object_ptr<Ui::RpWidget> Controller::createInviteLinkBlock() {
|
||||
|
|
|
@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/fields/special_fields.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/wrap/follow_slide_wrap.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
@ -31,16 +32,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace {
|
||||
|
||||
struct CheckInfo final {
|
||||
enum class Type {
|
||||
Good,
|
||||
Error,
|
||||
Default,
|
||||
PurchaseAvailable,
|
||||
};
|
||||
Type type;
|
||||
v::text::data text;
|
||||
};
|
||||
[[nodiscard]] TextWithEntities PurchaseAvailableText() {
|
||||
constexpr auto kUsernameAuction = "auction";
|
||||
return tr::lng_username_purchase_available(
|
||||
tr::now,
|
||||
lt_link,
|
||||
Ui::Text::Link(
|
||||
'@' + QString(kUsernameAuction),
|
||||
u"https://t.me/"_q + kUsernameAuction),
|
||||
Ui::Text::RichLangValue);
|
||||
}
|
||||
|
||||
class UsernameEditor final : public Ui::RpWidget {
|
||||
public:
|
||||
|
@ -49,7 +50,7 @@ public:
|
|||
void setInnerFocus();
|
||||
[[nodiscard]] rpl::producer<> submitted() const;
|
||||
[[nodiscard]] rpl::producer<> save();
|
||||
[[nodiscard]] rpl::producer<CheckInfo> checkInfoChanged() const;
|
||||
[[nodiscard]] rpl::producer<UsernameCheckInfo> checkInfoChanged() const;
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
@ -80,7 +81,7 @@ private:
|
|||
base::Timer _checkTimer;
|
||||
|
||||
rpl::event_stream<> _saved;
|
||||
rpl::event_stream<CheckInfo> _checkInfoChanged;
|
||||
rpl::event_stream<UsernameCheckInfo> _checkInfoChanged;
|
||||
|
||||
};
|
||||
|
||||
|
@ -147,7 +148,7 @@ rpl::producer<> UsernameEditor::save() {
|
|||
return _saved.events();
|
||||
}
|
||||
|
||||
rpl::producer<CheckInfo> UsernameEditor::checkInfoChanged() const {
|
||||
rpl::producer<UsernameCheckInfo> UsernameEditor::checkInfoChanged() const {
|
||||
return _checkInfoChanged.events();
|
||||
}
|
||||
|
||||
|
@ -184,7 +185,7 @@ void UsernameEditor::changed() {
|
|||
if (name.isEmpty()) {
|
||||
if (!_errorText.isEmpty() || !_goodText.isEmpty()) {
|
||||
_errorText = _goodText = QString();
|
||||
checkInfoChange();
|
||||
_checkInfoChanged.fire({ UsernameCheckInfo::Type::Default });
|
||||
}
|
||||
_checkTimer.cancel();
|
||||
} else {
|
||||
|
@ -223,38 +224,29 @@ void UsernameEditor::changed() {
|
|||
void UsernameEditor::checkInfoChange() {
|
||||
if (!_errorText.isEmpty()) {
|
||||
_checkInfoChanged.fire({
|
||||
.type = CheckInfo::Type::Error,
|
||||
.text = _errorText,
|
||||
.type = UsernameCheckInfo::Type::Error,
|
||||
.text = { _errorText },
|
||||
});
|
||||
} else if (!_goodText.isEmpty()) {
|
||||
_checkInfoChanged.fire({
|
||||
.type = CheckInfo::Type::Good,
|
||||
.text = _goodText,
|
||||
.type = UsernameCheckInfo::Type::Good,
|
||||
.text = { _goodText },
|
||||
});
|
||||
} else {
|
||||
_checkInfoChanged.fire({
|
||||
.type = CheckInfo::Type::Default,
|
||||
.text = tr::lng_username_choose(tr::now),
|
||||
.type = UsernameCheckInfo::Type::Default,
|
||||
.text = { tr::lng_username_choose(tr::now) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void UsernameEditor::checkInfoPurchaseAvailable() {
|
||||
constexpr auto kUsernameAuction = "auction";
|
||||
const auto text = tr::lng_username_purchase_available(
|
||||
tr::now,
|
||||
lt_link,
|
||||
Ui::Text::Link(
|
||||
'@' + QString(kUsernameAuction),
|
||||
u"https://t.me/"_q + kUsernameAuction),
|
||||
Ui::Text::RichLangValue);
|
||||
_username->setFocus();
|
||||
_username->showError();
|
||||
_errorText = text.text;
|
||||
_errorText = u".bad."_q;
|
||||
|
||||
_checkInfoChanged.fire({
|
||||
.type = CheckInfo::Type::PurchaseAvailable,
|
||||
.text = text,
|
||||
.type = UsernameCheckInfo::Type::PurchaseAvailable,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -320,52 +312,7 @@ void UsernamesBox(
|
|||
{});
|
||||
box->setFocusCallback([=] { editor->setInnerFocus(); });
|
||||
|
||||
{
|
||||
const auto padding = st::boxRowPadding;
|
||||
const auto &st = st::aboutRevokePublicLabel;
|
||||
const auto skip = (st::usernameSkip - st.style.font->height) / 2;
|
||||
|
||||
box->addSkip(skip);
|
||||
const auto wrap = box->addRow(
|
||||
object_ptr<Ui::SlideWrap<Ui::RpWidget>>(
|
||||
box,
|
||||
object_ptr<Ui::RpWidget>(box)),
|
||||
padding);
|
||||
wrap->setMinimalHeight(st.style.font->height);
|
||||
|
||||
const auto maxHeightWrap = wrap->entity();
|
||||
const auto label = Ui::CreateChild<Ui::FlatLabel>(
|
||||
maxHeightWrap,
|
||||
editor->checkInfoChanged(
|
||||
) | rpl::map([](CheckInfo info) {
|
||||
return v::text::take_marked(base::take(info.text));
|
||||
}) | rpl::flatten_latest(),
|
||||
st);
|
||||
label->heightValue(
|
||||
) | rpl::start_with_next([=](int height) {
|
||||
if (height > maxHeightWrap->height()) {
|
||||
maxHeightWrap->resize(maxHeightWrap->width(), height);
|
||||
}
|
||||
}, maxHeightWrap->lifetime());
|
||||
|
||||
editor->checkInfoChanged(
|
||||
) | rpl::start_with_next([=](CheckInfo info) {
|
||||
const auto &color = (info.type == CheckInfo::Type::Good)
|
||||
? st::boxTextFgGood
|
||||
: (info.type == CheckInfo::Type::Error)
|
||||
? st::boxTextFgError
|
||||
: st::usernameDefaultFg;
|
||||
label->setTextColorOverride(color->c);
|
||||
label->resizeToWidth(container->width()
|
||||
- padding.left()
|
||||
- padding.right());
|
||||
|
||||
wrap->toggle(
|
||||
info.type == CheckInfo::Type::PurchaseAvailable,
|
||||
anim::type::normal);
|
||||
}, label->lifetime());
|
||||
box->addSkip(skip);
|
||||
}
|
||||
AddUsernameCheckLabel(container, editor->checkInfoChanged());
|
||||
|
||||
container->add(object_ptr<Ui::DividerLabel>(
|
||||
container,
|
||||
|
@ -401,3 +348,41 @@ void UsernamesBox(
|
|||
box->addButton(tr::lng_settings_save(), finish);
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
||||
void AddUsernameCheckLabel(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
rpl::producer<UsernameCheckInfo> checkInfo) {
|
||||
const auto padding = st::boxRowPadding;
|
||||
const auto &st = st::aboutRevokePublicLabel;
|
||||
const auto skip = (st::usernameSkip - st.style.font->height) / 4;
|
||||
|
||||
auto wrapped = object_ptr<Ui::VerticalLayout>(container);
|
||||
Settings::AddSkip(wrapped, skip);
|
||||
const auto label = wrapped->add(object_ptr<Ui::FlatLabel>(wrapped, st));
|
||||
Settings::AddSkip(wrapped, skip);
|
||||
|
||||
Settings::AddSkip(container, skip);
|
||||
const auto wrap = container->add(
|
||||
object_ptr<Ui::FollowSlideWrap<Ui::VerticalLayout>>(
|
||||
container,
|
||||
std::move(wrapped)),
|
||||
padding);
|
||||
|
||||
rpl::combine(
|
||||
std::move(checkInfo),
|
||||
container->widthValue()
|
||||
) | rpl::start_with_next([=](const UsernameCheckInfo &info, int w) {
|
||||
using Type = UsernameCheckInfo::Type;
|
||||
label->setMarkedText((info.type == Type::PurchaseAvailable)
|
||||
? PurchaseAvailableText()
|
||||
: info.text);
|
||||
const auto &color = (info.type == Type::Good)
|
||||
? st::boxTextFgGood
|
||||
: (info.type == Type::Error)
|
||||
? st::boxTextFgError
|
||||
: st::usernameDefaultFg;
|
||||
label->setTextColorOverride(color->c);
|
||||
label->resizeToWidth(w - padding.left() - padding.right());
|
||||
}, label->lifetime());
|
||||
Settings::AddSkip(container, skip);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Ui {
|
||||
class GenericBox;
|
||||
class VerticalLayout;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Main {
|
||||
|
@ -18,3 +19,18 @@ class Session;
|
|||
void UsernamesBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Main::Session*> session);
|
||||
|
||||
struct UsernameCheckInfo final {
|
||||
enum class Type {
|
||||
Good,
|
||||
Error,
|
||||
Default,
|
||||
PurchaseAvailable,
|
||||
};
|
||||
Type type;
|
||||
TextWithEntities text;
|
||||
};
|
||||
|
||||
void AddUsernameCheckLabel(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
rpl::producer<UsernameCheckInfo> checkInfo);
|
||||
|
|
|
@ -655,7 +655,7 @@ editPeerHistoryVisibilityLabelMargins: margins(34px, 0px, 48px, 0px);
|
|||
editPeerPrivacyLabelMargins: margins(42px, 0px, 34px, 0px);
|
||||
editPeerPreHistoryLabelMargins: margins(34px, 0px, 34px, 0px);
|
||||
editPeerUsernameTitleLabelMargins: margins(22px, 17px, 22px, 10px);
|
||||
editPeerUsernameFieldMargins: margins(22px, 0px, 22px, 16px);
|
||||
editPeerUsernameFieldMargins: margins(22px, 0px, 22px, 0px);
|
||||
editPeerUsername: setupChannelLink;
|
||||
editPeerUsernameSkip: 8px;
|
||||
editPeerInviteLink: FlatLabel(defaultFlatLabel) {
|
||||
|
@ -669,7 +669,6 @@ editPeerUsernameGood: FlatLabel(defaultFlatLabel) {
|
|||
editPeerUsernameError: FlatLabel(editPeerUsernameGood) {
|
||||
textFg: boxTextFgError;
|
||||
}
|
||||
editPeerUsernamePosition: point(22px, 18px);
|
||||
|
||||
editPeerReactionsButton: SettingsButton(infoProfileButton) {
|
||||
padding: margins(59px, 13px, 8px, 11px);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 0937ac0ad0feaf3cbccf009e0e1f2a04cc0ef9f8
|
||||
Subproject commit c197c1831d1af48cf769f271a126af2c2eaf8185
|
Loading…
Add table
Reference in a new issue