mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Allow creating approve-only invite links.
This commit is contained in:
parent
e471d61d7a
commit
3af3f85f82
20 changed files with 259 additions and 52 deletions
BIN
Telegram/Resources/icons/info/edit/group_manage_requests.png
Normal file
BIN
Telegram/Resources/icons/info/edit/group_manage_requests.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 620 B |
BIN
Telegram/Resources/icons/info/edit/group_manage_requests@2x.png
Normal file
BIN
Telegram/Resources/icons/info/edit/group_manage_requests@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
Telegram/Resources/icons/info/edit/group_manage_requests@3x.png
Normal file
BIN
Telegram/Resources/icons/info/edit/group_manage_requests@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
|
@ -978,6 +978,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_manage_peer_removed_users" = "Removed users";
|
||||
"lng_manage_peer_permissions" = "Permissions";
|
||||
"lng_manage_peer_invite_links" = "Invite links";
|
||||
"lng_manage_peer_requests" = "Member Requests";
|
||||
"lng_manage_peer_requests_channel" = "Subscriber Requests";
|
||||
|
||||
"lng_manage_peer_group_type" = "Group type";
|
||||
"lng_manage_peer_channel_type" = "Channel type";
|
||||
|
@ -1158,8 +1160,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_action_user_left" = "{from} left the group";
|
||||
"lng_action_user_joined" = "{from} joined the group";
|
||||
"lng_action_user_joined_by_link" = "{from} joined the group via invite link";
|
||||
"lng_action_user_joined_by_request" = "{from} joined the group by request";
|
||||
"lng_action_user_joined_by_request" = "{from} was accepted to the group";
|
||||
"lng_action_you_joined_by_request" = "Your request to join the group was approved";
|
||||
"lng_action_you_joined_by_request_channel" = "Your request to join the channel was approved";
|
||||
"lng_action_user_registered" = "{from} just joined Telegram";
|
||||
"lng_action_removed_photo" = "{from} removed group photo";
|
||||
"lng_action_removed_photo_channel" = "Channel photo removed";
|
||||
|
@ -1271,6 +1274,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_group_invite_joined#other" = "{count} joined";
|
||||
"lng_group_invite_remaining#one" = "{count} remaining";
|
||||
"lng_group_invite_remaining#other" = "{count} remaining";
|
||||
"lng_group_invite_requested#one" = "{count} requested";
|
||||
"lng_group_invite_requested#other" = "{count} requested";
|
||||
"lng_group_invite_requested_full#one" = "{count} requested to join";
|
||||
"lng_group_invite_requested_full#other" = "{count} requested to join";
|
||||
"lng_group_invite_can_join#one" = "{count} can join";
|
||||
"lng_group_invite_can_join#other" = "{count} can join";
|
||||
"lng_group_invite_days_left#one" = "{count} day left";
|
||||
|
@ -1322,6 +1329,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_group_invite_qr_title" = "Invite by QR Code";
|
||||
"lng_group_invite_qr_about" = "Everyone on Telegram can scan this code to join your group.";
|
||||
"lng_group_invite_qr_copied" = "QR Code copied to clipboard.";
|
||||
"lng_group_invite_request_approve" = "Request admin approval";
|
||||
"lng_group_invite_about_approve" = "New users will be able to join the group only after having been approved by the admins.";
|
||||
"lng_group_invite_about_no_approve" = "New users will be able to join the group without being approved by the admins.";
|
||||
"lng_group_invite_about_approve_channel" = "New users will be able to join the channel only after having been approved by the admins.";
|
||||
"lng_group_invite_about_no_approve_channel" = "New users will be able to join the channel without being approved by the admins.";
|
||||
|
||||
"lng_group_request_to_join" = "Request to Join";
|
||||
"lng_group_request_about" = "This group accepts new members only after they are approved by its admins.";
|
||||
"lng_group_request_about_channel" = "This channel accepts new subscribers only after they are approved by its admins.";
|
||||
"lng_group_request_sent" = "You will be added to the group once its admins approve your request.";
|
||||
"lng_group_request_sent_channel" = "You will be added to the channel once its admins approve your request.";
|
||||
"lng_group_requests_pending#one" = "{count} pending member request";
|
||||
"lng_group_requests_pending#other" = "{count} pending member requests";
|
||||
"lng_group_requests_pending_channel#one" = "{count} pending subscriber request";
|
||||
"lng_group_requests_pending_channel#other" = "{count} pending subscriber requests";
|
||||
"lng_group_requests_status" = "requested to join {date}";
|
||||
"lng_group_requests_add" = "Add to Group";
|
||||
"lng_group_requests_add_channel" = "Add to Channel";
|
||||
"lng_group_requests_dismiss" = "Dismiss";
|
||||
"lng_group_requests_was_added" = "{user} has been added to the group.";
|
||||
"lng_group_requests_none" = "No member requests";
|
||||
"lng_group_requests_none_channel" = "No subscriber requests";
|
||||
|
||||
"lng_channel_public_link_copied" = "Link copied to clipboard.";
|
||||
"lng_context_about_private_link" = "This link will only work for members of this chat.";
|
||||
|
@ -2497,6 +2526,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_admin_log_edited_invite_link" = "edited invite link {link}";
|
||||
"lng_admin_log_invite_link_expire_date" = "Expire date: {previous} -> {limit}";
|
||||
"lng_admin_log_invite_link_usage_limit" = "Usage limit: {previous} -> {limit}";
|
||||
"lng_admin_log_invite_link_request_needed" = "Now admin approval is required to join.";
|
||||
"lng_admin_log_invite_link_request_not_needed" = "Now admin approval is not required to join.";
|
||||
"lng_admin_log_restricted_forever" = "indefinitely";
|
||||
"lng_admin_log_restricted_until" = "until {date}";
|
||||
"lng_admin_log_banned_view_messages" = "Read messages";
|
||||
|
|
|
@ -70,8 +70,15 @@ void InviteLinks::create(
|
|||
not_null<PeerData*> peer,
|
||||
Fn<void(Link)> done,
|
||||
TimeId expireDate,
|
||||
int usageLimit) {
|
||||
performCreate(peer, std::move(done), false, expireDate, usageLimit);
|
||||
int usageLimit,
|
||||
bool requestApproval) {
|
||||
performCreate(
|
||||
peer,
|
||||
std::move(done),
|
||||
false,
|
||||
expireDate,
|
||||
usageLimit,
|
||||
requestApproval);
|
||||
}
|
||||
|
||||
void InviteLinks::performCreate(
|
||||
|
@ -79,7 +86,8 @@ void InviteLinks::performCreate(
|
|||
Fn<void(Link)> done,
|
||||
bool revokeLegacyPermanent,
|
||||
TimeId expireDate,
|
||||
int usageLimit) {
|
||||
int usageLimit,
|
||||
bool requestApproval) {
|
||||
if (const auto i = _createCallbacks.find(peer)
|
||||
; i != end(_createCallbacks)) {
|
||||
if (done) {
|
||||
|
@ -98,7 +106,8 @@ void InviteLinks::performCreate(
|
|||
? Flag::f_legacy_revoke_permanent
|
||||
: Flag(0))
|
||||
| (expireDate ? Flag::f_expire_date : Flag(0))
|
||||
| (usageLimit ? Flag::f_usage_limit : Flag(0))),
|
||||
| (usageLimit ? Flag::f_usage_limit : Flag(0))
|
||||
| (requestApproval ? Flag::f_request_needed : Flag(0))),
|
||||
peer->input,
|
||||
MTP_int(expireDate),
|
||||
MTP_int(usageLimit)
|
||||
|
@ -201,6 +210,7 @@ void InviteLinks::edit(
|
|||
const QString &link,
|
||||
TimeId expireDate,
|
||||
int usageLimit,
|
||||
bool requestApproval,
|
||||
Fn<void(Link)> done) {
|
||||
performEdit(
|
||||
peer,
|
||||
|
@ -209,7 +219,8 @@ void InviteLinks::edit(
|
|||
std::move(done),
|
||||
false,
|
||||
expireDate,
|
||||
usageLimit);
|
||||
usageLimit,
|
||||
requestApproval);
|
||||
}
|
||||
|
||||
void InviteLinks::performEdit(
|
||||
|
@ -219,7 +230,8 @@ void InviteLinks::performEdit(
|
|||
Fn<void(Link)> done,
|
||||
bool revoke,
|
||||
TimeId expireDate,
|
||||
int usageLimit) {
|
||||
int usageLimit,
|
||||
bool requestApproval) {
|
||||
const auto key = LinkKey{ peer, link };
|
||||
if (_deleteCallbacks.contains(key)) {
|
||||
return;
|
||||
|
@ -239,12 +251,13 @@ void InviteLinks::performEdit(
|
|||
_api->request(MTPmessages_EditExportedChatInvite(
|
||||
MTP_flags((revoke ? Flag::f_revoked : Flag(0))
|
||||
| (!revoke ? Flag::f_expire_date : Flag(0))
|
||||
| (!revoke ? Flag::f_usage_limit : Flag(0))),
|
||||
| (!revoke ? Flag::f_usage_limit : Flag(0))
|
||||
| (!revoke ? Flag::f_request_needed : Flag(0))),
|
||||
peer->input,
|
||||
MTP_string(link),
|
||||
MTP_int(expireDate),
|
||||
MTP_int(usageLimit),
|
||||
MTPbool() // request_needed // #TODO requests
|
||||
MTP_bool(requestApproval)
|
||||
)).done([=](const MTPmessages_ExportedChatInvite &result) {
|
||||
const auto callbacks = _editCallbacks.take(key);
|
||||
const auto peer = key.peer;
|
||||
|
@ -632,6 +645,7 @@ auto InviteLinks::parse(
|
|||
.expireDate = data.vexpire_date().value_or_empty(),
|
||||
.usageLimit = data.vusage_limit().value_or_empty(),
|
||||
.usage = data.vusage().value_or_empty(),
|
||||
.requestApproval = data.is_request_needed(),
|
||||
.permanent = data.is_permanent(),
|
||||
.revoked = data.is_revoked(),
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@ struct InviteLink {
|
|||
TimeId expireDate = 0;
|
||||
int usageLimit = 0;
|
||||
int usage = 0;
|
||||
bool requestApproval = false;
|
||||
bool permanent = false;
|
||||
bool revoked = false;
|
||||
};
|
||||
|
@ -61,13 +62,15 @@ public:
|
|||
not_null<PeerData*> peer,
|
||||
Fn<void(Link)> done = nullptr,
|
||||
TimeId expireDate = 0,
|
||||
int usageLimit = 0);
|
||||
int usageLimit = 0,
|
||||
bool requestApproval = false);
|
||||
void edit(
|
||||
not_null<PeerData*> peer,
|
||||
not_null<UserData*> admin,
|
||||
const QString &link,
|
||||
TimeId expireDate,
|
||||
int usageLimit,
|
||||
bool requestApproval,
|
||||
Fn<void(Link)> done = nullptr);
|
||||
void revoke(
|
||||
not_null<PeerData*> peer,
|
||||
|
@ -164,13 +167,15 @@ private:
|
|||
Fn<void(Link)> done,
|
||||
bool revoke,
|
||||
TimeId expireDate = 0,
|
||||
int usageLimit = 0);
|
||||
int usageLimit = 0,
|
||||
bool requestApproval = false);
|
||||
void performCreate(
|
||||
not_null<PeerData*> peer,
|
||||
Fn<void(Link)> done,
|
||||
bool revokeLegacyPermanent,
|
||||
TimeId expireDate = 0,
|
||||
int usageLimit = 0);
|
||||
int usageLimit = 0,
|
||||
bool requestApproval = false);
|
||||
|
||||
void requestJoinedFirstSlice(LinkKey key);
|
||||
[[nodiscard]] std::optional<JoinedByLinkSlice> lookupJoinedFirstSlice(
|
||||
|
|
|
@ -1965,6 +1965,18 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
|||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updatePendingJoinRequests: {
|
||||
const auto &d = update.c_updatePendingJoinRequests();
|
||||
if (const auto peer = session().data().peerLoaded(peerFromMTP(d.vpeer()))) {
|
||||
const auto count = d.vrequests_pending().v;
|
||||
if (const auto chat = peer->asChat()) {
|
||||
chat->setPendingRequestsCount(count);
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
channel->setPendingRequestsCount(count);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateServiceNotification: {
|
||||
const auto &d = update.c_updateServiceNotification();
|
||||
const auto text = TextWithEntities {
|
||||
|
|
|
@ -297,6 +297,7 @@ private:
|
|||
void fillSignaturesButton();
|
||||
void fillHistoryVisibilityButton();
|
||||
void fillManageSection();
|
||||
void fillPendingRequestsButton();
|
||||
|
||||
void submitTitle();
|
||||
void submitDescription();
|
||||
|
@ -845,6 +846,8 @@ void Controller::fillHistoryVisibilityButton() {
|
|||
void Controller::fillManageSection() {
|
||||
Expects(_controls.buttonsLayout != nullptr);
|
||||
|
||||
using namespace rpl::mappers;
|
||||
|
||||
const auto chat = _peer->asChat();
|
||||
const auto channel = _peer->asChannel();
|
||||
const auto isChannel = (!chat);
|
||||
|
@ -1042,6 +1045,9 @@ void Controller::fillManageSection() {
|
|||
},
|
||||
st::infoIconMembers);
|
||||
}
|
||||
|
||||
fillPendingRequestsButton();
|
||||
|
||||
if (canViewKicked) {
|
||||
AddButtonWithCount(
|
||||
_controls.buttonsLayout,
|
||||
|
@ -1089,6 +1095,42 @@ void Controller::fillManageSection() {
|
|||
}
|
||||
}
|
||||
|
||||
void Controller::fillPendingRequestsButton() {
|
||||
auto pendingRequestsCount = Info::Profile::MigratedOrMeValue(
|
||||
_peer
|
||||
) | rpl::map(
|
||||
Info::Profile::PendingRequestsCountValue
|
||||
) | rpl::flatten_latest(
|
||||
) | rpl::start_spawning(_controls.buttonsLayout->lifetime());
|
||||
const auto wrap = _controls.buttonsLayout->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
_controls.buttonsLayout,
|
||||
object_ptr<Ui::VerticalLayout>(
|
||||
_controls.buttonsLayout)));
|
||||
AddButtonWithCount(
|
||||
wrap->entity(),
|
||||
(_isGroup
|
||||
? tr::lng_manage_peer_requests()
|
||||
: tr::lng_manage_peer_requests_channel()),
|
||||
rpl::duplicate(pendingRequestsCount) | ToPositiveNumberString(),
|
||||
[=] {
|
||||
_navigation->parentController()->show(
|
||||
Box( // #TODO requests
|
||||
ManageInviteLinksBox,
|
||||
_peer,
|
||||
_peer->session().user(),
|
||||
0,
|
||||
0),
|
||||
Ui::LayerOption::KeepOther);
|
||||
},
|
||||
st::infoIconRequests);
|
||||
std::move(
|
||||
pendingRequestsCount
|
||||
) | rpl::start_with_next([=](int count) {
|
||||
wrap->toggle(count > 0, anim::type::instant);
|
||||
}, wrap->lifetime());
|
||||
}
|
||||
|
||||
void Controller::submitTitle() {
|
||||
Expects(_controls.title != nullptr);
|
||||
|
||||
|
|
|
@ -943,7 +943,8 @@ void EditLink(
|
|||
peer,
|
||||
finish,
|
||||
result.expireDate,
|
||||
result.usageLimit);
|
||||
result.usageLimit,
|
||||
result.requestApproval);
|
||||
} else {
|
||||
peer->session().api().inviteLinks().edit(
|
||||
peer,
|
||||
|
@ -951,18 +952,22 @@ void EditLink(
|
|||
result.link,
|
||||
result.expireDate,
|
||||
result.usageLimit,
|
||||
result.requestApproval,
|
||||
finish);
|
||||
}
|
||||
};
|
||||
const auto isGroup = !peer->isBroadcast();
|
||||
*box = Ui::show(
|
||||
(creating
|
||||
? Box(Ui::CreateInviteLinkBox, done)
|
||||
? Box(Ui::CreateInviteLinkBox, isGroup, done)
|
||||
: Box(
|
||||
Ui::EditInviteLinkBox,
|
||||
Fields{
|
||||
.link = data.link,
|
||||
.expireDate = data.expireDate,
|
||||
.usageLimit = data.usageLimit
|
||||
.usageLimit = data.usageLimit,
|
||||
.requestApproval = data.requestApproval,
|
||||
.isGroup = isGroup,
|
||||
},
|
||||
done)),
|
||||
Ui::LayerOption::KeepOther);
|
||||
|
|
|
@ -50,51 +50,52 @@ struct NameUpdate {
|
|||
};
|
||||
|
||||
struct PeerUpdate {
|
||||
enum class Flag : uint32 {
|
||||
enum class Flag : uint64 {
|
||||
None = 0,
|
||||
|
||||
// Common flags
|
||||
Name = (1U << 0),
|
||||
Username = (1U << 1),
|
||||
Photo = (1U << 2),
|
||||
About = (1U << 3),
|
||||
Notifications = (1U << 4),
|
||||
Migration = (1U << 5),
|
||||
UnavailableReason = (1U << 6),
|
||||
ChatThemeEmoji = (1U << 7),
|
||||
IsBlocked = (1U << 8),
|
||||
MessagesTTL = (1U << 9),
|
||||
Name = (1ULL << 0),
|
||||
Username = (1ULL << 1),
|
||||
Photo = (1ULL << 2),
|
||||
About = (1ULL << 3),
|
||||
Notifications = (1ULL << 4),
|
||||
Migration = (1ULL << 5),
|
||||
UnavailableReason = (1ULL << 6),
|
||||
ChatThemeEmoji = (1ULL << 7),
|
||||
IsBlocked = (1ULL << 8),
|
||||
MessagesTTL = (1ULL << 9),
|
||||
|
||||
// For users
|
||||
CanShareContact = (1U << 10),
|
||||
IsContact = (1U << 11),
|
||||
PhoneNumber = (1U << 12),
|
||||
OnlineStatus = (1U << 13),
|
||||
BotCommands = (1U << 14),
|
||||
BotCanBeInvited = (1U << 15),
|
||||
BotStartToken = (1U << 16),
|
||||
CommonChats = (1U << 17),
|
||||
HasCalls = (1U << 18),
|
||||
SupportInfo = (1U << 19),
|
||||
IsBot = (1U << 20),
|
||||
CanShareContact = (1ULL << 10),
|
||||
IsContact = (1ULL << 11),
|
||||
PhoneNumber = (1ULL << 12),
|
||||
OnlineStatus = (1ULL << 13),
|
||||
BotCommands = (1ULL << 14),
|
||||
BotCanBeInvited = (1ULL << 15),
|
||||
BotStartToken = (1ULL << 16),
|
||||
CommonChats = (1ULL << 17),
|
||||
HasCalls = (1ULL << 18),
|
||||
SupportInfo = (1ULL << 19),
|
||||
IsBot = (1ULL << 20),
|
||||
|
||||
// For chats and channels
|
||||
InviteLinks = (1U << 21),
|
||||
Members = (1U << 22),
|
||||
Admins = (1U << 23),
|
||||
BannedUsers = (1U << 24),
|
||||
Rights = (1U << 25),
|
||||
InviteLinks = (1ULL << 21),
|
||||
Members = (1ULL << 22),
|
||||
Admins = (1ULL << 23),
|
||||
BannedUsers = (1ULL << 24),
|
||||
Rights = (1ULL << 25),
|
||||
PendingRequests = (1ULL << 26),
|
||||
|
||||
// For channels
|
||||
ChannelAmIn = (1U << 26),
|
||||
StickersSet = (1U << 27),
|
||||
ChannelLinkedChat = (1U << 28),
|
||||
ChannelLocation = (1U << 29),
|
||||
Slowmode = (1U << 30),
|
||||
GroupCall = (1U << 31),
|
||||
ChannelAmIn = (1ULL << 27),
|
||||
StickersSet = (1ULL << 28),
|
||||
ChannelLinkedChat = (1ULL << 29),
|
||||
ChannelLocation = (1ULL << 30),
|
||||
Slowmode = (1ULL << 31),
|
||||
GroupCall = (1ULL << 32),
|
||||
|
||||
// For iteration
|
||||
LastUsedBit = (1U << 31),
|
||||
LastUsedBit = (1ULL << 32),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||
|
|
|
@ -195,6 +195,13 @@ void ChannelData::setKickedCount(int newKickedCount) {
|
|||
}
|
||||
}
|
||||
|
||||
void ChannelData::setPendingRequestsCount(int count) {
|
||||
if (_pendingRequestsCount != count) {
|
||||
_pendingRequestsCount = count;
|
||||
session().changes().peerUpdated(this, UpdateFlag::PendingRequests);
|
||||
}
|
||||
}
|
||||
|
||||
ChatRestrictionsInfo ChannelData::KickedRestrictedRights(
|
||||
not_null<PeerData*> participant) {
|
||||
using Flag = ChatRestriction;
|
||||
|
@ -542,6 +549,9 @@ void ChannelData::setAdminRights(ChatAdminRights rights) {
|
|||
return;
|
||||
}
|
||||
_adminRights.set(rights);
|
||||
if (!canHaveInviteLink()) {
|
||||
setPendingRequestsCount(0);
|
||||
}
|
||||
if (isMegagroup()) {
|
||||
const auto self = session().user();
|
||||
if (hasAdminRights()) {
|
||||
|
@ -874,6 +884,8 @@ void ApplyChannelUpdate(
|
|||
}
|
||||
channel->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
|
||||
channel->fullUpdated();
|
||||
channel->setPendingRequestsCount(
|
||||
update.vrequests_pending().value_or_empty());
|
||||
|
||||
if (canViewAdmins != channel->canViewAdmins()
|
||||
|| canViewMembers != channel->canViewMembers()) {
|
||||
|
|
|
@ -177,6 +177,11 @@ public:
|
|||
}
|
||||
void setKickedCount(int newKickedCount);
|
||||
|
||||
[[nodiscard]] int pendingRequestsCount() const {
|
||||
return _pendingRequestsCount;
|
||||
}
|
||||
void setPendingRequestsCount(int count);
|
||||
|
||||
[[nodiscard]] bool haveLeft() const {
|
||||
return flags() & Flag::Left;
|
||||
}
|
||||
|
@ -426,6 +431,7 @@ private:
|
|||
int _adminsCount = 1;
|
||||
int _restrictedCount = 0;
|
||||
int _kickedCount = 0;
|
||||
int _pendingRequestsCount = 0;
|
||||
MsgId _availableMinId = 0;
|
||||
|
||||
RestrictionFlags _defaultRestrictions;
|
||||
|
|
|
@ -146,6 +146,9 @@ void ChatData::setAdminRights(ChatAdminRights rights) {
|
|||
return;
|
||||
}
|
||||
_adminRights.set(rights);
|
||||
if (!canHaveInviteLink()) {
|
||||
setPendingRequestsCount(0);
|
||||
}
|
||||
session().changes().peerUpdated(
|
||||
this,
|
||||
UpdateFlag::Rights | UpdateFlag::Admins | UpdateFlag::BannedUsers);
|
||||
|
@ -258,6 +261,13 @@ void ChatData::setBotCommands(
|
|||
}
|
||||
}
|
||||
|
||||
void ChatData::setPendingRequestsCount(int count) {
|
||||
if (_pendingRequestsCount != count) {
|
||||
_pendingRequestsCount = count;
|
||||
session().changes().peerUpdated(this, UpdateFlag::PendingRequests);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Data {
|
||||
|
||||
void ApplyChatUpdate(
|
||||
|
@ -431,6 +441,8 @@ void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
|
|||
chat->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
|
||||
chat->fullUpdated();
|
||||
chat->setAbout(qs(update.vabout()));
|
||||
chat->setPendingRequestsCount(
|
||||
update.vrequests_pending().value_or_empty());
|
||||
|
||||
chat->session().api().applyNotifySettings(
|
||||
MTP_inputNotifyPeer(chat->input),
|
||||
|
|
|
@ -164,6 +164,11 @@ public:
|
|||
return _botCommands;
|
||||
}
|
||||
|
||||
[[nodiscard]] int pendingRequestsCount() const {
|
||||
return _pendingRequestsCount;
|
||||
}
|
||||
void setPendingRequestsCount(int count);
|
||||
|
||||
// Still public data members.
|
||||
const MTPlong inputChat;
|
||||
|
||||
|
@ -185,6 +190,7 @@ private:
|
|||
RestrictionFlags _defaultRestrictions;
|
||||
AdminRightFlags _adminRights;
|
||||
int _version = 0;
|
||||
int _pendingRequestsCount = 0;
|
||||
|
||||
std::unique_ptr<Data::GroupCall> _call;
|
||||
PeerId _callDefaultJoinAs = 0;
|
||||
|
|
|
@ -312,6 +312,11 @@ TextWithEntities GenerateInviteLinkChangeText(
|
|||
return data.vusage_limit().value_or_empty();
|
||||
});
|
||||
};
|
||||
const auto requestApproval = [](const MTPExportedChatInvite &link) {
|
||||
return link.match([](const MTPDchatInviteExported &data) {
|
||||
return data.is_request_needed();
|
||||
});
|
||||
};
|
||||
const auto wrapDate = [](TimeId date) {
|
||||
return date
|
||||
? langDateTime(base::unixtime::parse(date))
|
||||
|
@ -326,12 +331,17 @@ TextWithEntities GenerateInviteLinkChangeText(
|
|||
const auto nowExpireDate = expireDate(newLink);
|
||||
const auto wasUsageLimit = usageLimit(prevLink);
|
||||
const auto nowUsageLimit = usageLimit(newLink);
|
||||
const auto wasRequestApproval = requestApproval(prevLink);
|
||||
const auto nowRequestApproval = requestApproval(newLink);
|
||||
if (wasExpireDate != nowExpireDate) {
|
||||
result.text.append('\n').append(tr::lng_admin_log_invite_link_expire_date(tr::now, lt_previous, wrapDate(wasExpireDate), lt_limit, wrapDate(nowExpireDate)));
|
||||
}
|
||||
if (wasUsageLimit != nowUsageLimit) {
|
||||
result.text.append('\n').append(tr::lng_admin_log_invite_link_usage_limit(tr::now, lt_previous, wrapUsage(wasUsageLimit), lt_limit, wrapUsage(nowUsageLimit)));
|
||||
}
|
||||
if (wasRequestApproval != nowRequestApproval) {
|
||||
result.text.append('\n').append(nowRequestApproval ? tr::lng_admin_log_invite_link_request_needed(tr::now) : tr::lng_admin_log_invite_link_request_not_needed(tr::now));
|
||||
}
|
||||
|
||||
result.entities.push_front(EntityInText(EntityType::Italic, 0, result.text.size()));
|
||||
return result;
|
||||
|
|
|
@ -345,6 +345,7 @@ infoProfileSeparatorPadding: margins(
|
|||
infoIconFg: menuIconFg;
|
||||
infoIconInformation: icon {{ "info_information", infoIconFg }};
|
||||
infoIconMembers: icon {{ "info/edit/group_manage_members", infoIconFg, point(-2px, 0px) }};
|
||||
infoIconRequests: icon {{ "info/edit/group_manage_requests", infoIconFg, point(-2px, 0px) }};
|
||||
infoIconNotifications: icon {{ "info_notifications", infoIconFg }};
|
||||
infoIconActions: icon {{ "info_actions", infoIconFg }};
|
||||
infoIconMediaPhoto: icon {{ "info_media_photo", infoIconFg }};
|
||||
|
|
|
@ -239,6 +239,25 @@ rpl::producer<int> MembersCountValue(not_null<PeerData*> peer) {
|
|||
Unexpected("User in MembersCountViewer().");
|
||||
}
|
||||
|
||||
rpl::producer<int> PendingRequestsCountValue(not_null<PeerData*> peer) {
|
||||
if (const auto chat = peer->asChat()) {
|
||||
return peer->session().changes().peerFlagsValue(
|
||||
peer,
|
||||
UpdateFlag::PendingRequests
|
||||
) | rpl::map([=] {
|
||||
return chat->pendingRequestsCount();
|
||||
});
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
return peer->session().changes().peerFlagsValue(
|
||||
peer,
|
||||
UpdateFlag::PendingRequests
|
||||
) | rpl::map([=] {
|
||||
return channel->pendingRequestsCount();
|
||||
});
|
||||
}
|
||||
Unexpected("User in MembersCountViewer().");
|
||||
}
|
||||
|
||||
rpl::producer<int> AdminsCountValue(not_null<PeerData*> peer) {
|
||||
if (const auto chat = peer->asChat()) {
|
||||
return peer->session().changes().peerFlagsValue(
|
||||
|
|
|
@ -49,6 +49,7 @@ rpl::producer<bool> CanShareContactValue(not_null<UserData*> user);
|
|||
rpl::producer<bool> CanAddContactValue(not_null<UserData*> user);
|
||||
rpl::producer<bool> AmInChannelValue(not_null<ChannelData*> channel);
|
||||
rpl::producer<int> MembersCountValue(not_null<PeerData*> peer);
|
||||
rpl::producer<int> PendingRequestsCountValue(not_null<PeerData*> peer);
|
||||
rpl::producer<int> AdminsCountValue(not_null<PeerData*> peer);
|
||||
rpl::producer<int> RestrictionsCountValue(not_null<PeerData*> peer);
|
||||
rpl::producer<int> RestrictedCountValue(not_null<ChannelData*> channel);
|
||||
|
|
|
@ -52,6 +52,7 @@ void EditInviteLinkBox(
|
|||
const InviteLinkFields &data,
|
||||
Fn<void(InviteLinkFields)> done) {
|
||||
const auto link = data.link;
|
||||
const auto isGroup = data.isGroup;
|
||||
box->setTitle(link.isEmpty()
|
||||
? tr::lng_group_invite_new_title()
|
||||
: tr::lng_group_invite_edit_title());
|
||||
|
@ -119,10 +120,12 @@ void EditInviteLinkBox(
|
|||
Buttons usageButtons;
|
||||
int expireValue = 0;
|
||||
int usageValue = 0;
|
||||
rpl::variable<bool> requestApproval = false;
|
||||
};
|
||||
const auto state = box->lifetime().make_state<State>(State{
|
||||
.expireValue = expire,
|
||||
.usageValue = usage
|
||||
.usageValue = usage,
|
||||
.requestApproval = data.requestApproval,
|
||||
});
|
||||
const auto regenerate = [=] {
|
||||
expireGroup->setValue(state->expireValue);
|
||||
|
@ -260,6 +263,24 @@ void EditInviteLinkBox(
|
|||
|
||||
regenerate();
|
||||
|
||||
const auto buttonSkip = st::settingsSectionSkip;
|
||||
const auto requestApproval = container->add(
|
||||
object_ptr<SettingsButton>(
|
||||
container,
|
||||
tr::lng_group_invite_request_approve(),
|
||||
st::settingsButton),
|
||||
style::margins{ 0, buttonSkip, 0, buttonSkip });
|
||||
requestApproval->toggleOn(state->requestApproval.value());
|
||||
state->requestApproval = requestApproval->toggledValue();
|
||||
addDivider(rpl::conditional(
|
||||
state->requestApproval.value(),
|
||||
(isGroup
|
||||
? tr::lng_group_invite_about_approve()
|
||||
: tr::lng_group_invite_about_approve_channel()),
|
||||
(isGroup
|
||||
? tr::lng_group_invite_about_no_approve()
|
||||
: tr::lng_group_invite_about_no_approve_channel())));
|
||||
|
||||
const auto &saveLabel = link.isEmpty()
|
||||
? tr::lng_formatting_link_create
|
||||
: tr::lng_settings_save;
|
||||
|
@ -275,7 +296,9 @@ void EditInviteLinkBox(
|
|||
done(InviteLinkFields{
|
||||
.link = link,
|
||||
.expireDate = expireDate,
|
||||
.usageLimit = usageLimit
|
||||
.usageLimit = usageLimit,
|
||||
.requestApproval = state->requestApproval.current(),
|
||||
.isGroup = isGroup,
|
||||
});
|
||||
});
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
|
@ -283,8 +306,12 @@ void EditInviteLinkBox(
|
|||
|
||||
void CreateInviteLinkBox(
|
||||
not_null<GenericBox*> box,
|
||||
bool isGroup,
|
||||
Fn<void(InviteLinkFields)> done) {
|
||||
EditInviteLinkBox(box, InviteLinkFields(), std::move(done));
|
||||
EditInviteLinkBox(
|
||||
box,
|
||||
InviteLinkFields{ .isGroup = isGroup },
|
||||
std::move(done));
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
@ -15,6 +15,8 @@ struct InviteLinkFields {
|
|||
QString link;
|
||||
TimeId expireDate = 0;
|
||||
int usageLimit = 0;
|
||||
bool requestApproval = false;
|
||||
bool isGroup = false;
|
||||
};
|
||||
|
||||
void EditInviteLinkBox(
|
||||
|
@ -24,6 +26,7 @@ void EditInviteLinkBox(
|
|||
|
||||
void CreateInviteLinkBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
bool isGroup,
|
||||
Fn<void(InviteLinkFields)> done);
|
||||
|
||||
} // namespace Ui
|
||||
|
|
Loading…
Add table
Reference in a new issue