mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Show transfer community button, set 2sv password.
This commit is contained in:
parent
ca7c50fbcd
commit
0dddb7694f
13 changed files with 341 additions and 140 deletions
|
@ -1651,6 +1651,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_rights_chat_banned_custom" = "Custom";
|
"lng_rights_chat_banned_custom" = "Custom";
|
||||||
"lng_rights_chat_banned_custom_date" = "Until {date}";
|
"lng_rights_chat_banned_custom_date" = "Until {date}";
|
||||||
|
|
||||||
|
"lng_rights_transfer_group" = "Transfer group ownership";
|
||||||
|
"lng_rights_transfer_channel" = "Transfer channel ownership";
|
||||||
|
"lng_rights_transfer_check" = "Security check";
|
||||||
|
"lng_rights_transfer_check_about" = "You can transfer this group to {user} only if you have:";
|
||||||
|
"lng_rights_transfer_check_password" = "• Enabled **2-Step Verification** more than **7 days** ago.";
|
||||||
|
"lng_rights_transfer_check_session" = "• Logged in on this device more than **24 hours** ago.";
|
||||||
|
"lng_rights_transfer_check_later" = "Please come back later.";
|
||||||
|
"lng_rights_transfer_set_password" = "Set password";
|
||||||
|
"lng_rights_transfer_about" = "This will transfer the full **owner rights** for {group} to {user}.";
|
||||||
|
"lng_rights_transfer_sure" = "Change owner";
|
||||||
|
"lng_rights_transfer_password" = "Please enter your password to complete the transfer.";
|
||||||
|
"lng_rights_transfer_done_group" = "{user} is now the owner of the group.";
|
||||||
|
"lng_rights_transfer_done_channel" = "{user} is now the owner of the channel.";
|
||||||
|
|
||||||
"lng_restricted_send_message" = "The admins of this group restricted you from writing here.";
|
"lng_restricted_send_message" = "The admins of this group restricted you from writing here.";
|
||||||
"lng_restricted_send_media" = "The admins of this group restricted you from posting media content here.";
|
"lng_restricted_send_media" = "The admins of this group restricted you from posting media content here.";
|
||||||
"lng_restricted_send_stickers" = "The admins of this group restricted you from posting stickers here.";
|
"lng_restricted_send_stickers" = "The admins of this group restricted you from posting stickers here.";
|
||||||
|
|
|
@ -985,3 +985,5 @@ addContactWarningMargin: margins(19px, 10px, 19px, 5px);
|
||||||
blockUserConfirmation: FlatLabel(boxLabel) {
|
blockUserConfirmation: FlatLabel(boxLabel) {
|
||||||
minWidth: 240px;
|
minWidth: 240px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transferCheckWidth: 300px;
|
||||||
|
|
|
@ -226,10 +226,17 @@ void PasscodeBox::setInnerFocus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PasscodeBox::setPasswordDone(const QByteArray &newPasswordBytes) {
|
void PasscodeBox::setPasswordDone(const QByteArray &newPasswordBytes) {
|
||||||
|
if (_replacedBy) {
|
||||||
|
_replacedBy->closeBox();
|
||||||
|
}
|
||||||
_setRequest = 0;
|
_setRequest = 0;
|
||||||
_newPasswordSet.fire_copy(newPasswordBytes);
|
_newPasswordSet.fire_copy(newPasswordBytes);
|
||||||
auto text = lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated));
|
const auto weak = make_weak(this);
|
||||||
getDelegate()->show(Box<InformBox>(text), LayerOption::CloseOther);
|
const auto text = lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated));
|
||||||
|
getDelegate()->show(Box<InformBox>(text));
|
||||||
|
if (weak) {
|
||||||
|
closeBox();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PasscodeBox::closeReplacedBy() {
|
void PasscodeBox::closeReplacedBy() {
|
||||||
|
@ -353,8 +360,7 @@ void PasscodeBox::validateEmail(
|
||||||
submit,
|
submit,
|
||||||
resend,
|
resend,
|
||||||
errors->events(),
|
errors->events(),
|
||||||
resent->events()),
|
resent->events()));
|
||||||
LayerOption::KeepOther);
|
|
||||||
|
|
||||||
box->setCloseByOutsideClick(false);
|
box->setCloseByOutsideClick(false);
|
||||||
box->setCloseByEscape(false);
|
box->setCloseByEscape(false);
|
||||||
|
@ -441,9 +447,12 @@ void PasscodeBox::save(bool force) {
|
||||||
}
|
}
|
||||||
if (!_recoverEmail->isHidden() && email.isEmpty() && !force) {
|
if (!_recoverEmail->isHidden() && email.isEmpty() && !force) {
|
||||||
_skipEmailWarning = true;
|
_skipEmailWarning = true;
|
||||||
_replacedBy = getDelegate()->show(Box<ConfirmBox>(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton, crl::guard(this, [this] {
|
_replacedBy = getDelegate()->show(
|
||||||
save(true);
|
Box<ConfirmBox>(
|
||||||
})));
|
lang(lng_cloud_password_about_recover),
|
||||||
|
lang(lng_cloud_password_skip_email),
|
||||||
|
st::attentionBoxButton,
|
||||||
|
crl::guard(this, [this] { save(true); })));
|
||||||
} else if (_newPasscode->isHidden()) {
|
} else if (_newPasscode->isHidden()) {
|
||||||
clearCloudPassword(old);
|
clearCloudPassword(old);
|
||||||
} else if (_oldPasscode->isHidden()) {
|
} else if (_oldPasscode->isHidden()) {
|
||||||
|
@ -452,6 +461,7 @@ void PasscodeBox::save(bool force) {
|
||||||
changeCloudPassword(old, pwd);
|
changeCloudPassword(old, pwd);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
closeReplacedBy();
|
||||||
const auto weak = make_weak(this);
|
const auto weak = make_weak(this);
|
||||||
cSetPasscodeBadTries(0);
|
cSetPasscodeBadTries(0);
|
||||||
Local::setPasscode(pwd.toUtf8());
|
Local::setPasscode(pwd.toUtf8());
|
||||||
|
|
|
@ -163,7 +163,7 @@ void Controller::choose(not_null<ChatData*> chat) {
|
||||||
}
|
}
|
||||||
text.append("\n\n" + lang(lng_manage_discussion_group_private));
|
text.append("\n\n" + lang(lng_manage_discussion_group_private));
|
||||||
text.append("\n\n");
|
text.append("\n\n");
|
||||||
text.append(lng_manage_discussion_group_warning__generic(
|
text.append(lng_manage_discussion_group_warning__rich(
|
||||||
lt_visible,
|
lt_visible,
|
||||||
Ui::Text::Bold(lang(lng_manage_discussion_group_visible))));
|
Ui::Text::Bold(lang(lng_manage_discussion_group_visible))));
|
||||||
const auto box = std::make_shared<QPointer<BoxContent>>();
|
const auto box = std::make_shared<QPointer<BoxContent>>();
|
||||||
|
|
|
@ -10,18 +10,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
#include "ui/wrap/padding_wrap.h"
|
#include "ui/wrap/padding_wrap.h"
|
||||||
|
#include "ui/wrap/slide_wrap.h"
|
||||||
#include "ui/widgets/checkbox.h"
|
#include "ui/widgets/checkbox.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/text_options.h"
|
#include "ui/text_options.h"
|
||||||
#include "ui/special_buttons.h"
|
#include "ui/special_buttons.h"
|
||||||
|
#include "info/profile/info_profile_button.h"
|
||||||
|
#include "settings/settings_privacy_security.h"
|
||||||
#include "boxes/calendar_box.h"
|
#include "boxes/calendar_box.h"
|
||||||
|
#include "boxes/generic_box.h"
|
||||||
#include "boxes/peers/edit_peer_permissions_box.h"
|
#include "boxes/peers/edit_peer_permissions_box.h"
|
||||||
|
#include "boxes/peers/edit_peer_info_box.h"
|
||||||
#include "data/data_peer_values.h"
|
#include "data/data_peer_values.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_chat.h"
|
#include "data/data_chat.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
|
#include "core/core_cloud_password.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "auth_session.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -29,6 +39,64 @@ constexpr auto kMaxRestrictDelayDays = 366;
|
||||||
constexpr auto kSecondsInDay = 24 * 60 * 60;
|
constexpr auto kSecondsInDay = 24 * 60 * 60;
|
||||||
constexpr auto kSecondsInWeek = 7 * kSecondsInDay;
|
constexpr auto kSecondsInWeek = 7 * kSecondsInDay;
|
||||||
|
|
||||||
|
enum class PasswordErrorType {
|
||||||
|
None,
|
||||||
|
NoPassword,
|
||||||
|
Later,
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetCloudPassword(not_null<GenericBox*> box, not_null<UserData*> user) {
|
||||||
|
user->session().api().reloadPasswordState();
|
||||||
|
user->session().api().passwordState(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
using namespace Settings;
|
||||||
|
const auto weak = make_weak(box);
|
||||||
|
if (CheckEditCloudPassword()) {
|
||||||
|
box->getDelegate()->show(
|
||||||
|
EditCloudPasswordBox(&user->session()));
|
||||||
|
} else {
|
||||||
|
box->getDelegate()->show(CloudPasswordAppOutdatedBox());
|
||||||
|
}
|
||||||
|
if (weak) {
|
||||||
|
weak->closeBox();
|
||||||
|
}
|
||||||
|
}, box->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferPasswordError(
|
||||||
|
not_null<GenericBox*> box,
|
||||||
|
not_null<UserData*> user,
|
||||||
|
PasswordErrorType error) {
|
||||||
|
box->setTitle(langFactory(lng_rights_transfer_check));
|
||||||
|
box->setWidth(st::transferCheckWidth);
|
||||||
|
|
||||||
|
auto text = lng_rights_transfer_check_about__rich(
|
||||||
|
lt_user,
|
||||||
|
Ui::Text::Bold(user->shortName())
|
||||||
|
).append('\n').append('\n').append(
|
||||||
|
Ui::Text::RichLangValue(lang(lng_rights_transfer_check_password))
|
||||||
|
).append('\n').append('\n').append(
|
||||||
|
Ui::Text::RichLangValue(lang(lng_rights_transfer_check_session))
|
||||||
|
);
|
||||||
|
if (error == PasswordErrorType::Later) {
|
||||||
|
text.append('\n').append('\n').append(
|
||||||
|
Ui::Text::RichLangValue(lang(lng_rights_transfer_check_later))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||||
|
box,
|
||||||
|
rpl::single(text),
|
||||||
|
st::boxLabel));
|
||||||
|
if (error == PasswordErrorType::Later) {
|
||||||
|
box->addButton(langFactory(lng_box_ok), [=] { box->closeBox(); });
|
||||||
|
} else {
|
||||||
|
box->addButton(langFactory(lng_rights_transfer_set_password), [=] {
|
||||||
|
SetCloudPassword(box, user);
|
||||||
|
});
|
||||||
|
box->addButton(langFactory(lng_cancel), [=] { box->closeBox(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class EditParticipantBox::Inner : public Ui::RpWidget {
|
class EditParticipantBox::Inner : public Ui::RpWidget {
|
||||||
|
@ -244,6 +312,7 @@ void EditAdminBox::prepare() {
|
||||||
return result;
|
return result;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
const auto isGroup = chat || channel->isMegagroup();
|
||||||
const auto anyoneCanAddMembers = chat
|
const auto anyoneCanAddMembers = chat
|
||||||
? chat->anyoneCanAddMembers()
|
? chat->anyoneCanAddMembers()
|
||||||
: channel->anyoneCanAddMembers();
|
: channel->anyoneCanAddMembers();
|
||||||
|
@ -252,18 +321,31 @@ void EditAdminBox::prepare() {
|
||||||
lng_rights_edit_admin_header,
|
lng_rights_edit_admin_header,
|
||||||
prepareFlags,
|
prepareFlags,
|
||||||
disabledMessages,
|
disabledMessages,
|
||||||
peer()->isChat() || peer()->isMegagroup(),
|
isGroup,
|
||||||
anyoneCanAddMembers);
|
anyoneCanAddMembers);
|
||||||
addControl(std::move(checkboxes), QMargins());
|
addControl(std::move(checkboxes), QMargins());
|
||||||
|
|
||||||
_aboutAddAdmins = addControl(
|
auto selectedFlags = rpl::single(
|
||||||
object_ptr<Ui::FlatLabel>(this, st::boxLabel),
|
|
||||||
st::rightsAboutMargin);
|
|
||||||
rpl::single(
|
|
||||||
getChecked()
|
getChecked()
|
||||||
) | rpl::then(std::move(
|
) | rpl::then(std::move(
|
||||||
changes
|
changes
|
||||||
)) | rpl::map(
|
));
|
||||||
|
if (canTransferOwnership()) {
|
||||||
|
const auto allFlags = FullAdminRights(isGroup);
|
||||||
|
setupTransferButton(
|
||||||
|
isGroup
|
||||||
|
)->toggleOn(rpl::duplicate(
|
||||||
|
selectedFlags
|
||||||
|
) | rpl::map(
|
||||||
|
((_1 & allFlags) == allFlags)
|
||||||
|
))->setDuration(0);
|
||||||
|
}
|
||||||
|
_aboutAddAdmins = addControl(
|
||||||
|
object_ptr<Ui::FlatLabel>(this, st::boxLabel),
|
||||||
|
st::rightsAboutMargin);
|
||||||
|
std::move(
|
||||||
|
selectedFlags
|
||||||
|
) | rpl::map(
|
||||||
(_1 & Flag::f_add_admins) != 0
|
(_1 & Flag::f_add_admins) != 0
|
||||||
) | rpl::distinct_until_changed(
|
) | rpl::distinct_until_changed(
|
||||||
) | rpl::start_with_next([=](bool checked) {
|
) | rpl::start_with_next([=](bool checked) {
|
||||||
|
@ -289,6 +371,88 @@ void EditAdminBox::prepare() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EditAdminBox::canTransferOwnership() const {
|
||||||
|
if (user()->isInaccessible() || user()->isBot()) {
|
||||||
|
return false;
|
||||||
|
} else if (const auto chat = peer()->asChat()) {
|
||||||
|
return chat->amCreator();
|
||||||
|
} else if (const auto channel = peer()->asChannel()) {
|
||||||
|
return channel->amCreator();
|
||||||
|
}
|
||||||
|
Unexpected("Chat type in EditAdminBox::canTransferOwnership.");
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<Ui::SlideWrap<Ui::RpWidget>*> EditAdminBox::setupTransferButton(
|
||||||
|
bool isGroup) {
|
||||||
|
const auto wrap = addControl(
|
||||||
|
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
this,
|
||||||
|
object_ptr<Ui::VerticalLayout>(this)));
|
||||||
|
|
||||||
|
const auto container = wrap->entity();
|
||||||
|
const auto addDivider = [&] {
|
||||||
|
container->add(
|
||||||
|
object_ptr<BoxContentDivider>(container),
|
||||||
|
{ 0, st::infoProfileSkip, 0, st::infoProfileSkip });
|
||||||
|
};
|
||||||
|
|
||||||
|
addDivider();
|
||||||
|
container->add(EditPeerInfoBox::CreateButton(
|
||||||
|
this,
|
||||||
|
Lang::Viewer(isGroup
|
||||||
|
? lng_rights_transfer_group
|
||||||
|
: lng_rights_transfer_channel),
|
||||||
|
rpl::single(QString()),
|
||||||
|
[=] { transferOwnership(); },
|
||||||
|
st::peerPermissionsButton));
|
||||||
|
addDivider();
|
||||||
|
|
||||||
|
return wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditAdminBox::transferOwnership() {
|
||||||
|
if (_checkTransferRequestId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto channel = peer()->isChannel()
|
||||||
|
? peer()->asChannel()->inputChannel
|
||||||
|
: MTP_inputChannelEmpty();
|
||||||
|
const auto api = &peer()->session().api();
|
||||||
|
_checkTransferRequestId = api->request(MTPchannels_EditCreator(
|
||||||
|
channel,
|
||||||
|
MTP_inputUserEmpty(),
|
||||||
|
MTP_inputCheckPasswordEmpty()
|
||||||
|
)).fail([=](const RPCError &error) {
|
||||||
|
_checkTransferRequestId = 0;
|
||||||
|
if (!handleTransferPasswordError(error)) {
|
||||||
|
requestTransferPassword();
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EditAdminBox::handleTransferPasswordError(const RPCError &error) {
|
||||||
|
const auto type = [&] {
|
||||||
|
const auto &type = error.type();
|
||||||
|
if (type == qstr("PASSWORD_MISSING")) {
|
||||||
|
return PasswordErrorType::NoPassword;
|
||||||
|
} else if (type.startsWith(qstr("PASSWORD_TOO_FRESH_"))
|
||||||
|
|| type.startsWith(qstr("SESSION_TOO_FRESH_"))) {
|
||||||
|
return PasswordErrorType::Later;
|
||||||
|
}
|
||||||
|
return PasswordErrorType::None;
|
||||||
|
}();
|
||||||
|
if (type == PasswordErrorType::None) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDelegate()->show(Box(TransferPasswordError, user(), type));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditAdminBox::requestTransferPassword() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void EditAdminBox::refreshAboutAddAdminsText(bool canAddAdmins) {
|
void EditAdminBox::refreshAboutAddAdminsText(bool canAddAdmins) {
|
||||||
_aboutAddAdmins->setText([&] {
|
_aboutAddAdmins->setText([&] {
|
||||||
if (!canSave()) {
|
if (!canSave()) {
|
||||||
|
|
|
@ -16,6 +16,8 @@ class LinkButton;
|
||||||
class Checkbox;
|
class Checkbox;
|
||||||
class Radiobutton;
|
class Radiobutton;
|
||||||
class RadiobuttonGroup;
|
class RadiobuttonGroup;
|
||||||
|
template <typename Widget>
|
||||||
|
class SlideWrap;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
class CalendarBox;
|
class CalendarBox;
|
||||||
|
@ -77,15 +79,21 @@ private:
|
||||||
|
|
||||||
static MTPChatAdminRights Defaults(not_null<PeerData*> peer);
|
static MTPChatAdminRights Defaults(not_null<PeerData*> peer);
|
||||||
|
|
||||||
|
void transferOwnership();
|
||||||
|
bool handleTransferPasswordError(const RPCError &error);
|
||||||
|
void requestTransferPassword();
|
||||||
bool canSave() const {
|
bool canSave() const {
|
||||||
return !!_saveCallback;
|
return !!_saveCallback;
|
||||||
}
|
}
|
||||||
void refreshAboutAddAdminsText(bool canAddAdmins);
|
void refreshAboutAddAdminsText(bool canAddAdmins);
|
||||||
|
bool canTransferOwnership() const;
|
||||||
|
not_null<Ui::SlideWrap<Ui::RpWidget>*> setupTransferButton(bool isGroup);
|
||||||
|
|
||||||
const MTPChatAdminRights _oldRights;
|
const MTPChatAdminRights _oldRights;
|
||||||
Fn<void(MTPChatAdminRights, MTPChatAdminRights)> _saveCallback;
|
Fn<void(MTPChatAdminRights, MTPChatAdminRights)> _saveCallback;
|
||||||
|
|
||||||
QPointer<Ui::FlatLabel> _aboutAddAdmins;
|
QPointer<Ui::FlatLabel> _aboutAddAdmins;
|
||||||
|
mtpRequestId _checkTransferRequestId = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ std::vector<std::pair<ChatRestrictions, LangKey>> RestrictionLabels() {
|
||||||
const auto restrictions = Data::ListOfRestrictions();
|
const auto restrictions = Data::ListOfRestrictions();
|
||||||
auto i = 0;
|
auto i = 0;
|
||||||
for (const auto key : langKeys) {
|
for (const auto key : langKeys) {
|
||||||
vector.push_back({restrictions[i++], key});
|
vector.emplace_back(restrictions[i++], key);
|
||||||
}
|
}
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
@ -276,6 +276,14 @@ ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions) {
|
||||||
return restrictions;
|
return restrictions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatAdminRights FullAdminRights(bool isGroup) {
|
||||||
|
auto result = ChatAdminRights();
|
||||||
|
for (const auto &[flag, label] : AdminRightLabels(isGroup, true)) {
|
||||||
|
result |= flag;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
EditPeerPermissionsBox::EditPeerPermissionsBox(
|
EditPeerPermissionsBox::EditPeerPermissionsBox(
|
||||||
QWidget*,
|
QWidget*,
|
||||||
not_null<PeerData*> peer)
|
not_null<PeerData*> peer)
|
||||||
|
|
|
@ -58,3 +58,4 @@ EditFlagsControl<MTPDchatAdminRights::Flags> CreateEditAdminRights(
|
||||||
|
|
||||||
ChatAdminRights DisabledByDefaultRestrictions(not_null<PeerData*> peer);
|
ChatAdminRights DisabledByDefaultRestrictions(not_null<PeerData*> peer);
|
||||||
ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions);
|
ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions);
|
||||||
|
ChatAdminRights FullAdminRights(bool isGroup);
|
||||||
|
|
|
@ -133,7 +133,7 @@ TextWithEntities GenerateAdminChangeText(
|
||||||
|
|
||||||
auto newFlags = newRights ? newRights->c_chatAdminRights().vflags.v : MTPDchatAdminRights::Flags(0);
|
auto newFlags = newRights ? newRights->c_chatAdminRights().vflags.v : MTPDchatAdminRights::Flags(0);
|
||||||
auto prevFlags = prevRights ? prevRights->c_chatAdminRights().vflags.v : MTPDchatAdminRights::Flags(0);
|
auto prevFlags = prevRights ? prevRights->c_chatAdminRights().vflags.v : MTPDchatAdminRights::Flags(0);
|
||||||
auto result = lng_admin_log_promoted__generic(lt_user, user);
|
auto result = lng_admin_log_promoted__rich(lt_user, user);
|
||||||
|
|
||||||
auto useInviteLinkPhrase = channel->isMegagroup() && channel->anyoneCanAddMembers();
|
auto useInviteLinkPhrase = channel->isMegagroup() && channel->anyoneCanAddMembers();
|
||||||
auto invitePhrase = (useInviteLinkPhrase ? lng_admin_log_admin_invite_link : lng_admin_log_admin_invite_users);
|
auto invitePhrase = (useInviteLinkPhrase ? lng_admin_log_admin_invite_link : lng_admin_log_admin_invite_users);
|
||||||
|
@ -201,14 +201,14 @@ TextWithEntities GenerateBannedChangeText(
|
||||||
auto newUntil = newRights ? newRights->c_chatBannedRights().vuntil_date.v : TimeId(0);
|
auto newUntil = newRights ? newRights->c_chatBannedRights().vuntil_date.v : TimeId(0);
|
||||||
auto indefinitely = ChannelData::IsRestrictedForever(newUntil);
|
auto indefinitely = ChannelData::IsRestrictedForever(newUntil);
|
||||||
if (newFlags & Flag::f_view_messages) {
|
if (newFlags & Flag::f_view_messages) {
|
||||||
return lng_admin_log_banned__generic(lt_user, user);
|
return lng_admin_log_banned__rich(lt_user, user);
|
||||||
}
|
}
|
||||||
auto untilText = indefinitely
|
auto untilText = indefinitely
|
||||||
? lang(lng_admin_log_restricted_forever)
|
? lang(lng_admin_log_restricted_forever)
|
||||||
: lng_admin_log_restricted_until(
|
: lng_admin_log_restricted_until(
|
||||||
lt_date,
|
lt_date,
|
||||||
langDateTime(ParseDateTime(newUntil)));
|
langDateTime(ParseDateTime(newUntil)));
|
||||||
auto result = lng_admin_log_restricted__generic(
|
auto result = lng_admin_log_restricted__rich(
|
||||||
lt_user,
|
lt_user,
|
||||||
user,
|
user,
|
||||||
lt_until,
|
lt_until,
|
||||||
|
@ -241,7 +241,7 @@ auto GenerateUserString(MTPint userId) {
|
||||||
EntityType::Mention,
|
EntityType::Mention,
|
||||||
0,
|
0,
|
||||||
mention.text.size() });
|
mention.text.size() });
|
||||||
return lng_admin_log_user_with_username__generic(lt_name, name, lt_mention, mention);
|
return lng_admin_log_user_with_username__rich(lt_name, name, lt_mention, mention);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GenerateParticipantChangeTextInner(
|
auto GenerateParticipantChangeTextInner(
|
||||||
|
@ -251,7 +251,7 @@ auto GenerateParticipantChangeTextInner(
|
||||||
const auto oldType = oldParticipant ? oldParticipant->type() : 0;
|
const auto oldType = oldParticipant ? oldParticipant->type() : 0;
|
||||||
return participant.match([&](const MTPDchannelParticipantCreator &data) {
|
return participant.match([&](const MTPDchannelParticipantCreator &data) {
|
||||||
// No valid string here :(
|
// No valid string here :(
|
||||||
return lng_admin_log_invited__generic(
|
return lng_admin_log_invited__rich(
|
||||||
lt_user,
|
lt_user,
|
||||||
GenerateUserString(data.vuser_id));
|
GenerateUserString(data.vuser_id));
|
||||||
}, [&](const MTPDchannelParticipantAdmin &data) {
|
}, [&](const MTPDchannelParticipantAdmin &data) {
|
||||||
|
@ -285,7 +285,7 @@ auto GenerateParticipantChangeTextInner(
|
||||||
nullptr,
|
nullptr,
|
||||||
&oldParticipant->c_channelParticipantBanned().vbanned_rights);
|
&oldParticipant->c_channelParticipantBanned().vbanned_rights);
|
||||||
}
|
}
|
||||||
return lng_admin_log_invited__generic(lt_user, user);
|
return lng_admin_log_invited__rich(lt_user, user);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "ui/wrap/padding_wrap.h"
|
#include "ui/wrap/padding_wrap.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
#include "lang/lang_file_parser.h"
|
#include "lang/lang_file_parser.h"
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
#include "core/click_handler_types.h"
|
#include "core/click_handler_types.h"
|
||||||
|
@ -72,42 +73,23 @@ ConfirmSwitchBox::ConfirmSwitchBox(
|
||||||
void ConfirmSwitchBox::prepare() {
|
void ConfirmSwitchBox::prepare() {
|
||||||
setTitle(langFactory(lng_language_switch_title));
|
setTitle(langFactory(lng_language_switch_title));
|
||||||
|
|
||||||
auto link = TextWithEntities{ lang(lng_language_switch_link) };
|
|
||||||
link.entities.push_back({
|
|
||||||
EntityType::CustomUrl,
|
|
||||||
0,
|
|
||||||
link.text.size(),
|
|
||||||
QString("internal:go_to_translations") });
|
|
||||||
auto name = TextWithEntities{ _name };
|
|
||||||
name.entities.push_back({
|
|
||||||
EntityType::Bold,
|
|
||||||
0,
|
|
||||||
name.text.size() });
|
|
||||||
auto percent = TextWithEntities{ QString::number(_percent) };
|
|
||||||
percent.entities.push_back({
|
|
||||||
EntityType::Bold,
|
|
||||||
0,
|
|
||||||
percent.text.size() });
|
|
||||||
const auto text = (_official
|
const auto text = (_official
|
||||||
? lng_language_switch_about_official__rich
|
? lng_language_switch_about_official__rich
|
||||||
: lng_language_switch_about_unofficial__rich)(
|
: lng_language_switch_about_unofficial__rich)(
|
||||||
lt_lang_name,
|
lt_lang_name,
|
||||||
name,
|
Ui::Text::Bold(_name),
|
||||||
lt_percent,
|
lt_percent,
|
||||||
percent,
|
Ui::Text::Bold(QString::number(_percent)),
|
||||||
lt_link,
|
lt_link,
|
||||||
link);
|
Ui::Text::Link(lang(lng_language_switch_link), _editLink));
|
||||||
auto content = Ui::CreateChild<Ui::PaddingWrap<Ui::FlatLabel>>(
|
const auto content = Ui::CreateChild<Ui::PaddingWrap<Ui::FlatLabel>>(
|
||||||
this,
|
this,
|
||||||
object_ptr<Ui::FlatLabel>(
|
object_ptr<Ui::FlatLabel>(
|
||||||
this,
|
this,
|
||||||
rpl::single(text),
|
rpl::single(text),
|
||||||
st::boxLabel),
|
st::boxLabel),
|
||||||
QMargins{ st::boxPadding.left(), 0, st::boxPadding.right(), 0 });
|
QMargins{ st::boxPadding.left(), 0, st::boxPadding.right(), 0 });
|
||||||
content->entity()->setClickHandlerFilter([=](auto&&...) {
|
content->entity()->setLinksTrusted();
|
||||||
UrlClickHandler::Open(_editLink);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
addButton(langFactory(lng_language_switch_apply), [=] {
|
addButton(langFactory(lng_language_switch_apply), [=] {
|
||||||
const auto apply = _apply;
|
const auto apply = _apply;
|
||||||
|
@ -133,29 +115,19 @@ NotReadyBox::NotReadyBox(
|
||||||
void NotReadyBox::prepare() {
|
void NotReadyBox::prepare() {
|
||||||
setTitle(langFactory(lng_language_not_ready_title));
|
setTitle(langFactory(lng_language_not_ready_title));
|
||||||
|
|
||||||
auto link = TextWithEntities{ lang(lng_language_not_ready_link) };
|
const auto text = lng_language_not_ready_about__rich(
|
||||||
link.entities.push_back({
|
|
||||||
EntityType::CustomUrl,
|
|
||||||
0,
|
|
||||||
link.text.size(),
|
|
||||||
QString("internal:go_to_translations") });
|
|
||||||
auto name = TextWithEntities{ _name };
|
|
||||||
const auto text = lng_language_not_ready_about__generic(
|
|
||||||
lt_lang_name,
|
lt_lang_name,
|
||||||
name,
|
TextWithEntities{ _name },
|
||||||
lt_link,
|
lt_link,
|
||||||
link);
|
Ui::Text::Link(lang(lng_language_not_ready_link), _editLink));
|
||||||
auto content = Ui::CreateChild<Ui::PaddingWrap<Ui::FlatLabel>>(
|
const auto content = Ui::CreateChild<Ui::PaddingWrap<Ui::FlatLabel>>(
|
||||||
this,
|
this,
|
||||||
object_ptr<Ui::FlatLabel>(
|
object_ptr<Ui::FlatLabel>(
|
||||||
this,
|
this,
|
||||||
rpl::single(text),
|
rpl::single(text),
|
||||||
st::boxLabel),
|
st::boxLabel),
|
||||||
QMargins{ st::boxPadding.left(), 0, st::boxPadding.right(), 0 });
|
QMargins{ st::boxPadding.left(), 0, st::boxPadding.right(), 0 });
|
||||||
content->entity()->setClickHandlerFilter([=](auto&&...) {
|
content->entity()->setLinksTrusted();
|
||||||
UrlClickHandler::Open(_editLink);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
addButton(langFactory(lng_box_ok), [=] { closeBox(); });
|
addButton(langFactory(lng_box_ok), [=] { closeBox(); });
|
||||||
|
|
||||||
|
|
|
@ -238,82 +238,6 @@ void SetupLocalPasscode(not_null<Ui::VerticalLayout*> container) {
|
||||||
AddSkip(container);
|
AddSkip(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckEditCloudPassword() {
|
|
||||||
const auto current = Auth().api().passwordStateCurrent();
|
|
||||||
Assert(current.has_value());
|
|
||||||
if (!current->unknownAlgorithm
|
|
||||||
&& current->newPassword
|
|
||||||
&& current->newSecureSecret) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
auto box = std::make_shared<QPointer<BoxContent>>();
|
|
||||||
const auto callback = [=] {
|
|
||||||
Core::UpdateApplication();
|
|
||||||
if (*box) (*box)->closeBox();
|
|
||||||
};
|
|
||||||
*box = Ui::show(Box<ConfirmBox>(
|
|
||||||
lang(lng_passport_app_out_of_date),
|
|
||||||
lang(lng_menu_update),
|
|
||||||
callback));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditCloudPassword() {
|
|
||||||
const auto current = Auth().api().passwordStateCurrent();
|
|
||||||
Assert(current.has_value());
|
|
||||||
|
|
||||||
const auto box = Ui::show(Box<PasscodeBox>(
|
|
||||||
current->request,
|
|
||||||
current->newPassword,
|
|
||||||
current->hasRecovery,
|
|
||||||
current->notEmptyPassport,
|
|
||||||
current->hint,
|
|
||||||
current->newSecureSecret));
|
|
||||||
|
|
||||||
rpl::merge(
|
|
||||||
box->newPasswordSet() | rpl::map([] { return rpl::empty_value(); }),
|
|
||||||
box->passwordReloadNeeded()
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
Auth().api().reloadPasswordState();
|
|
||||||
}, box->lifetime());
|
|
||||||
|
|
||||||
box->clearUnconfirmedPassword(
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
Auth().api().clearUnconfirmedPassword();
|
|
||||||
}, box->lifetime());
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveCloudPassword() {
|
|
||||||
const auto current = Auth().api().passwordStateCurrent();
|
|
||||||
Assert(current.has_value());
|
|
||||||
|
|
||||||
if (!current->request) {
|
|
||||||
Auth().api().clearUnconfirmedPassword();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto box = Ui::show(Box<PasscodeBox>(
|
|
||||||
current->request,
|
|
||||||
current->newPassword,
|
|
||||||
current->hasRecovery,
|
|
||||||
current->notEmptyPassport,
|
|
||||||
current->hint,
|
|
||||||
current->newSecureSecret,
|
|
||||||
true));
|
|
||||||
|
|
||||||
rpl::merge(
|
|
||||||
box->newPasswordSet(
|
|
||||||
) | rpl::map([] { return rpl::empty_value(); }),
|
|
||||||
box->passwordReloadNeeded()
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
Auth().api().reloadPasswordState();
|
|
||||||
}, box->lifetime());
|
|
||||||
|
|
||||||
box->clearUnconfirmedPassword(
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
Auth().api().clearUnconfirmedPassword();
|
|
||||||
}, box->lifetime());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupCloudPassword(not_null<Ui::VerticalLayout*> container) {
|
void SetupCloudPassword(not_null<Ui::VerticalLayout*> container) {
|
||||||
using namespace rpl::mappers;
|
using namespace rpl::mappers;
|
||||||
using State = Core::CloudPasswordState;
|
using State = Core::CloudPasswordState;
|
||||||
|
@ -396,7 +320,9 @@ void SetupCloudPassword(not_null<Ui::VerticalLayout*> container) {
|
||||||
))->setDuration(0);
|
))->setDuration(0);
|
||||||
change->entity()->addClickHandler([] {
|
change->entity()->addClickHandler([] {
|
||||||
if (CheckEditCloudPassword()) {
|
if (CheckEditCloudPassword()) {
|
||||||
EditCloudPassword();
|
Ui::show(EditCloudPasswordBox(&Auth()));
|
||||||
|
} else {
|
||||||
|
Ui::show(CloudPasswordAppOutdatedBox());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -437,6 +363,8 @@ void SetupCloudPassword(not_null<Ui::VerticalLayout*> container) {
|
||||||
const auto remove = [] {
|
const auto remove = [] {
|
||||||
if (CheckEditCloudPassword()) {
|
if (CheckEditCloudPassword()) {
|
||||||
RemoveCloudPassword();
|
RemoveCloudPassword();
|
||||||
|
} else {
|
||||||
|
Ui::show(CloudPasswordAppOutdatedBox());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const auto disable = container->add(
|
const auto disable = container->add(
|
||||||
|
@ -537,6 +465,91 @@ int ExceptionUsersCount(const std::vector<not_null<PeerData*>> &exceptions) {
|
||||||
return ranges::accumulate(exceptions, 0, add);
|
return ranges::accumulate(exceptions, 0, add);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckEditCloudPassword() {
|
||||||
|
const auto current = Auth().api().passwordStateCurrent();
|
||||||
|
Assert(current.has_value());
|
||||||
|
|
||||||
|
if (!current->unknownAlgorithm
|
||||||
|
&& current->newPassword
|
||||||
|
&& current->newSecureSecret) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ptr<BoxContent> EditCloudPasswordBox(not_null<AuthSession*> session) {
|
||||||
|
const auto current = session->api().passwordStateCurrent();
|
||||||
|
Assert(current.has_value());
|
||||||
|
|
||||||
|
auto result = Box<PasscodeBox>(
|
||||||
|
current->request,
|
||||||
|
current->newPassword,
|
||||||
|
current->hasRecovery,
|
||||||
|
current->notEmptyPassport,
|
||||||
|
current->hint,
|
||||||
|
current->newSecureSecret);
|
||||||
|
const auto box = result.data();
|
||||||
|
|
||||||
|
rpl::merge(
|
||||||
|
box->newPasswordSet() | rpl::map([] { return rpl::empty_value(); }),
|
||||||
|
box->passwordReloadNeeded()
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
session->api().reloadPasswordState();
|
||||||
|
}, box->lifetime());
|
||||||
|
|
||||||
|
box->clearUnconfirmedPassword(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
session->api().clearUnconfirmedPassword();
|
||||||
|
}, box->lifetime());
|
||||||
|
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveCloudPassword() {
|
||||||
|
const auto current = Auth().api().passwordStateCurrent();
|
||||||
|
Assert(current.has_value());
|
||||||
|
|
||||||
|
if (!current->request) {
|
||||||
|
Auth().api().clearUnconfirmedPassword();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto box = Ui::show(Box<PasscodeBox>(
|
||||||
|
current->request,
|
||||||
|
current->newPassword,
|
||||||
|
current->hasRecovery,
|
||||||
|
current->notEmptyPassport,
|
||||||
|
current->hint,
|
||||||
|
current->newSecureSecret,
|
||||||
|
true));
|
||||||
|
|
||||||
|
rpl::merge(
|
||||||
|
box->newPasswordSet(
|
||||||
|
) | rpl::map([] { return rpl::empty_value(); }),
|
||||||
|
box->passwordReloadNeeded()
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
Auth().api().reloadPasswordState();
|
||||||
|
}, box->lifetime());
|
||||||
|
|
||||||
|
box->clearUnconfirmedPassword(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
Auth().api().clearUnconfirmedPassword();
|
||||||
|
}, box->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ptr<BoxContent> CloudPasswordAppOutdatedBox() {
|
||||||
|
auto box = std::make_shared<QPointer<BoxContent>>();
|
||||||
|
const auto callback = [=] {
|
||||||
|
Core::UpdateApplication();
|
||||||
|
if (*box) (*box)->closeBox();
|
||||||
|
};
|
||||||
|
auto result = Box<ConfirmBox>(
|
||||||
|
lang(lng_passport_app_out_of_date),
|
||||||
|
lang(lng_menu_update),
|
||||||
|
callback);
|
||||||
|
*box = result.data();
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
void AddPrivacyButton(
|
void AddPrivacyButton(
|
||||||
not_null<Ui::VerticalLayout*> container,
|
not_null<Ui::VerticalLayout*> container,
|
||||||
LangKey label,
|
LangKey label,
|
||||||
|
|
|
@ -16,6 +16,11 @@ namespace Settings {
|
||||||
|
|
||||||
int ExceptionUsersCount(const std::vector<not_null<PeerData*>> &exceptions);
|
int ExceptionUsersCount(const std::vector<not_null<PeerData*>> &exceptions);
|
||||||
|
|
||||||
|
bool CheckEditCloudPassword();
|
||||||
|
object_ptr<BoxContent> EditCloudPasswordBox(not_null<AuthSession*> session);
|
||||||
|
void RemoveCloudPassword();
|
||||||
|
object_ptr<BoxContent> CloudPasswordAppOutdatedBox();
|
||||||
|
|
||||||
void AddPrivacyButton(
|
void AddPrivacyButton(
|
||||||
not_null<Ui::VerticalLayout*> container,
|
not_null<Ui::VerticalLayout*> container,
|
||||||
LangKey label,
|
LangKey label,
|
||||||
|
|
|
@ -552,8 +552,6 @@ void LayerStackWidget::startAnimation(
|
||||||
ClearOld clearOldWidgets,
|
ClearOld clearOldWidgets,
|
||||||
Action action,
|
Action action,
|
||||||
anim::type animated) {
|
anim::type animated) {
|
||||||
if (App::quitting()) return;
|
|
||||||
|
|
||||||
if (animated == anim::type::instant) {
|
if (animated == anim::type::instant) {
|
||||||
setupNewWidgets();
|
setupNewWidgets();
|
||||||
clearOldWidgets();
|
clearOldWidgets();
|
||||||
|
@ -845,7 +843,13 @@ void LayerStackWidget::sendFakeMouseEvent() {
|
||||||
sendSynteticMouseEvent(this, QEvent::MouseMove, Qt::NoButton);
|
sendSynteticMouseEvent(this, QEvent::MouseMove, Qt::NoButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerStackWidget::~LayerStackWidget() = default;
|
LayerStackWidget::~LayerStackWidget() {
|
||||||
|
// Some layer destructors call back into LayerStackWidget.
|
||||||
|
while (!_layers.empty() || !_closingLayers.empty()) {
|
||||||
|
hideAll(anim::type::instant);
|
||||||
|
clearClosingLayers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue