mirror of https://github.com/procxx/kepka.git
Added GroupTypeBox with Controller.
This commit is contained in:
parent
d06337dddc
commit
be8aed6a95
|
@ -805,8 +805,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_manage_peer_permissions" = "Permissions";
|
"lng_manage_peer_permissions" = "Permissions";
|
||||||
|
|
||||||
"lng_manage_peer_group_type" = "Group type";
|
"lng_manage_peer_group_type" = "Group type";
|
||||||
"lng_manage_private_group_title" = "Private";
|
"lng_manage_peer_channel_type" = "Channel type";
|
||||||
"lng_manage_public_group_title" = "Public";
|
"lng_manage_private_peer_title" = "Private";
|
||||||
|
"lng_manage_public_peer_title" = "Public";
|
||||||
|
|
||||||
"lng_manage_history_visibility_title" = "Chat history for new members";
|
"lng_manage_history_visibility_title" = "Chat history for new members";
|
||||||
"lng_manage_history_visibility_shown" = "Visible";
|
"lng_manage_history_visibility_shown" = "Visible";
|
||||||
|
|
|
@ -0,0 +1,810 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
#include "boxes/peers/edit_peer_group_type_box.h"
|
||||||
|
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "boxes/add_contact_box.h"
|
||||||
|
#include "boxes/add_contact_box.h"
|
||||||
|
#include "boxes/confirm_box.h"
|
||||||
|
#include "boxes/confirm_box.h"
|
||||||
|
#include "boxes/peer_list_controllers.h"
|
||||||
|
#include "boxes/peer_list_controllers.h"
|
||||||
|
#include "boxes/peers/edit_participants_box.h"
|
||||||
|
#include "boxes/peers/edit_participants_box.h"
|
||||||
|
#include "boxes/peers/edit_participants_box.h"
|
||||||
|
#include "boxes/peers/edit_peer_group_type_box.h"
|
||||||
|
#include "boxes/peers/edit_peer_history_visibility_box.h"
|
||||||
|
#include "boxes/peers/edit_peer_info_box.h"
|
||||||
|
#include "boxes/peers/edit_peer_permissions_box.h"
|
||||||
|
#include "boxes/peers/edit_peer_permissions_box.h"
|
||||||
|
#include "boxes/photo_crop_box.h"
|
||||||
|
#include "boxes/stickers_box.h"
|
||||||
|
#include "boxes/stickers_box.h"
|
||||||
|
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||||
|
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||||
|
#include "core/application.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
|
#include "data/data_chat.h"
|
||||||
|
#include "data/data_chat.h"
|
||||||
|
#include "data/data_chat.h"
|
||||||
|
#include "data/data_peer.h"
|
||||||
|
#include "data/data_peer.h"
|
||||||
|
#include "history/admin_log/history_admin_log_section.h"
|
||||||
|
#include "history/admin_log/history_admin_log_section.h"
|
||||||
|
#include "info/profile/info_profile_button.h"
|
||||||
|
#include "info/profile/info_profile_button.h"
|
||||||
|
#include "info/profile/info_profile_button.h"
|
||||||
|
#include "info/profile/info_profile_icon.h"
|
||||||
|
#include "info/profile/info_profile_values.h"
|
||||||
|
#include "info/profile/info_profile_values.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "mtproto/sender.h"
|
||||||
|
#include "mtproto/sender.h"
|
||||||
|
#include "observer_peer.h"
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
|
#include "ui/special_buttons.h"
|
||||||
|
#include "ui/special_buttons.h"
|
||||||
|
#include "ui/toast/toast.h"
|
||||||
|
#include "ui/toast/toast.h"
|
||||||
|
#include "ui/widgets/checkbox.h"
|
||||||
|
#include "ui/widgets/checkbox.h"
|
||||||
|
#include "ui/widgets/checkbox.h"
|
||||||
|
#include "ui/widgets/input_fields.h"
|
||||||
|
#include "ui/widgets/input_fields.h"
|
||||||
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "ui/wrap/padding_wrap.h"
|
||||||
|
#include "ui/wrap/padding_wrap.h"
|
||||||
|
#include "ui/wrap/slide_wrap.h"
|
||||||
|
#include "ui/wrap/slide_wrap.h"
|
||||||
|
#include "ui/wrap/vertical_layout.h"
|
||||||
|
#include "ui/wrap/vertical_layout.h"
|
||||||
|
#include "ui/wrap/vertical_layout.h"
|
||||||
|
#include "window/window_controller.h"
|
||||||
|
#include "window/window_controller.h"
|
||||||
|
#include <rpl/combine.h>
|
||||||
|
#include <rpl/flatten_latest.h>
|
||||||
|
#include <rpl/flatten_latest.h>
|
||||||
|
#include <rpl/range.h>
|
||||||
|
#include <rpl/range.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_dialogs.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "mtproto/sender.h"
|
||||||
|
#include "base/flat_set.h"
|
||||||
|
#include "boxes/confirm_box.h"
|
||||||
|
#include "boxes/photo_crop_box.h"
|
||||||
|
#include "boxes/peer_list_controllers.h"
|
||||||
|
#include "boxes/peers/add_participants_box.h"
|
||||||
|
#include "boxes/peers/edit_participant_box.h"
|
||||||
|
#include "boxes/peers/edit_participants_box.h"
|
||||||
|
#include "core/file_utilities.h"
|
||||||
|
#include "core/application.h"
|
||||||
|
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||||
|
#include "ui/widgets/checkbox.h"
|
||||||
|
#include "ui/widgets/buttons.h"
|
||||||
|
#include "ui/widgets/input_fields.h"
|
||||||
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "ui/toast/toast.h"
|
||||||
|
#include "ui/special_buttons.h"
|
||||||
|
#include "ui/text_options.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
|
#include "data/data_chat.h"
|
||||||
|
#include "data/data_user.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "observer_peer.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
|
||||||
|
std::optional<Privacy> privacySavedValue;
|
||||||
|
std::optional<QString> usernameSavedValue;
|
||||||
|
|
||||||
|
std::shared_ptr<Ui::RadioenumGroup<Privacy>> privacyButtons;
|
||||||
|
Ui::SlideWrap<Ui::RpWidget> *usernameWrap = nullptr;
|
||||||
|
Ui::UsernameInput *usernameInput = nullptr;
|
||||||
|
base::unique_qptr<Ui::FlatLabel> usernameResult;
|
||||||
|
const style::FlatLabel *usernameResultStyle = nullptr;
|
||||||
|
|
||||||
|
Ui::SlideWrap<Ui::RpWidget> *createInviteLinkWrap = nullptr;
|
||||||
|
// Ui::SlideWrap<Ui::RpWidget> *_editInviteLinkWrap = nullptr;
|
||||||
|
Ui::FlatLabel *inviteLink = nullptr;
|
||||||
|
|
||||||
|
PeerData *peer = nullptr;
|
||||||
|
|
||||||
|
bool allowSave = false;
|
||||||
|
|
||||||
|
|
||||||
|
mtpRequestId _checkUsernameRequestId = 0;
|
||||||
|
UsernameState _usernameState = UsernameState::Normal;
|
||||||
|
rpl::event_stream<rpl::producer<QString>> _usernameResultTexts;
|
||||||
|
|
||||||
|
bool isGroup = false;
|
||||||
|
|
||||||
|
void AddRoundButton(
|
||||||
|
not_null<Ui::VerticalLayout*> container,
|
||||||
|
Privacy value,
|
||||||
|
LangKey groupTextKey,
|
||||||
|
LangKey channelTextKey,
|
||||||
|
LangKey groupAboutKey,
|
||||||
|
LangKey channelAboutKey) {
|
||||||
|
container->add(object_ptr<Ui::Radioenum<Privacy>>(
|
||||||
|
container,
|
||||||
|
privacyButtons,
|
||||||
|
value,
|
||||||
|
lang(isGroup ? groupTextKey : channelTextKey),
|
||||||
|
st::defaultBoxCheckbox));
|
||||||
|
container->add(object_ptr<Ui::PaddingWrap<Ui::FlatLabel>>(
|
||||||
|
container,
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
container,
|
||||||
|
Lang::Viewer(isGroup ? groupAboutKey : channelAboutKey),
|
||||||
|
st::editPeerPrivacyLabel),
|
||||||
|
st::editPeerPrivacyLabelMargins));
|
||||||
|
container->add(object_ptr<Ui::FixedHeightWidget>(
|
||||||
|
container,
|
||||||
|
st::editPeerPrivacyBottomSkip));
|
||||||
|
};
|
||||||
|
|
||||||
|
void FillGroupedButtons(
|
||||||
|
not_null<Ui::VerticalLayout*> parent,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
std::optional<Privacy> savedValue = std::nullopt) {
|
||||||
|
|
||||||
|
const auto canEditUsername = [&] {
|
||||||
|
if (const auto chat = peer->asChat()) {
|
||||||
|
return chat->canEditUsername();
|
||||||
|
} else if (const auto channel = peer->asChannel()) {
|
||||||
|
return channel->canEditUsername();
|
||||||
|
}
|
||||||
|
Unexpected("Peer type in Controller::createPrivaciesEdit.");
|
||||||
|
}();
|
||||||
|
if (!canEditUsername) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto result = parent->add(object_ptr<Ui::PaddingWrap<Ui::VerticalLayout>>(
|
||||||
|
parent,
|
||||||
|
object_ptr<Ui::VerticalLayout>(parent),
|
||||||
|
st::editPeerPrivaciesMargins));
|
||||||
|
auto container = result->entity();
|
||||||
|
|
||||||
|
const auto isPublic = peer->isChannel()
|
||||||
|
&& peer->asChannel()->isPublic();
|
||||||
|
privacyButtons = std::make_shared<Ui::RadioenumGroup<Privacy>>(
|
||||||
|
savedValue.value_or(isPublic ? Privacy::Public : Privacy::Private));
|
||||||
|
|
||||||
|
AddRoundButton(
|
||||||
|
container,
|
||||||
|
Privacy::Public,
|
||||||
|
lng_create_public_group_title,
|
||||||
|
lng_create_public_channel_title,
|
||||||
|
lng_create_public_group_about,
|
||||||
|
lng_create_public_channel_about);
|
||||||
|
AddRoundButton(
|
||||||
|
container,
|
||||||
|
Privacy::Private,
|
||||||
|
lng_create_private_group_title,
|
||||||
|
lng_create_private_channel_title,
|
||||||
|
lng_create_private_group_about,
|
||||||
|
lng_create_private_channel_about);
|
||||||
|
|
||||||
|
// privacyButtons->setChangedCallback([this](Privacy value) {
|
||||||
|
// privacyChanged(value);
|
||||||
|
// });
|
||||||
|
if (!isPublic) {
|
||||||
|
// checkUsernameAvailability();
|
||||||
|
}
|
||||||
|
|
||||||
|
// return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FillContent(
|
||||||
|
not_null<Ui::VerticalLayout*> parent,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
std::optional<Privacy> savedValue = std::nullopt) {
|
||||||
|
|
||||||
|
FillGroupedButtons(parent, peer, savedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFocusUsername() {
|
||||||
|
if (usernameInput) {
|
||||||
|
usernameInput->setFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GetUsernameInput() {
|
||||||
|
return usernameInput->getLastText().trimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InviteLinkShown() {
|
||||||
|
return !privacyButtons
|
||||||
|
|| (privacyButtons->value() == Privacy::Private);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString InviteLinkText() {
|
||||||
|
if (const auto channel = peer->asChannel()) {
|
||||||
|
return channel->inviteLink();
|
||||||
|
} else if (const auto chat = peer->asChat()) {
|
||||||
|
return chat->inviteLink();
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kUsernameCheckTimeout = crl::time(200);
|
||||||
|
constexpr auto kMinUsernameLength = 5;
|
||||||
|
constexpr auto kMaxGroupChannelTitle = 255; // See also add_contact_box.
|
||||||
|
constexpr auto kMaxChannelDescription = 255; // See also add_contact_box.
|
||||||
|
|
||||||
|
class Controller
|
||||||
|
: public base::has_weak_ptr
|
||||||
|
, private MTP::Sender {
|
||||||
|
public:
|
||||||
|
Controller(
|
||||||
|
not_null<Ui::VerticalLayout*> container,
|
||||||
|
not_null<PeerData*> peer);
|
||||||
|
|
||||||
|
void createContent();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
object_ptr<Ui::RpWidget> createPrivaciesEdit();
|
||||||
|
object_ptr<Ui::RpWidget> createUsernameEdit();
|
||||||
|
object_ptr<Ui::RpWidget> createInviteLinkCreate();
|
||||||
|
object_ptr<Ui::RpWidget> createInviteLinkEdit();
|
||||||
|
|
||||||
|
void observeInviteLink();
|
||||||
|
|
||||||
|
void privacyChanged(Privacy value);
|
||||||
|
|
||||||
|
void checkUsernameAvailability();
|
||||||
|
void askUsernameRevoke();
|
||||||
|
void usernameChanged();
|
||||||
|
void showUsernameError(rpl::producer<QString> &&error);
|
||||||
|
void showUsernameGood();
|
||||||
|
void showUsernameResult(
|
||||||
|
rpl::producer<QString> &&text,
|
||||||
|
not_null<const style::FlatLabel*> st);
|
||||||
|
|
||||||
|
bool canEditInviteLink() const;
|
||||||
|
void refreshEditInviteLink();
|
||||||
|
void refreshCreateInviteLink();
|
||||||
|
void createInviteLink();
|
||||||
|
void revokeInviteLink();
|
||||||
|
void exportInviteLink(const QString &confirmation);
|
||||||
|
|
||||||
|
void subscribeToMigration();
|
||||||
|
void migrate(not_null<ChannelData*> channel);
|
||||||
|
|
||||||
|
not_null<PeerData*> _peer;
|
||||||
|
bool _isGroup = false;
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::VerticalLayout> _wrap;
|
||||||
|
base::Timer _checkUsernameTimer;
|
||||||
|
mtpRequestId _checkUsernameRequestId = 0;
|
||||||
|
UsernameState _usernameState = UsernameState::Normal;
|
||||||
|
rpl::event_stream<rpl::producer<QString>> _usernameResultTexts;
|
||||||
|
|
||||||
|
Ui::SlideWrap<Ui::RpWidget> *_editInviteLinkWrap = nullptr;
|
||||||
|
|
||||||
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Controller::Controller(
|
||||||
|
not_null<Ui::VerticalLayout*> container,
|
||||||
|
not_null<PeerData*> peer)
|
||||||
|
: _peer(peer)
|
||||||
|
, _isGroup(_peer->isChat() || _peer->isMegagroup())
|
||||||
|
, _wrap(container)
|
||||||
|
, _checkUsernameTimer([=] { checkUsernameAvailability(); }) {
|
||||||
|
subscribeToMigration();
|
||||||
|
_peer->updateFull();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::subscribeToMigration() {
|
||||||
|
SubscribeToMigration(
|
||||||
|
_peer,
|
||||||
|
_lifetime,
|
||||||
|
[=](not_null<ChannelData*> channel) { migrate(channel); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::migrate(not_null<ChannelData*> channel) {
|
||||||
|
_peer = channel;
|
||||||
|
observeInviteLink();
|
||||||
|
_peer->updateFull();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::createContent() {
|
||||||
|
privacyButtons->setChangedCallback([this](Privacy value) {
|
||||||
|
privacyChanged(value);
|
||||||
|
});
|
||||||
|
if (privacyButtons->value() == Privacy::Private) {
|
||||||
|
checkUsernameAvailability();
|
||||||
|
}
|
||||||
|
|
||||||
|
// _wrap->add(createPrivaciesEdit());
|
||||||
|
_wrap->add(createInviteLinkCreate());
|
||||||
|
_wrap->add(createInviteLinkEdit());
|
||||||
|
_wrap->add(createUsernameEdit());
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
|
||||||
|
Expects(_wrap != nullptr);
|
||||||
|
|
||||||
|
const auto channel = _peer->asChannel();
|
||||||
|
const auto username = usernameSavedValue.value_or(channel ? channel->username : QString());
|
||||||
|
|
||||||
|
auto result = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
_wrap,
|
||||||
|
object_ptr<Ui::VerticalLayout>(_wrap),
|
||||||
|
st::editPeerUsernameMargins);
|
||||||
|
usernameWrap = result.data();
|
||||||
|
|
||||||
|
auto container = result->entity();
|
||||||
|
container->add(object_ptr<Ui::FlatLabel>(
|
||||||
|
container,
|
||||||
|
Lang::Viewer(lng_create_group_link),
|
||||||
|
st::editPeerSectionLabel));
|
||||||
|
auto placeholder = container->add(object_ptr<Ui::RpWidget>(
|
||||||
|
container));
|
||||||
|
placeholder->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
usernameInput = Ui::AttachParentChild(
|
||||||
|
container,
|
||||||
|
object_ptr<Ui::UsernameInput>(
|
||||||
|
container,
|
||||||
|
st::setupChannelLink,
|
||||||
|
Fn<QString()>(),
|
||||||
|
username,
|
||||||
|
true));
|
||||||
|
usernameInput->heightValue(
|
||||||
|
) | rpl::start_with_next([placeholder](int height) {
|
||||||
|
placeholder->resize(placeholder->width(), height);
|
||||||
|
}, placeholder->lifetime());
|
||||||
|
placeholder->widthValue(
|
||||||
|
) | rpl::start_with_next([this](int width) {
|
||||||
|
usernameInput->resize(
|
||||||
|
width,
|
||||||
|
usernameInput->height());
|
||||||
|
}, placeholder->lifetime());
|
||||||
|
usernameInput->move(placeholder->pos());
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
usernameInput,
|
||||||
|
&Ui::UsernameInput::changed,
|
||||||
|
[this] { usernameChanged(); });
|
||||||
|
|
||||||
|
auto shown = (privacyButtons->value() == Privacy::Public);
|
||||||
|
result->toggle(shown, anim::type::instant);
|
||||||
|
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::privacyChanged(Privacy value) {
|
||||||
|
auto toggleEditUsername = [&] {
|
||||||
|
usernameWrap->toggle(
|
||||||
|
(value == Privacy::Public),
|
||||||
|
anim::type::instant);
|
||||||
|
};
|
||||||
|
auto refreshVisibilities = [&] {
|
||||||
|
// Now first we need to hide that was shown.
|
||||||
|
// Otherwise box will change own Y position.
|
||||||
|
|
||||||
|
if (value == Privacy::Public) {
|
||||||
|
refreshCreateInviteLink();
|
||||||
|
refreshEditInviteLink();
|
||||||
|
toggleEditUsername();
|
||||||
|
|
||||||
|
usernameResult = nullptr;
|
||||||
|
checkUsernameAvailability();
|
||||||
|
} else {
|
||||||
|
toggleEditUsername();
|
||||||
|
refreshCreateInviteLink();
|
||||||
|
refreshEditInviteLink();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (value == Privacy::Public) {
|
||||||
|
if (_usernameState == UsernameState::TooMany) {
|
||||||
|
askUsernameRevoke();
|
||||||
|
return;
|
||||||
|
} else if (_usernameState == UsernameState::NotAvailable) {
|
||||||
|
privacyButtons->setValue(Privacy::Private);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refreshVisibilities();
|
||||||
|
usernameInput->setDisplayFocused(true);
|
||||||
|
SetFocusUsername();
|
||||||
|
// _box->scrollToWidget(usernameInput);
|
||||||
|
} else {
|
||||||
|
request(base::take(_checkUsernameRequestId)).cancel();
|
||||||
|
_checkUsernameTimer.cancel();
|
||||||
|
refreshVisibilities();
|
||||||
|
SetFocusUsername();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::checkUsernameAvailability() {
|
||||||
|
if (!usernameInput) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto initial = (privacyButtons->value() != Privacy::Public);
|
||||||
|
auto checking = initial
|
||||||
|
? qsl(".bad.")
|
||||||
|
: GetUsernameInput();
|
||||||
|
if (checking.size() < kMinUsernameLength) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_checkUsernameRequestId) {
|
||||||
|
request(_checkUsernameRequestId).cancel();
|
||||||
|
}
|
||||||
|
const auto channel = _peer->migrateToOrMe()->asChannel();
|
||||||
|
const auto username = channel ? channel->username : QString();
|
||||||
|
_checkUsernameRequestId = request(MTPchannels_CheckUsername(
|
||||||
|
channel ? channel->inputChannel : MTP_inputChannelEmpty(),
|
||||||
|
MTP_string(checking)
|
||||||
|
)).done([=](const MTPBool &result) {
|
||||||
|
_checkUsernameRequestId = 0;
|
||||||
|
if (initial) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mtpIsTrue(result) && checking != username) {
|
||||||
|
showUsernameError(
|
||||||
|
Lang::Viewer(lng_create_channel_link_occupied));
|
||||||
|
} else {
|
||||||
|
showUsernameGood();
|
||||||
|
}
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
_checkUsernameRequestId = 0;
|
||||||
|
const auto &type = error.type();
|
||||||
|
_usernameState = UsernameState::Normal;
|
||||||
|
if (type == qstr("CHANNEL_PUBLIC_GROUP_NA")) {
|
||||||
|
_usernameState = UsernameState::NotAvailable;
|
||||||
|
privacyButtons->setValue(Privacy::Private);
|
||||||
|
} else if (type == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) {
|
||||||
|
_usernameState = UsernameState::TooMany;
|
||||||
|
if (privacyButtons->value() == Privacy::Public) {
|
||||||
|
askUsernameRevoke();
|
||||||
|
}
|
||||||
|
} else if (initial) {
|
||||||
|
if (privacyButtons->value() == Privacy::Public) {
|
||||||
|
usernameResult = nullptr;
|
||||||
|
SetFocusUsername();
|
||||||
|
// _box->scrollToWidget(usernameInput);
|
||||||
|
}
|
||||||
|
} else if (type == qstr("USERNAME_INVALID")) {
|
||||||
|
showUsernameError(
|
||||||
|
Lang::Viewer(lng_create_channel_link_invalid));
|
||||||
|
} else if (type == qstr("USERNAME_OCCUPIED")
|
||||||
|
&& checking != username) {
|
||||||
|
showUsernameError(
|
||||||
|
Lang::Viewer(lng_create_channel_link_occupied));
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::askUsernameRevoke() {
|
||||||
|
privacyButtons->setValue(Privacy::Private);
|
||||||
|
auto revokeCallback = crl::guard(this, [this] {
|
||||||
|
_usernameState = UsernameState::Normal;
|
||||||
|
privacyButtons->setValue(Privacy::Public);
|
||||||
|
checkUsernameAvailability();
|
||||||
|
});
|
||||||
|
Ui::show(
|
||||||
|
Box<RevokePublicLinkBox>(std::move(revokeCallback)),
|
||||||
|
LayerOption::KeepOther);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::usernameChanged() {
|
||||||
|
allowSave = false;
|
||||||
|
auto username = GetUsernameInput();
|
||||||
|
if (username.isEmpty()) {
|
||||||
|
usernameResult = nullptr;
|
||||||
|
_checkUsernameTimer.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto bad = ranges::find_if(username, [](QChar ch) {
|
||||||
|
return (ch < 'A' || ch > 'Z')
|
||||||
|
&& (ch < 'a' || ch > 'z')
|
||||||
|
&& (ch < '0' || ch > '9')
|
||||||
|
&& (ch != '_');
|
||||||
|
}) != username.end();
|
||||||
|
if (bad) {
|
||||||
|
showUsernameError(
|
||||||
|
Lang::Viewer(lng_create_channel_link_bad_symbols));
|
||||||
|
} else if (username.size() < kMinUsernameLength) {
|
||||||
|
showUsernameError(
|
||||||
|
Lang::Viewer(lng_create_channel_link_too_short));
|
||||||
|
} else {
|
||||||
|
usernameResult = nullptr;
|
||||||
|
_checkUsernameTimer.callOnce(kUsernameCheckTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::showUsernameError(rpl::producer<QString> &&error) {
|
||||||
|
showUsernameResult(std::move(error), &st::editPeerUsernameError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::showUsernameGood() {
|
||||||
|
allowSave = true;
|
||||||
|
showUsernameResult(
|
||||||
|
Lang::Viewer(lng_create_channel_link_available),
|
||||||
|
&st::editPeerUsernameGood);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::showUsernameResult(
|
||||||
|
rpl::producer<QString> &&text,
|
||||||
|
not_null<const style::FlatLabel*> st) {
|
||||||
|
if (!usernameResult
|
||||||
|
|| usernameResultStyle != st) {
|
||||||
|
usernameResultStyle = st;
|
||||||
|
usernameResult = base::make_unique_q<Ui::FlatLabel>(
|
||||||
|
usernameWrap,
|
||||||
|
_usernameResultTexts.events() | rpl::flatten_latest(),
|
||||||
|
*st);
|
||||||
|
auto label = 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::createInviteLink() {
|
||||||
|
exportInviteLink(lang(_isGroup
|
||||||
|
? lng_group_invite_about
|
||||||
|
: lng_group_invite_about_channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::revokeInviteLink() {
|
||||||
|
exportInviteLink(lang(lng_group_invite_about_new));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::exportInviteLink(const QString &confirmation) {
|
||||||
|
auto boxPointer = std::make_shared<QPointer<ConfirmBox>>();
|
||||||
|
auto callback = crl::guard(this, [=] {
|
||||||
|
if (const auto strong = *boxPointer) {
|
||||||
|
strong->closeBox();
|
||||||
|
}
|
||||||
|
_peer->session().api().exportInviteLink(_peer->migrateToOrMe());
|
||||||
|
});
|
||||||
|
auto box = Box<ConfirmBox>(
|
||||||
|
confirmation,
|
||||||
|
std::move(callback));
|
||||||
|
*boxPointer = Ui::show(std::move(box), LayerOption::KeepOther);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Controller::canEditInviteLink() const {
|
||||||
|
if (const auto channel = _peer->asChannel()) {
|
||||||
|
return channel->amCreator()
|
||||||
|
|| (channel->adminRights() & ChatAdminRight::f_invite_users);
|
||||||
|
} else if (const auto chat = _peer->asChat()) {
|
||||||
|
return chat->amCreator()
|
||||||
|
|| (chat->adminRights() & ChatAdminRight::f_invite_users);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::observeInviteLink() {
|
||||||
|
if (!_editInviteLinkWrap) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// return; //
|
||||||
|
Notify::PeerUpdateValue(
|
||||||
|
_peer,
|
||||||
|
Notify::PeerUpdate::Flag::InviteLinkChanged
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
refreshCreateInviteLink();
|
||||||
|
refreshEditInviteLink();
|
||||||
|
}, _editInviteLinkWrap->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ptr<Ui::RpWidget> Controller::createInviteLinkEdit() {
|
||||||
|
Expects(_wrap != nullptr);
|
||||||
|
|
||||||
|
if (!canEditInviteLink()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
_wrap,
|
||||||
|
object_ptr<Ui::VerticalLayout>(_wrap),
|
||||||
|
st::editPeerInviteLinkMargins);
|
||||||
|
_editInviteLinkWrap = result.data();
|
||||||
|
|
||||||
|
auto container = result->entity();
|
||||||
|
container->add(object_ptr<Ui::FlatLabel>(
|
||||||
|
container,
|
||||||
|
Lang::Viewer(lng_profile_invite_link_section),
|
||||||
|
st::editPeerSectionLabel));
|
||||||
|
container->add(object_ptr<Ui::FixedHeightWidget>(
|
||||||
|
container,
|
||||||
|
st::editPeerInviteLinkSkip));
|
||||||
|
|
||||||
|
inviteLink = container->add(object_ptr<Ui::FlatLabel>(
|
||||||
|
container,
|
||||||
|
st::editPeerInviteLink));
|
||||||
|
inviteLink->setSelectable(true);
|
||||||
|
inviteLink->setContextCopyText(QString());
|
||||||
|
inviteLink->setBreakEverywhere(true);
|
||||||
|
inviteLink->setClickHandlerFilter([=](auto&&...) {
|
||||||
|
QApplication::clipboard()->setText(InviteLinkText());
|
||||||
|
Ui::Toast::Show(lang(lng_group_invite_copied));
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
container->add(object_ptr<Ui::FixedHeightWidget>(
|
||||||
|
container,
|
||||||
|
st::editPeerInviteLinkSkip));
|
||||||
|
container->add(object_ptr<Ui::LinkButton>(
|
||||||
|
container,
|
||||||
|
lang(lng_group_invite_create_new),
|
||||||
|
st::editPeerInviteLinkButton)
|
||||||
|
)->addClickHandler([=] { revokeInviteLink(); });
|
||||||
|
|
||||||
|
observeInviteLink();
|
||||||
|
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::refreshEditInviteLink() {
|
||||||
|
auto link = InviteLinkText();
|
||||||
|
auto text = TextWithEntities();
|
||||||
|
if (!link.isEmpty()) {
|
||||||
|
text.text = link;
|
||||||
|
auto remove = qstr("https://");
|
||||||
|
if (text.text.startsWith(remove)) {
|
||||||
|
text.text.remove(0, remove.size());
|
||||||
|
}
|
||||||
|
text.entities.push_back(EntityInText(
|
||||||
|
EntityInTextCustomUrl,
|
||||||
|
0,
|
||||||
|
text.text.size(),
|
||||||
|
link));
|
||||||
|
}
|
||||||
|
inviteLink->setMarkedText(text);
|
||||||
|
|
||||||
|
// Hack to expand FlatLabel width to naturalWidth again.
|
||||||
|
_editInviteLinkWrap->resizeToWidth(st::boxWideWidth);
|
||||||
|
|
||||||
|
_editInviteLinkWrap->toggle(
|
||||||
|
InviteLinkShown() && !link.isEmpty(),
|
||||||
|
anim::type::instant);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ptr<Ui::RpWidget> Controller::createInviteLinkCreate() {
|
||||||
|
Expects(_wrap != nullptr);
|
||||||
|
|
||||||
|
if (!canEditInviteLink()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
_wrap,
|
||||||
|
object_ptr<Ui::VerticalLayout>(_wrap),
|
||||||
|
st::editPeerInviteLinkMargins);
|
||||||
|
auto container = result->entity();
|
||||||
|
|
||||||
|
container->add(object_ptr<Ui::FlatLabel>(
|
||||||
|
container,
|
||||||
|
Lang::Viewer(lng_profile_invite_link_section),
|
||||||
|
st::editPeerSectionLabel));
|
||||||
|
container->add(object_ptr<Ui::FixedHeightWidget>(
|
||||||
|
container,
|
||||||
|
st::editPeerInviteLinkSkip));
|
||||||
|
|
||||||
|
container->add(object_ptr<Ui::LinkButton>(
|
||||||
|
_wrap,
|
||||||
|
lang(lng_group_invite_create),
|
||||||
|
st::editPeerInviteLinkButton)
|
||||||
|
)->addClickHandler([this] {
|
||||||
|
createInviteLink();
|
||||||
|
});
|
||||||
|
createInviteLinkWrap = result.data();
|
||||||
|
|
||||||
|
observeInviteLink();
|
||||||
|
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::refreshCreateInviteLink() {
|
||||||
|
createInviteLinkWrap->toggle(
|
||||||
|
InviteLinkShown() && InviteLinkText().isEmpty(),
|
||||||
|
anim::type::instant);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
EditPeerGroupTypeBox::EditPeerGroupTypeBox(
|
||||||
|
QWidget*,
|
||||||
|
not_null<PeerData*> p,
|
||||||
|
FnMut<void(Privacy, QString)> savedCallback,
|
||||||
|
std::optional<Privacy> privacySaved,
|
||||||
|
std::optional<QString> usernameSaved)
|
||||||
|
: _peer(p)
|
||||||
|
, _savedCallback(std::move(savedCallback)) {
|
||||||
|
peer = p;
|
||||||
|
privacySavedValue = privacySaved;
|
||||||
|
usernameSavedValue = usernameSaved;
|
||||||
|
allowSave = !usernameSaved->isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditPeerGroupTypeBox::prepare() {
|
||||||
|
_peer->updateFull();
|
||||||
|
|
||||||
|
setTitle(langFactory((peer->isChat() || peer->isMegagroup())
|
||||||
|
? lng_manage_peer_group_type
|
||||||
|
: lng_manage_peer_channel_type));
|
||||||
|
|
||||||
|
addButton(langFactory(lng_settings_save), [=] {
|
||||||
|
const auto v = privacyButtons->value();
|
||||||
|
if (!allowSave && (v == Privacy::Public)) {
|
||||||
|
SetFocusUsername();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto local = std::move(_savedCallback);
|
||||||
|
local(v,
|
||||||
|
(v == Privacy::Public)
|
||||||
|
? GetUsernameInput()
|
||||||
|
: QString()); // We dont need username with private type.
|
||||||
|
closeBox();
|
||||||
|
});
|
||||||
|
addButton(langFactory(lng_cancel), [=] { closeBox(); });
|
||||||
|
|
||||||
|
setupContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditPeerGroupTypeBox::setupContent() {
|
||||||
|
isGroup = (_peer->isChat() || _peer->isMegagroup());
|
||||||
|
|
||||||
|
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||||
|
FillContent(content, _peer, privacySavedValue);
|
||||||
|
|
||||||
|
auto controller = Ui::CreateChild<Controller>(this, content, _peer);
|
||||||
|
_focusRequests.events(
|
||||||
|
) | rpl::start_with_next(
|
||||||
|
[=] { SetFocusUsername(); },
|
||||||
|
lifetime());
|
||||||
|
controller->createContent();
|
||||||
|
// setDimensionsToContent(st::boxWidth, content);
|
||||||
|
setDimensionsToContent(st::boxWideWidth, content);
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "boxes/abstract_box.h"
|
||||||
|
#include "base/timer.h"
|
||||||
|
|
||||||
|
namespace style {
|
||||||
|
struct InfoProfileCountButton;
|
||||||
|
} // namespace style
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class VerticalLayout;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace Info {
|
||||||
|
namespace Profile {
|
||||||
|
class Button;
|
||||||
|
} // namespace Profile
|
||||||
|
} // namespace Info
|
||||||
|
|
||||||
|
enum class Privacy {
|
||||||
|
Public,
|
||||||
|
Private,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class UsernameState {
|
||||||
|
Normal,
|
||||||
|
TooMany,
|
||||||
|
NotAvailable,
|
||||||
|
};
|
||||||
|
|
||||||
|
class EditPeerGroupTypeBox : public BoxContent {
|
||||||
|
public:
|
||||||
|
|
||||||
|
EditPeerGroupTypeBox(
|
||||||
|
QWidget*,
|
||||||
|
not_null<PeerData*> p,
|
||||||
|
FnMut<void(Privacy, QString)> savedCallback,
|
||||||
|
std::optional<Privacy> privacySaved = std::nullopt,
|
||||||
|
std::optional<QString> usernameSaved = std::nullopt);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void prepare() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupContent();
|
||||||
|
|
||||||
|
not_null<PeerData*> _peer;
|
||||||
|
FnMut<void(Privacy, QString)> _savedCallback;
|
||||||
|
|
||||||
|
rpl::event_stream<> _focusRequests;
|
||||||
|
|
||||||
|
};
|
|
@ -281,15 +281,6 @@ public:
|
||||||
void setFocus();
|
void setFocus();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Privacy {
|
|
||||||
Public,
|
|
||||||
Private,
|
|
||||||
};
|
|
||||||
enum class UsernameState {
|
|
||||||
Normal,
|
|
||||||
TooMany,
|
|
||||||
NotAvailable,
|
|
||||||
};
|
|
||||||
struct Controls {
|
struct Controls {
|
||||||
Ui::InputField *title = nullptr;
|
Ui::InputField *title = nullptr;
|
||||||
Ui::InputField *description = nullptr;
|
Ui::InputField *description = nullptr;
|
||||||
|
@ -308,8 +299,10 @@ private:
|
||||||
|
|
||||||
Ui::Checkbox *signatures = nullptr;
|
Ui::Checkbox *signatures = nullptr;
|
||||||
|
|
||||||
std::optional<HistoryVisibility> historyVisibilitySavedValue = std::nullopt;
|
|
||||||
Ui::SlideWrap<Ui::RpWidget> *historyVisibilityWrap = nullptr;
|
Ui::SlideWrap<Ui::RpWidget> *historyVisibilityWrap = nullptr;
|
||||||
|
std::optional<HistoryVisibility> historyVisibilitySavedValue = std::nullopt;
|
||||||
|
std::optional<Privacy> privacySavedValue = std::nullopt;
|
||||||
|
std::optional<QString> usernameSavedValue = std::nullopt;
|
||||||
};
|
};
|
||||||
struct Saving {
|
struct Saving {
|
||||||
std::optional<QString> username;
|
std::optional<QString> username;
|
||||||
|
@ -638,7 +631,7 @@ object_ptr<Ui::RpWidget> Controller::createPrivaciesEdit() {
|
||||||
container,
|
container,
|
||||||
Lang::Viewer(_isGroup ? groupAboutKey : channelAboutKey),
|
Lang::Viewer(_isGroup ? groupAboutKey : channelAboutKey),
|
||||||
st::editPeerPrivacyLabel),
|
st::editPeerPrivacyLabel),
|
||||||
st::editPeerPrivacyLabelMargins));
|
st::editPeerHistoryVisibilityLabelMargins));
|
||||||
container->add(object_ptr<Ui::FixedHeightWidget>(
|
container->add(object_ptr<Ui::FixedHeightWidget>(
|
||||||
container,
|
container,
|
||||||
st::editPeerPrivacyBottomSkip));
|
st::editPeerPrivacyBottomSkip));
|
||||||
|
@ -683,30 +676,57 @@ object_ptr<Ui::RpWidget> Controller::createPrivaciesButtons() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bug with defaultValue here.
|
||||||
const auto channel = _peer->asChannel();
|
const auto channel = _peer->asChannel();
|
||||||
auto defaultValue = (!channel || channel->hiddenPreHistory())
|
auto defaultValue = (!channel || channel->hiddenPreHistory())
|
||||||
? HistoryVisibility::Hidden
|
? HistoryVisibility::Hidden
|
||||||
: HistoryVisibility::Visible;
|
: HistoryVisibility::Visible;
|
||||||
|
|
||||||
const auto update = std::make_shared<rpl::event_stream<HistoryVisibility>>();
|
auto defaultValuePrivacy = (_peer->isChannel()
|
||||||
|
&& _peer->asChannel()->isPublic())
|
||||||
|
? Privacy::Public
|
||||||
|
: Privacy::Private;
|
||||||
|
|
||||||
|
const auto updateHistoryVisibility = std::make_shared<rpl::event_stream<HistoryVisibility>>();
|
||||||
|
const auto updateType = std::make_shared<rpl::event_stream<Privacy>>();
|
||||||
|
|
||||||
auto result = object_ptr<Ui::PaddingWrap<Ui::VerticalLayout>>(
|
auto result = object_ptr<Ui::PaddingWrap<Ui::VerticalLayout>>(
|
||||||
_wrap,
|
_wrap,
|
||||||
object_ptr<Ui::VerticalLayout>(_wrap),
|
object_ptr<Ui::VerticalLayout>(_wrap),
|
||||||
st::editPeerTopButtonsLayoutMargins);
|
st::editPeerTopButtonsLayoutMargins);
|
||||||
auto resultContainer = result->entity();
|
auto resultContainer = result->entity();
|
||||||
|
|
||||||
|
const auto boxCallback = [=](Privacy checked, QString publicLink) {
|
||||||
|
updateType->fire(std::move(checked));
|
||||||
|
_controls.privacySavedValue = checked;
|
||||||
|
_controls.usernameSavedValue = publicLink;
|
||||||
|
refreshHistoryVisibility();
|
||||||
|
};
|
||||||
|
const auto buttonCallback = [=]{
|
||||||
|
Ui::show(Box<EditPeerGroupTypeBox>(
|
||||||
|
_peer,
|
||||||
|
boxCallback,
|
||||||
|
_controls.privacySavedValue,
|
||||||
|
_controls.usernameSavedValue
|
||||||
|
), LayerOption::KeepOther);
|
||||||
|
};
|
||||||
AddButtonWithText(
|
AddButtonWithText(
|
||||||
resultContainer,
|
resultContainer,
|
||||||
std::move(Lang::Viewer(lng_manage_peer_group_type)),
|
std::move(Lang::Viewer((_peer->isChat() || _peer->isMegagroup())
|
||||||
update->events(
|
? lng_manage_peer_group_type
|
||||||
) | rpl::map([](HistoryVisibility count) {
|
: lng_manage_peer_channel_type)),
|
||||||
return HistoryVisibility::Visible == count ? QString("A") : QString("B");
|
|
||||||
}),
|
|
||||||
[] {LOG(("BUTTON")); });
|
|
||||||
|
|
||||||
const auto addPrivaciesButton = [=](LangKey privacyTextKey, Ui::VerticalLayout* container) {
|
updateType->events(
|
||||||
|
) | rpl::map([](Privacy flag) {
|
||||||
|
return lang(Privacy::Public == flag
|
||||||
|
? lng_manage_public_peer_title
|
||||||
|
: lng_manage_private_peer_title);
|
||||||
|
}),
|
||||||
|
buttonCallback);
|
||||||
|
|
||||||
|
const auto addHistoryVisibilityButton = [=](LangKey privacyTextKey, Ui::VerticalLayout* container) {
|
||||||
const auto boxCallback = [=](HistoryVisibility checked) {
|
const auto boxCallback = [=](HistoryVisibility checked) {
|
||||||
update->fire(std::move(checked));
|
updateHistoryVisibility->fire(std::move(checked));
|
||||||
_controls.historyVisibilitySavedValue = checked;
|
_controls.historyVisibilitySavedValue = checked;
|
||||||
};
|
};
|
||||||
const auto buttonCallback = [=]{
|
const auto buttonCallback = [=]{
|
||||||
|
@ -719,7 +739,7 @@ object_ptr<Ui::RpWidget> Controller::createPrivaciesButtons() {
|
||||||
AddButtonWithText(
|
AddButtonWithText(
|
||||||
container,
|
container,
|
||||||
std::move(Lang::Viewer(privacyTextKey)),
|
std::move(Lang::Viewer(privacyTextKey)),
|
||||||
update->events(
|
updateHistoryVisibility->events(
|
||||||
) | rpl::map([](HistoryVisibility flag) {
|
) | rpl::map([](HistoryVisibility flag) {
|
||||||
return lang(HistoryVisibility::Visible == flag
|
return lang(HistoryVisibility::Visible == flag
|
||||||
? lng_manage_history_visibility_shown
|
? lng_manage_history_visibility_shown
|
||||||
|
@ -734,9 +754,10 @@ object_ptr<Ui::RpWidget> Controller::createPrivaciesButtons() {
|
||||||
st::boxOptionListPadding)); // Empty margins.
|
st::boxOptionListPadding)); // Empty margins.
|
||||||
_controls.historyVisibilityWrap = wrapLayout;
|
_controls.historyVisibilityWrap = wrapLayout;
|
||||||
|
|
||||||
addPrivaciesButton(lng_manage_history_visibility_title, wrapLayout->entity());
|
addHistoryVisibilityButton(lng_manage_history_visibility_title, wrapLayout->entity());
|
||||||
|
|
||||||
update->fire(std::move(defaultValue));
|
updateHistoryVisibility->fire(std::move(defaultValue));
|
||||||
|
updateType->fire(std::move(defaultValuePrivacy));
|
||||||
refreshHistoryVisibility();
|
refreshHistoryVisibility();
|
||||||
|
|
||||||
return std::move(result);
|
return std::move(result);
|
||||||
|
@ -1164,7 +1185,8 @@ void Controller::refreshHistoryVisibility() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto historyVisibilityShown = !_controls.privacy
|
auto historyVisibilityShown = !_controls.privacy
|
||||||
|| (_controls.privacy->value() == Privacy::Private);
|
|| (_controls.privacy->value() == Privacy::Private)
|
||||||
|
|| (_controls.privacySavedValue == Privacy::Private);
|
||||||
_controls.historyVisibilityWrap->toggle(
|
_controls.historyVisibilityWrap->toggle(
|
||||||
historyVisibilityShown,
|
historyVisibilityShown,
|
||||||
anim::type::normal);
|
anim::type::normal);
|
||||||
|
@ -1302,11 +1324,15 @@ std::optional<Controller::Saving> Controller::validate() const {
|
||||||
bool Controller::validateUsername(Saving &to) const {
|
bool Controller::validateUsername(Saving &to) const {
|
||||||
if (!_controls.privacy) {
|
if (!_controls.privacy) {
|
||||||
return true;
|
return true;
|
||||||
} else if (_controls.privacy->value() == Privacy::Private) {
|
} else if (_controls.privacySavedValue == Privacy::Private) {
|
||||||
to.username = QString();
|
to.username = QString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
auto username = _controls.username->getLastText().trimmed();
|
auto username = _controls.usernameSavedValue.value_or(
|
||||||
|
_peer->isChannel()
|
||||||
|
? _peer->asChannel()->username
|
||||||
|
: QString()
|
||||||
|
);
|
||||||
if (username.isEmpty()) {
|
if (username.isEmpty()) {
|
||||||
_controls.username->showError();
|
_controls.username->showError();
|
||||||
_box->scrollToWidget(_controls.username);
|
_box->scrollToWidget(_controls.username);
|
||||||
|
|
|
@ -650,14 +650,15 @@ editPeerTitle: defaultInputField;
|
||||||
editPeerTitleMargins: margins(27px, 21px, 23px, 8px);
|
editPeerTitleMargins: margins(27px, 21px, 23px, 8px);
|
||||||
editPeerDescription: newGroupDescription;
|
editPeerDescription: newGroupDescription;
|
||||||
editPeerDescriptionMargins: margins(23px, 5px, 23px, 16px);
|
editPeerDescriptionMargins: margins(23px, 5px, 23px, 16px);
|
||||||
editPeerPrivaciesMargins: margins(23px, 10px, 23px, 0px);
|
editPeerPrivaciesMargins: margins(15px, 0px, 23px, 0px);
|
||||||
editPeerPrivacyTopSkip: 10px;
|
editPeerPrivacyTopSkip: 10px;
|
||||||
editPeerPrivacyBottomSkip: 16px;
|
editPeerPrivacyBottomSkip: 16px;
|
||||||
editPeerPrivacyLabel: FlatLabel(defaultFlatLabel) {
|
editPeerPrivacyLabel: FlatLabel(defaultFlatLabel) {
|
||||||
minWidth: 220px;
|
minWidth: 220px;
|
||||||
textFg: windowSubTextFg;
|
textFg: windowSubTextFg;
|
||||||
}
|
}
|
||||||
editPeerPrivacyLabelMargins: margins(34px, 0px, 48px, 0px);
|
editPeerHistoryVisibilityLabelMargins: margins(34px, 0px, 48px, 0px);
|
||||||
|
editPeerPrivacyLabelMargins: margins(34px, 0px, 34px, 0px);
|
||||||
editPeerSectionLabel: FlatLabel(boxTitle) {
|
editPeerSectionLabel: FlatLabel(boxTitle) {
|
||||||
style: TextStyle(defaultTextStyle) {
|
style: TextStyle(defaultTextStyle) {
|
||||||
font: font(15px semibold);
|
font: font(15px semibold);
|
||||||
|
@ -672,7 +673,7 @@ editPeerInviteLink: FlatLabel(defaultFlatLabel) {
|
||||||
style: boxTextStyle;
|
style: boxTextStyle;
|
||||||
}
|
}
|
||||||
editPeerInviteLinkButton: boxLinkButton;
|
editPeerInviteLinkButton: boxLinkButton;
|
||||||
editPeerUsernameMargins: margins(0px, 10px, 0px, 13px);
|
editPeerUsernameMargins: margins(15px, 2px, 35px, 2px);
|
||||||
editPeerUsernameGood: FlatLabel(defaultFlatLabel) {
|
editPeerUsernameGood: FlatLabel(defaultFlatLabel) {
|
||||||
textFg: boxTextFgGood;
|
textFg: boxTextFgGood;
|
||||||
style: boxTextStyle;
|
style: boxTextStyle;
|
||||||
|
@ -680,9 +681,9 @@ editPeerUsernameGood: FlatLabel(defaultFlatLabel) {
|
||||||
editPeerUsernameError: FlatLabel(editPeerUsernameGood) {
|
editPeerUsernameError: FlatLabel(editPeerUsernameGood) {
|
||||||
textFg: boxTextFgError;
|
textFg: boxTextFgError;
|
||||||
}
|
}
|
||||||
editPeerUsernamePosition: point(0px, 10px);
|
editPeerUsernamePosition: point(35px, 3px);
|
||||||
editPeerInviteLinkSkip: 10px;
|
editPeerInviteLinkSkip: 10px;
|
||||||
editPeerInviteLinkMargins: margins(23px, 10px, 14px, 16px);
|
editPeerInviteLinkMargins: margins(15px, 10px, 14px, 16px);
|
||||||
editPeerSignaturesMargins: margins(23px, 10px, 23px, 16px);
|
editPeerSignaturesMargins: margins(23px, 10px, 23px, 16px);
|
||||||
editPeerInvitesMargins: margins(23px, 10px, 23px, 16px);
|
editPeerInvitesMargins: margins(23px, 10px, 23px, 16px);
|
||||||
editPeerInvitesTopSkip: 10px;
|
editPeerInvitesTopSkip: 10px;
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
<(src_loc)/boxes/peers/edit_participants_box.h
|
<(src_loc)/boxes/peers/edit_participants_box.h
|
||||||
<(src_loc)/boxes/peers/edit_peer_info_box.cpp
|
<(src_loc)/boxes/peers/edit_peer_info_box.cpp
|
||||||
<(src_loc)/boxes/peers/edit_peer_info_box.h
|
<(src_loc)/boxes/peers/edit_peer_info_box.h
|
||||||
<(src_loc)/boxes/peers/edit_peer_permissions_box.cpp
|
<(src_loc)/boxes/peers/edit_peer_group_type_box.cpp
|
||||||
<(src_loc)/boxes/peers/edit_peer_permissions_box.h
|
<(src_loc)/boxes/peers/edit_peer_group_type_box.h
|
||||||
<(src_loc)/boxes/peers/edit_peer_history_visibility_box.cpp
|
<(src_loc)/boxes/peers/edit_peer_history_visibility_box.cpp
|
||||||
<(src_loc)/boxes/peers/edit_peer_history_visibility_box.h
|
<(src_loc)/boxes/peers/edit_peer_history_visibility_box.h
|
||||||
|
<(src_loc)/boxes/peers/edit_peer_permissions_box.cpp
|
||||||
|
<(src_loc)/boxes/peers/edit_peer_permissions_box.h
|
||||||
<(src_loc)/boxes/peers/manage_peer_box.cpp
|
<(src_loc)/boxes/peers/manage_peer_box.cpp
|
||||||
<(src_loc)/boxes/peers/manage_peer_box.h
|
<(src_loc)/boxes/peers/manage_peer_box.h
|
||||||
<(src_loc)/boxes/about_box.cpp
|
<(src_loc)/boxes/about_box.cpp
|
||||||
|
|
Loading…
Reference in New Issue