2017-09-25 09:02:55 +00:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
2018-01-03 10:23:14 +00:00
|
|
|
the official desktop application for the Telegram messaging service.
|
2017-09-25 09:02:55 +00:00
|
|
|
|
2018-01-03 10:23:14 +00:00
|
|
|
For license and copyright information please follow this link:
|
|
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
2017-09-25 09:02:55 +00:00
|
|
|
*/
|
|
|
|
#include "info/profile/info_profile_values.h"
|
|
|
|
|
|
|
|
#include <rpl/filter.h>
|
|
|
|
#include <rpl/range.h>
|
|
|
|
#include <rpl/then.h>
|
|
|
|
#include <rpl/combine.h>
|
|
|
|
#include "observer_peer.h"
|
2019-01-21 13:42:21 +00:00
|
|
|
#include "core/application.h"
|
2018-02-07 12:40:37 +00:00
|
|
|
#include "auth_session.h"
|
2017-09-25 09:02:55 +00:00
|
|
|
#include "ui/wrap/slide_wrap.h"
|
2017-10-22 17:06:57 +00:00
|
|
|
#include "data/data_peer_values.h"
|
2017-11-06 07:31:18 +00:00
|
|
|
#include "data/data_shared_media.h"
|
2018-02-07 12:40:37 +00:00
|
|
|
#include "data/data_feed.h"
|
2019-01-04 11:09:48 +00:00
|
|
|
#include "data/data_channel.h"
|
|
|
|
#include "data/data_chat.h"
|
|
|
|
#include "data/data_user.h"
|
2018-02-07 12:40:37 +00:00
|
|
|
#include "data/data_session.h"
|
2017-09-25 09:02:55 +00:00
|
|
|
|
2019-03-15 08:20:12 +00:00
|
|
|
#include "boxes/peers/edit_peer_permissions_box.h"
|
|
|
|
|
2017-09-25 09:02:55 +00:00
|
|
|
namespace Info {
|
|
|
|
namespace Profile {
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<TextWithEntities> NameValue(not_null<PeerData*> peer) {
|
2018-09-09 17:38:08 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
|
|
|
peer,
|
|
|
|
Notify::PeerUpdate::Flag::NameChanged
|
|
|
|
) | rpl::map([=] {
|
|
|
|
return App::peerName(peer);
|
|
|
|
}) | WithEmptyEntities();
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<TextWithEntities> PhoneValue(not_null<UserData*> user) {
|
2017-10-24 17:11:35 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
2017-09-25 09:02:55 +00:00
|
|
|
user,
|
2017-12-22 07:05:20 +00:00
|
|
|
Notify::PeerUpdate::Flag::UserPhoneChanged
|
|
|
|
) | rpl::map([user] {
|
|
|
|
return App::formatPhone(user->phone());
|
|
|
|
}) | WithEmptyEntities();
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
auto PlainBioValue(not_null<UserData*> user) {
|
2017-10-24 17:11:35 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
2019-01-08 13:57:22 +00:00
|
|
|
user,
|
|
|
|
Notify::PeerUpdate::Flag::AboutChanged
|
2017-12-22 07:05:20 +00:00
|
|
|
) | rpl::map([user] { return user->about(); });
|
2017-11-07 07:21:48 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<TextWithEntities> BioValue(not_null<UserData*> user) {
|
2017-11-07 07:21:48 +00:00
|
|
|
return PlainBioValue(user)
|
|
|
|
| ToSingleLine()
|
2017-09-25 09:02:55 +00:00
|
|
|
| WithEmptyEntities();
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
auto PlainUsernameValue(not_null<PeerData*> peer) {
|
2017-10-24 17:11:35 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
2017-09-25 09:02:55 +00:00
|
|
|
peer,
|
2017-12-22 07:05:20 +00:00
|
|
|
Notify::PeerUpdate::Flag::UsernameChanged
|
|
|
|
) | rpl::map([peer] {
|
|
|
|
return peer->userName();
|
|
|
|
});
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<TextWithEntities> UsernameValue(not_null<UserData*> user) {
|
2017-12-22 07:05:20 +00:00
|
|
|
return PlainUsernameValue(
|
|
|
|
user
|
|
|
|
) | rpl::map([](QString &&username) {
|
|
|
|
return username.isEmpty()
|
|
|
|
? QString()
|
|
|
|
: ('@' + username);
|
|
|
|
}) | WithEmptyEntities();
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<QString> PlainAboutValue(not_null<PeerData*> peer) {
|
2019-01-08 13:57:22 +00:00
|
|
|
if (const auto user = peer->asUser()) {
|
|
|
|
if (!user->botInfo) {
|
|
|
|
return rpl::single(QString());
|
2017-11-07 07:21:48 +00:00
|
|
|
}
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
2019-01-08 13:57:22 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
|
|
|
peer,
|
|
|
|
Notify::PeerUpdate::Flag::AboutChanged
|
|
|
|
) | rpl::map([=] { return peer->about(); });
|
2017-11-17 07:42:53 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<TextWithEntities> AboutValue(not_null<PeerData*> peer) {
|
2017-11-17 07:42:53 +00:00
|
|
|
auto flags = TextParseLinks
|
|
|
|
| TextParseMentions
|
|
|
|
| TextParseHashtags;
|
|
|
|
if (peer->isUser()) {
|
|
|
|
flags |= TextParseBotCommands;
|
|
|
|
}
|
2017-12-22 07:05:20 +00:00
|
|
|
return PlainAboutValue(
|
|
|
|
peer
|
|
|
|
) | WithEmptyEntities(
|
|
|
|
) | rpl::map([=](TextWithEntities &&text) {
|
|
|
|
TextUtilities::ParseEntities(text, flags);
|
|
|
|
return std::move(text);
|
|
|
|
});
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<QString> LinkValue(not_null<PeerData*> peer) {
|
2017-12-22 07:05:20 +00:00
|
|
|
return PlainUsernameValue(
|
|
|
|
peer
|
|
|
|
) | rpl::map([](QString &&username) {
|
|
|
|
return username.isEmpty()
|
|
|
|
? QString()
|
2019-01-21 13:42:21 +00:00
|
|
|
: Core::App().createInternalLinkFull(username);
|
2017-12-22 07:05:20 +00:00
|
|
|
});
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<bool> NotificationsEnabledValue(not_null<PeerData*> peer) {
|
2018-04-09 17:48:29 +00:00
|
|
|
return rpl::merge(
|
|
|
|
Notify::PeerUpdateValue(
|
2017-09-25 09:02:55 +00:00
|
|
|
peer,
|
2017-12-22 07:05:20 +00:00
|
|
|
Notify::PeerUpdate::Flag::NotificationsEnabled
|
2018-04-09 17:48:29 +00:00
|
|
|
) | rpl::map([] { return rpl::empty_value(); }),
|
|
|
|
Auth().data().defaultNotifyUpdates(peer)
|
2017-12-22 07:05:20 +00:00
|
|
|
) | rpl::map([peer] {
|
2018-04-09 17:48:29 +00:00
|
|
|
return !Auth().data().notifyIsMuted(peer);
|
2017-12-22 07:05:20 +00:00
|
|
|
}) | rpl::distinct_until_changed();
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<bool> IsContactValue(not_null<UserData*> user) {
|
2017-10-24 17:11:35 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
2017-09-25 09:02:55 +00:00
|
|
|
user,
|
2017-12-22 07:05:20 +00:00
|
|
|
Notify::PeerUpdate::Flag::UserIsContact
|
|
|
|
) | rpl::map([user] { return user->isContact(); });
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<bool> CanInviteBotToGroupValue(not_null<UserData*> user) {
|
2017-11-07 11:53:05 +00:00
|
|
|
if (!user->botInfo) {
|
|
|
|
return rpl::single(false);
|
|
|
|
}
|
|
|
|
return Notify::PeerUpdateValue(
|
|
|
|
user,
|
2017-12-22 07:05:20 +00:00
|
|
|
Notify::PeerUpdate::Flag::BotCanAddToGroups
|
|
|
|
) | rpl::map([user] {
|
|
|
|
return !user->botInfo->cantJoinGroups;
|
|
|
|
});
|
2017-11-07 11:53:05 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<bool> CanShareContactValue(not_null<UserData*> user) {
|
2017-10-24 17:11:35 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
2017-09-25 09:02:55 +00:00
|
|
|
user,
|
2017-12-22 07:05:20 +00:00
|
|
|
Notify::PeerUpdate::Flag::UserCanShareContact
|
|
|
|
) | rpl::map([user] {
|
|
|
|
return user->canShareThisContact();
|
|
|
|
});
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<bool> CanAddContactValue(not_null<UserData*> user) {
|
2017-09-25 09:02:55 +00:00
|
|
|
using namespace rpl::mappers;
|
|
|
|
return rpl::combine(
|
2019-01-08 13:57:22 +00:00
|
|
|
IsContactValue(user),
|
|
|
|
CanShareContactValue(user),
|
|
|
|
!_1 && _2);
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<bool> AmInChannelValue(not_null<ChannelData*> channel) {
|
2017-11-07 11:53:05 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
|
|
|
channel,
|
2017-12-22 07:05:20 +00:00
|
|
|
Notify::PeerUpdate::Flag::ChannelAmIn
|
|
|
|
) | rpl::map([channel] { return channel->amIn(); });
|
2017-11-07 11:53:05 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<int> MembersCountValue(not_null<PeerData*> peer) {
|
|
|
|
using Flag = Notify::PeerUpdate::Flag;
|
|
|
|
if (const auto chat = peer->asChat()) {
|
2017-10-24 17:11:35 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
2017-11-07 11:53:05 +00:00
|
|
|
peer,
|
2019-01-08 13:57:22 +00:00
|
|
|
Flag::MembersChanged
|
2017-12-22 07:05:20 +00:00
|
|
|
) | rpl::map([chat] {
|
|
|
|
return chat->amIn()
|
|
|
|
? std::max(chat->count, int(chat->participants.size()))
|
|
|
|
: 0;
|
|
|
|
});
|
2019-01-07 12:55:49 +00:00
|
|
|
} else if (const auto channel = peer->asChannel()) {
|
2017-11-10 19:19:43 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
2019-01-08 13:57:22 +00:00
|
|
|
channel,
|
|
|
|
Flag::MembersChanged
|
2017-12-22 07:05:20 +00:00
|
|
|
) | rpl::map([channel] {
|
|
|
|
return channel->membersCount();
|
|
|
|
});
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
Unexpected("User in MembersCountViewer().");
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<int> AdminsCountValue(not_null<PeerData*> peer) {
|
2017-11-08 16:45:30 +00:00
|
|
|
using Flag = Notify::PeerUpdate::Flag;
|
2019-01-07 12:55:49 +00:00
|
|
|
if (const auto chat = peer->asChat()) {
|
|
|
|
return Notify::PeerUpdateValue(
|
|
|
|
chat,
|
|
|
|
Flag::AdminsChanged | Flag::RightsChanged
|
|
|
|
) | rpl::map([=] {
|
2019-01-10 12:38:57 +00:00
|
|
|
return chat->participants.empty()
|
|
|
|
? 0
|
|
|
|
: int(chat->admins.size() + 1); // + creator
|
2019-01-07 12:55:49 +00:00
|
|
|
});
|
|
|
|
} else if (const auto channel = peer->asChannel()) {
|
|
|
|
return Notify::PeerUpdateValue(
|
|
|
|
channel,
|
|
|
|
Flag::AdminsChanged | Flag::RightsChanged
|
|
|
|
) | rpl::map([=] {
|
|
|
|
return channel->canViewAdmins()
|
|
|
|
? channel->adminsCount()
|
|
|
|
: 0;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
Unexpected("User in AdminsCountValue().");
|
2017-11-08 16:45:30 +00:00
|
|
|
}
|
|
|
|
|
2019-03-15 08:20:12 +00:00
|
|
|
|
|
|
|
rpl::producer<int> RestrictionsCountValue(not_null<PeerData*> peer) {
|
|
|
|
const auto countOfRestrictions = [](ChatRestrictions restrictions) {
|
|
|
|
auto count = 0;
|
|
|
|
for (const auto f : Data::ListOfRestrictions()) {
|
|
|
|
if (restrictions & f) count++;
|
|
|
|
}
|
|
|
|
return int(Data::ListOfRestrictions().size()) - count;
|
|
|
|
};
|
|
|
|
|
|
|
|
using Flag = Notify::PeerUpdate::Flag;
|
|
|
|
if (const auto chat = peer->asChat()) {
|
|
|
|
return Notify::PeerUpdateValue(
|
|
|
|
chat,
|
|
|
|
Flag::RightsChanged
|
|
|
|
) | rpl::map([=] {
|
|
|
|
return countOfRestrictions(chat->defaultRestrictions());
|
|
|
|
});
|
|
|
|
} else if (const auto channel = peer->asChannel()) {
|
|
|
|
return Notify::PeerUpdateValue(
|
|
|
|
channel,
|
|
|
|
Flag::RightsChanged
|
|
|
|
) | rpl::map([=] {
|
|
|
|
return countOfRestrictions(channel->defaultRestrictions());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
Unexpected("User in RestrictionsCountValue().");
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<int> RestrictedCountValue(not_null<ChannelData*> channel) {
|
2017-11-08 16:45:30 +00:00
|
|
|
using Flag = Notify::PeerUpdate::Flag;
|
|
|
|
return Notify::PeerUpdateValue(
|
|
|
|
channel,
|
2019-01-05 10:50:04 +00:00
|
|
|
Flag::BannedUsersChanged | Flag::RightsChanged
|
|
|
|
) | rpl::map([=] {
|
2017-12-22 07:05:20 +00:00
|
|
|
return channel->canViewBanned()
|
|
|
|
? channel->restrictedCount()
|
|
|
|
: 0;
|
|
|
|
});
|
2017-11-08 16:45:30 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<int> KickedCountValue(not_null<ChannelData*> channel) {
|
2017-11-08 16:45:30 +00:00
|
|
|
using Flag = Notify::PeerUpdate::Flag;
|
|
|
|
return Notify::PeerUpdateValue(
|
|
|
|
channel,
|
2019-01-05 10:50:04 +00:00
|
|
|
Flag::BannedUsersChanged | Flag::RightsChanged
|
|
|
|
) | rpl::map([=] {
|
2017-12-22 07:05:20 +00:00
|
|
|
return channel->canViewBanned()
|
|
|
|
? channel->kickedCount()
|
|
|
|
: 0;
|
|
|
|
});
|
2017-11-08 16:45:30 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 09:02:55 +00:00
|
|
|
rpl::producer<int> SharedMediaCountValue(
|
|
|
|
not_null<PeerData*> peer,
|
2017-10-31 18:25:22 +00:00
|
|
|
PeerData *migrated,
|
2017-09-25 09:02:55 +00:00
|
|
|
Storage::SharedMediaType type) {
|
|
|
|
auto aroundId = 0;
|
|
|
|
auto limit = 0;
|
|
|
|
auto updated = SharedMediaMergedViewer(
|
2017-10-29 15:32:01 +00:00
|
|
|
SharedMediaMergedKey(
|
|
|
|
SparseIdsMergedSlice::Key(
|
2017-10-31 18:25:22 +00:00
|
|
|
peer->id,
|
2017-10-29 15:32:01 +00:00
|
|
|
migrated ? migrated->id : 0,
|
|
|
|
aroundId),
|
|
|
|
type),
|
2017-09-25 09:02:55 +00:00
|
|
|
limit,
|
2017-12-22 07:05:20 +00:00
|
|
|
limit
|
|
|
|
) | rpl::map([](const SparseIdsMergedSlice &slice) {
|
|
|
|
return slice.fullCount();
|
|
|
|
}) | rpl::filter_optional();
|
2017-09-25 09:02:55 +00:00
|
|
|
return rpl::single(0) | rpl::then(std::move(updated));
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<int> CommonGroupsCountValue(not_null<UserData*> user) {
|
2017-10-24 17:11:35 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
2017-09-25 09:02:55 +00:00
|
|
|
user,
|
2017-12-22 07:05:20 +00:00
|
|
|
Notify::PeerUpdate::Flag::UserCommonChatsChanged
|
|
|
|
) | rpl::map([user] {
|
|
|
|
return user->commonChatsCount();
|
|
|
|
});
|
2017-09-25 09:02:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<bool> CanAddMemberValue(not_null<PeerData*> peer) {
|
2017-09-25 16:06:53 +00:00
|
|
|
if (auto chat = peer->asChat()) {
|
2017-10-24 17:11:35 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
2017-09-25 16:06:53 +00:00
|
|
|
chat,
|
2019-01-05 10:50:04 +00:00
|
|
|
Notify::PeerUpdate::Flag::RightsChanged
|
|
|
|
) | rpl::map([=] {
|
|
|
|
return chat->canAddMembers();
|
2017-12-22 07:05:20 +00:00
|
|
|
});
|
2017-09-25 16:06:53 +00:00
|
|
|
} else if (auto channel = peer->asChannel()) {
|
2017-10-24 17:11:35 +00:00
|
|
|
return Notify::PeerUpdateValue(
|
2017-09-25 16:06:53 +00:00
|
|
|
channel,
|
2019-01-05 10:50:04 +00:00
|
|
|
Notify::PeerUpdate::Flag::RightsChanged
|
|
|
|
) | rpl::map([=] {
|
2017-12-22 07:05:20 +00:00
|
|
|
return channel->canAddMembers();
|
|
|
|
});
|
2017-09-25 16:06:53 +00:00
|
|
|
}
|
|
|
|
return rpl::single(false);
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<bool> VerifiedValue(not_null<PeerData*> peer) {
|
2017-11-06 14:13:56 +00:00
|
|
|
if (auto user = peer->asUser()) {
|
|
|
|
return Data::PeerFlagValue(user, MTPDuser::Flag::f_verified);
|
|
|
|
} else if (auto channel = peer->asChannel()) {
|
|
|
|
return Data::PeerFlagValue(
|
|
|
|
channel,
|
|
|
|
MTPDchannel::Flag::f_verified);
|
|
|
|
}
|
|
|
|
return rpl::single(false);
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:55:49 +00:00
|
|
|
rpl::producer<int> FeedChannelsCountValue(not_null<Data::Feed*> feed) {
|
2018-02-07 12:40:37 +00:00
|
|
|
using Flag = Data::FeedUpdateFlag;
|
|
|
|
return rpl::single(
|
|
|
|
Data::FeedUpdate{ feed, Flag::Channels }
|
|
|
|
) | rpl::then(
|
|
|
|
Auth().data().feedUpdated()
|
|
|
|
) | rpl::filter([=](const Data::FeedUpdate &update) {
|
|
|
|
return (update.feed == feed) && (update.flag == Flag::Channels);
|
|
|
|
}) | rpl::filter([=] {
|
|
|
|
return feed->channelsLoaded();
|
|
|
|
}) | rpl::map([=] {
|
|
|
|
return int(feed->channels().size());
|
|
|
|
}) | rpl::distinct_until_changed();
|
|
|
|
}
|
|
|
|
|
2017-09-25 09:02:55 +00:00
|
|
|
} // namespace Profile
|
|
|
|
} // namespace Info
|