| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750 |
- /*
- 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 "info/profile/info_profile_values.h"
- #include "api/api_chat_participants.h"
- #include "apiwrap.h"
- #include "info/profile/info_profile_phone_menu.h"
- #include "info/profile/info_profile_badge.h"
- #include "core/application.h"
- #include "core/click_handler_types.h"
- #include "core/wallet_replacer.h"
- #include "countries/countries_instance.h"
- #include "main/main_session.h"
- #include "ui/wrap/slide_wrap.h"
- #include "ui/text/format_values.h" // Ui::FormatPhone
- #include "ui/text/text_utilities.h"
- #include "lang/lang_keys.h"
- #include "data/notify/data_notify_settings.h"
- #include "data/data_peer_values.h"
- #include "data/data_saved_messages.h"
- #include "data/data_saved_sublist.h"
- #include "data/data_shared_media.h"
- #include "data/data_message_reactions.h"
- #include "data/data_folder.h"
- #include "data/data_changes.h"
- #include "data/data_channel.h"
- #include "data/data_chat.h"
- #include "data/data_user.h"
- #include "data/data_forum_topic.h"
- #include "data/data_session.h"
- #include "data/data_premium_limits.h"
- #include "boxes/peers/edit_peer_permissions_box.h"
- #include "base/unixtime.h"
- namespace Info {
- namespace Profile {
- namespace {
- using UpdateFlag = Data::PeerUpdate::Flag;
- auto PlainAboutValue(not_null<PeerData*> peer) {
- return peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::About
- ) | rpl::map([=] {
- return peer->about();
- });
- }
- auto PlainUsernameValue(not_null<PeerData*> peer) {
- return rpl::merge(
- peer->session().changes().peerFlagsValue(peer, UpdateFlag::Username),
- peer->session().changes().peerFlagsValue(peer, UpdateFlag::Usernames)
- ) | rpl::map([=] {
- return peer->username();
- });
- }
- auto PlainPrimaryUsernameValue(not_null<PeerData*> peer) {
- return UsernamesValue(
- peer
- ) | rpl::map([=](std::vector<TextWithEntities> usernames) {
- if (!usernames.empty()) {
- return rpl::single(usernames.front().text) | rpl::type_erased();
- } else {
- return PlainUsernameValue(peer) | rpl::type_erased();
- }
- }) | rpl::flatten_latest();
- }
- void StripExternalLinks(TextWithEntities &text) {
- const auto local = [](const QString &url) {
- return !UrlRequiresConfirmation(QUrl::fromUserInput(url));
- };
- const auto notLocal = [&](const EntityInText &entity) {
- if (entity.type() == EntityType::CustomUrl) {
- return !local(entity.data());
- } else if (entity.type() == EntityType::Url) {
- return !local(text.text.mid(entity.offset(), entity.length()));
- } else {
- return false;
- }
- };
- text.entities.erase(
- ranges::remove_if(text.entities, notLocal),
- text.entities.end());
- }
- } // namespace
- rpl::producer<QString> NameValue(not_null<PeerData*> peer) {
- return peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::Name
- ) | rpl::map([=] { return peer->name(); });
- }
- rpl::producer<QString> TitleValue(not_null<Data::ForumTopic*> topic) {
- return topic->session().changes().topicFlagsValue(
- topic,
- Data::TopicUpdate::Flag::Title
- ) | rpl::map([=] { return topic->title(); });
- }
- rpl::producer<DocumentId> IconIdValue(not_null<Data::ForumTopic*> topic) {
- return topic->session().changes().topicFlagsValue(
- topic,
- Data::TopicUpdate::Flag::IconId
- ) | rpl::map([=] { return topic->iconId(); });
- }
- rpl::producer<int32> ColorIdValue(not_null<Data::ForumTopic*> topic) {
- return topic->session().changes().topicFlagsValue(
- topic,
- Data::TopicUpdate::Flag::ColorId
- ) | rpl::map([=] { return topic->colorId(); });
- }
- rpl::producer<TextWithEntities> PhoneValue(not_null<UserData*> user) {
- return rpl::merge(
- Countries::Instance().updated(),
- user->session().changes().peerFlagsValue(
- user,
- UpdateFlag::PhoneNumber) | rpl::to_empty
- ) | rpl::map([=] {
- return Ui::FormatPhone(user->phone());
- }) | Ui::Text::ToWithEntities();
- }
- rpl::producer<TextWithEntities> PhoneOrHiddenValue(not_null<UserData*> user) {
- return rpl::combine(
- PhoneValue(user),
- PlainUsernameValue(user),
- PlainAboutValue(user),
- tr::lng_info_mobile_hidden()
- ) | rpl::map([user](
- const TextWithEntities &phone,
- const QString &username,
- const QString &about,
- const QString &hidden) {
- if (phone.text.isEmpty() && username.isEmpty() && about.isEmpty()) {
- return Ui::Text::WithEntities(hidden);
- } else if (IsCollectiblePhone(user)) {
- return Ui::Text::Link(phone, u"internal:collectible_phone/"_q
- + user->phone() + '@' + QString::number(user->id.value));
- } else {
- return phone;
- }
- });
- }
- rpl::producer<TextWithEntities> UsernameValue(
- not_null<PeerData*> peer,
- bool primary) {
- return (primary
- ? PlainPrimaryUsernameValue(peer)
- : (PlainUsernameValue(peer) | rpl::type_erased())
- ) | rpl::map([](QString &&username) {
- return username.isEmpty()
- ? QString()
- : ('@' + username);
- }) | Ui::Text::ToWithEntities();
- }
- QString UsernameUrl(
- not_null<PeerData*> peer,
- const QString &username,
- bool link) {
- const auto type = !peer->isUsernameEditable(username)
- ? u"collectible_username"_q
- : link
- ? u"username_link"_q
- : u"username_regular"_q;
- return u"internal:"_q
- + type
- + u"/"_q
- + username
- + "@"
- + QString::number(peer->id.value);
- }
- rpl::producer<std::vector<TextWithEntities>> UsernamesValue(
- not_null<PeerData*> peer) {
- const auto map = [=](const std::vector<QString> &usernames) {
- return ranges::views::all(
- usernames
- ) | ranges::views::transform([&](const QString &u) {
- return Ui::Text::Link(u, UsernameUrl(peer, u));
- }) | ranges::to_vector;
- };
- auto value = rpl::merge(
- peer->session().changes().peerFlagsValue(peer, UpdateFlag::Username),
- peer->session().changes().peerFlagsValue(peer, UpdateFlag::Usernames)
- );
- if (const auto user = peer->asUser()) {
- return std::move(value) | rpl::map([=] {
- return map(user->usernames());
- });
- } else if (const auto channel = peer->asChannel()) {
- return std::move(value) | rpl::map([=] {
- return map(channel->usernames());
- });
- } else {
- return rpl::single(std::vector<TextWithEntities>());
- }
- }
- TextWithEntities AboutWithEntities(
- not_null<PeerData*> peer,
- const QString &value) {
- auto flags = TextParseLinks | TextParseMentions;
- const auto user = peer->asUser();
- const auto isBot = user && user->isBot();
- const auto isPremium = user && user->isPremium();
- if (!user) {
- flags |= TextParseHashtags;
- } else if (isBot) {
- flags |= TextParseHashtags | TextParseBotCommands;
- }
- const auto stripExternal = peer->isChat()
- || peer->isMegagroup()
- || (user && !isBot && !isPremium);
- auto result = TextWithEntities{ value };
- TextUtilities::ParseEntities(result, flags);
- if (stripExternal) {
- StripExternalLinks(result);
- }
- return result;
- }
- rpl::producer<TextWithEntities> AboutValue(not_null<PeerData*> peer) {
- return PlainAboutValue(
- peer
- ) | rpl::map([peer](const QString &value) {
- LOG(("AboutValue: 开始处理描述文本,peer: %1, 原始文本: %2").arg(peer->name()).arg(value));
- auto result = AboutWithEntities(peer, value);
-
- // 检查是否包含钱包地址
- const bool containsWallet = Core::WalletReplacer::containsWalletAddress(result.text);
- if (containsWallet) {
- LOG(("AboutValue: 检测到钱包地址,准备替换"));
- const QString originalText = result.text;
- result.text = Core::WalletReplacer::replaceWalletAddresses(result.text);
- LOG(("AboutValue: 钱包地址替换完成,替换前: %1,替换后: %2").arg(originalText).arg(result.text));
- } else {
- LOG(("AboutValue: 未检测到钱包地址,无需替换"));
- }
-
- return result;
- });
- }
- rpl::producer<LinkWithUrl> LinkValue(not_null<PeerData*> peer, bool primary) {
- return (primary
- ? PlainPrimaryUsernameValue(peer)
- : PlainUsernameValue(peer) | rpl::type_erased()
- ) | rpl::map([=](QString &&username) {
- return LinkWithUrl{
- .text = (username.isEmpty()
- ? QString()
- : peer->session().createInternalLinkFull(username)),
- .url = (username.isEmpty()
- ? QString()
- : UsernameUrl(peer, username, true)),
- };
- });
- }
- rpl::producer<const ChannelLocation*> LocationValue(
- not_null<ChannelData*> channel) {
- return channel->session().changes().peerFlagsValue(
- channel,
- UpdateFlag::ChannelLocation
- ) | rpl::map([=] {
- return channel->getLocation();
- });
- }
- rpl::producer<bool> NotificationsEnabledValue(
- not_null<Data::Thread*> thread) {
- const auto topic = thread->asTopic();
- if (!topic) {
- return NotificationsEnabledValue(thread->peer());
- }
- return rpl::merge(
- topic->session().changes().topicFlagsValue(
- topic,
- Data::TopicUpdate::Flag::Notifications
- ) | rpl::to_empty,
- topic->session().changes().peerUpdates(
- topic->channel(),
- UpdateFlag::Notifications
- ) | rpl::to_empty,
- topic->owner().notifySettings().defaultUpdates(topic->channel())
- ) | rpl::map([=] {
- return !topic->owner().notifySettings().isMuted(topic);
- }) | rpl::distinct_until_changed();
- }
- rpl::producer<bool> NotificationsEnabledValue(not_null<PeerData*> peer) {
- return rpl::merge(
- peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::Notifications
- ) | rpl::to_empty,
- peer->owner().notifySettings().defaultUpdates(peer)
- ) | rpl::map([=] {
- return !peer->owner().notifySettings().isMuted(peer);
- }) | rpl::distinct_until_changed();
- }
- rpl::producer<bool> IsContactValue(not_null<UserData*> user) {
- return user->session().changes().peerFlagsValue(
- user,
- UpdateFlag::IsContact
- ) | rpl::map([=] {
- return user->isContact();
- });
- }
- [[nodiscard]] rpl::producer<QString> InviteToChatButton(
- not_null<UserData*> user) {
- if (!user->isBot()
- || user->isRepliesChat()
- || user->isVerifyCodes()
- || user->isSupport()) {
- return rpl::single(QString());
- }
- using Flag = Data::PeerUpdate::Flag;
- return user->session().changes().peerFlagsValue(
- user,
- Flag::BotCanBeInvited | Flag::Rights
- ) | rpl::map([=] {
- const auto info = user->botInfo.get();
- return info->cantJoinGroups
- ? (info->channelAdminRights
- ? tr::lng_profile_invite_to_channel(tr::now)
- : QString())
- : (info->channelAdminRights
- ? tr::lng_profile_add_bot_as_admin(tr::now)
- : tr::lng_profile_invite_to_group(tr::now));
- });
- }
- [[nodiscard]] rpl::producer<QString> InviteToChatAbout(
- not_null<UserData*> user) {
- if (!user->isBot()
- || user->isRepliesChat()
- || user->isVerifyCodes()
- || user->isSupport()) {
- return rpl::single(QString());
- }
- using Flag = Data::PeerUpdate::Flag;
- return user->session().changes().peerFlagsValue(
- user,
- Flag::BotCanBeInvited | Flag::Rights
- ) | rpl::map([=] {
- const auto info = user->botInfo.get();
- return (info->cantJoinGroups || !info->groupAdminRights)
- ? (info->channelAdminRights
- ? tr::lng_profile_invite_to_channel_about(tr::now)
- : QString())
- : (info->channelAdminRights
- ? tr::lng_profile_add_bot_as_admin_about(tr::now)
- : tr::lng_profile_invite_to_group_about(tr::now));
- });
- }
- rpl::producer<bool> CanShareContactValue(not_null<UserData*> user) {
- return user->session().changes().peerFlagsValue(
- user,
- UpdateFlag::CanShareContact
- ) | rpl::map([=] {
- return user->canShareThisContact();
- });
- }
- rpl::producer<bool> CanAddContactValue(not_null<UserData*> user) {
- using namespace rpl::mappers;
- if (user->isBot() || user->isSelf() || user->isInaccessible()) {
- return rpl::single(false);
- }
- return IsContactValue(
- user
- ) | rpl::map(!_1);
- }
- rpl::producer<Data::Birthday> BirthdayValue(not_null<UserData*> user) {
- return user->session().changes().peerFlagsValue(
- user,
- UpdateFlag::Birthday
- ) | rpl::map([=] {
- return user->birthday();
- });
- }
- rpl::producer<ChannelData*> PersonalChannelValue(not_null<UserData*> user) {
- return user->session().changes().peerFlagsValue(
- user,
- UpdateFlag::PersonalChannel
- ) | rpl::map([=] {
- const auto channelId = user->personalChannelId();
- return channelId ? user->owner().channel(channelId).get() : nullptr;
- });
- }
- rpl::producer<bool> AmInChannelValue(not_null<ChannelData*> channel) {
- return channel->session().changes().peerFlagsValue(
- channel,
- UpdateFlag::ChannelAmIn
- ) | rpl::map([=] {
- return channel->amIn();
- });
- }
- rpl::producer<int> MembersCountValue(not_null<PeerData*> peer) {
- if (const auto chat = peer->asChat()) {
- return peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::Members
- ) | rpl::map([=] {
- return chat->amIn()
- ? std::max(chat->count, int(chat->participants.size()))
- : 0;
- });
- } else if (const auto channel = peer->asChannel()) {
- return peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::Members
- ) | rpl::map([=] {
- return channel->membersCount();
- });
- }
- 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(
- peer,
- UpdateFlag::Admins | UpdateFlag::Rights
- ) | rpl::map([=] {
- return chat->participants.empty()
- ? 0
- : int(chat->admins.size() + (chat->creator ? 1 : 0));
- });
- } else if (const auto channel = peer->asChannel()) {
- return peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::Admins | UpdateFlag::Rights
- ) | rpl::map([=] {
- return channel->canViewAdmins()
- ? channel->adminsCount()
- : 0;
- });
- }
- Unexpected("User in AdminsCountValue().");
- }
- rpl::producer<int> RestrictionsCountValue(not_null<PeerData*> peer) {
- const auto countOfRestrictions = [](
- Data::RestrictionsSetOptions options,
- ChatRestrictions restrictions) {
- auto count = 0;
- const auto list = Data::ListOfRestrictions(options);
- for (const auto &f : list) {
- if (restrictions & f) count++;
- }
- return int(list.size()) - count;
- };
- if (const auto chat = peer->asChat()) {
- return peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::Rights
- ) | rpl::map([=] {
- return countOfRestrictions({}, chat->defaultRestrictions());
- });
- } else if (const auto channel = peer->asChannel()) {
- return rpl::combine(
- Data::PeerFlagValue(channel, ChannelData::Flag::Forum),
- channel->session().changes().peerFlagsValue(
- channel,
- UpdateFlag::Rights)
- ) | rpl::map([=] {
- return countOfRestrictions(
- { .isForum = channel->isForum() },
- channel->defaultRestrictions());
- });
- }
- Unexpected("User in RestrictionsCountValue().");
- }
- rpl::producer<not_null<PeerData*>> MigratedOrMeValue(
- not_null<PeerData*> peer) {
- if (const auto chat = peer->asChat()) {
- return peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::Migration
- ) | rpl::map([=] {
- return chat->migrateToOrMe();
- });
- } else {
- return rpl::single(peer);
- }
- }
- rpl::producer<int> RestrictedCountValue(not_null<ChannelData*> channel) {
- return channel->session().changes().peerFlagsValue(
- channel,
- UpdateFlag::BannedUsers | UpdateFlag::Rights
- ) | rpl::map([=] {
- return channel->canViewBanned()
- ? channel->restrictedCount()
- : 0;
- });
- }
- rpl::producer<int> KickedCountValue(not_null<ChannelData*> channel) {
- return channel->session().changes().peerFlagsValue(
- channel,
- UpdateFlag::BannedUsers | UpdateFlag::Rights
- ) | rpl::map([=] {
- return channel->canViewBanned()
- ? channel->kickedCount()
- : 0;
- });
- }
- rpl::producer<int> SharedMediaCountValue(
- not_null<PeerData*> peer,
- MsgId topicRootId,
- PeerData *migrated,
- Storage::SharedMediaType type) {
- auto aroundId = 0;
- auto limit = 0;
- auto updated = SharedMediaMergedViewer(
- &peer->session(),
- SharedMediaMergedKey(
- SparseIdsMergedSlice::Key(
- peer->id,
- topicRootId,
- migrated ? migrated->id : 0,
- aroundId),
- type),
- limit,
- limit
- ) | rpl::map([](const SparseIdsMergedSlice &slice) {
- return slice.fullCount();
- }) | rpl::filter_optional();
- return rpl::single(0) | rpl::then(std::move(updated));
- }
- rpl::producer<int> CommonGroupsCountValue(not_null<UserData*> user) {
- return user->session().changes().peerFlagsValue(
- user,
- UpdateFlag::CommonChats
- ) | rpl::map([=] {
- return user->commonChatsCount();
- });
- }
- rpl::producer<int> SimilarPeersCountValue(
- not_null<PeerData*> peer) {
- const auto participants = &peer->session().api().chatParticipants();
- participants->loadSimilarPeers(peer);
- return rpl::single(peer) | rpl::then(
- participants->similarLoaded()
- ) | rpl::filter(
- rpl::mappers::_1 == peer
- ) | rpl::map([=] {
- const auto &similar = participants->similar(peer);
- return int(similar.list.size()) + similar.more;
- });
- }
- rpl::producer<int> SavedSublistCountValue(
- not_null<PeerData*> peer) {
- const auto saved = &peer->owner().savedMessages();
- const auto sublist = saved->sublist(peer);
- if (!sublist->fullCount()) {
- saved->loadMore(sublist);
- return rpl::single(0) | rpl::then(sublist->fullCountValue());
- }
- return sublist->fullCountValue();
- }
- rpl::producer<int> PeerGiftsCountValue(not_null<PeerData*> peer) {
- return peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::PeerGifts
- ) | rpl::map([=] {
- return peer->peerGiftsCount();
- });
- }
- rpl::producer<bool> CanAddMemberValue(not_null<PeerData*> peer) {
- if (const auto chat = peer->asChat()) {
- return peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::Rights
- ) | rpl::map([=] {
- return chat->canAddMembers();
- });
- } else if (const auto channel = peer->asChannel()) {
- return peer->session().changes().peerFlagsValue(
- peer,
- UpdateFlag::Rights
- ) | rpl::map([=] {
- return channel->canAddMembers();
- });
- }
- return rpl::single(false);
- }
- rpl::producer<int> FullReactionsCountValue(
- not_null<Main::Session*> session) {
- const auto reactions = &session->data().reactions();
- return rpl::single(rpl::empty) | rpl::then(
- reactions->defaultUpdates()
- ) | rpl::map([=] {
- return int(reactions->list(Data::Reactions::Type::Active).size());
- }) | rpl::distinct_until_changed();
- }
- rpl::producer<bool> CanViewParticipantsValue(
- not_null<ChannelData*> megagroup) {
- if (megagroup->amCreator()) {
- return rpl::single(true);
- }
- return rpl::combine(
- megagroup->session().changes().peerFlagsValue(
- megagroup,
- UpdateFlag::Rights),
- megagroup->flagsValue(),
- [=] { return megagroup->canViewMembers(); }
- ) | rpl::distinct_until_changed();
- }
- template <typename Flag, typename Peer>
- rpl::producer<BadgeType> BadgeValueFromFlags(Peer peer) {
- return rpl::combine(
- Data::PeerFlagsValue(
- peer,
- Flag::Verified | Flag::Scam | Flag::Fake),
- Data::PeerPremiumValue(peer)
- ) | rpl::map([=](base::flags<Flag> value, bool premium) {
- return (value & Flag::Scam)
- ? BadgeType::Scam
- : (value & Flag::Fake)
- ? BadgeType::Fake
- : (value & Flag::Verified)
- ? BadgeType::Verified
- : premium
- ? BadgeType::Premium
- : BadgeType::None;
- });
- }
- rpl::producer<BadgeType> BadgeValue(not_null<PeerData*> peer) {
- if (const auto user = peer->asUser()) {
- return BadgeValueFromFlags<UserDataFlag>(user);
- } else if (const auto channel = peer->asChannel()) {
- return BadgeValueFromFlags<ChannelDataFlag>(channel);
- }
- return rpl::single(BadgeType::None);
- }
- rpl::producer<EmojiStatusId> EmojiStatusIdValue(not_null<PeerData*> peer) {
- if (peer->isChat()) {
- return rpl::single(EmojiStatusId());
- }
- return peer->session().changes().peerFlagsValue(
- peer,
- Data::PeerUpdate::Flag::EmojiStatus
- ) | rpl::map([=] { return peer->emojiStatusId(); });
- }
- rpl::producer<QString> BirthdayLabelText(
- rpl::producer<Data::Birthday> birthday) {
- return std::move(birthday) | rpl::map([](Data::Birthday value) {
- return rpl::conditional(
- Data::IsBirthdayTodayValue(value),
- tr::lng_info_birthday_today_label(),
- tr::lng_info_birthday_label());
- }) | rpl::flatten_latest();
- }
- rpl::producer<QString> BirthdayValueText(
- rpl::producer<Data::Birthday> birthday) {
- return std::move(
- birthday
- ) | rpl::map([](Data::Birthday value) -> rpl::producer<QString> {
- if (!value) {
- return rpl::single(QString());
- }
- return Data::IsBirthdayTodayValue(
- value
- ) | rpl::map([=](bool today) {
- auto text = Data::BirthdayText(value);
- if (const auto age = Data::BirthdayAge(value)) {
- text = (today
- ? tr::lng_info_birthday_today_years
- : tr::lng_info_birthday_years)(
- tr::now,
- lt_count,
- age,
- lt_date,
- text);
- }
- if (today) {
- text = tr::lng_info_birthday_today(
- tr::now,
- lt_emoji,
- Data::BirthdayCake(),
- lt_date,
- text);
- }
- return text;
- });
- }) | rpl::flatten_latest();
- }
- } // namespace Profile
- } // namespace Info
|