Files
AyuGramDesktop/Telegram/SourceFiles/info/profile/info_profile_status_label.cpp
T
2026-07-10 14:04:30 +04:00

232 lines
6.2 KiB
C++

/*
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_status_label.h"
#include "data/data_changes.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_community.h"
#include "data/data_peer.h"
#include "data/data_peer_values.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "ui/widgets/labels.h"
#include "ui/text/text_utilities.h"
#include "ui/basic_click_handlers.h"
#include "base/unixtime.h"
#include "styles/style_info.h"
namespace Info::Profile {
namespace {
[[nodiscard]] auto MembersStatusText(int count) {
return tr::lng_chat_status_members(tr::now, lt_count_decimal, count);
};
[[nodiscard]] auto OnlineStatusText(int count) {
return tr::lng_chat_status_online(tr::now, lt_count_decimal, count);
};
[[nodiscard]] auto ChatStatusText(
int fullCount,
int onlineCount,
bool isGroup) {
if (onlineCount > 1 && onlineCount <= fullCount) {
return tr::lng_chat_status_members_online(
tr::now,
lt_members_count,
MembersStatusText(fullCount),
lt_online_count,
OnlineStatusText(onlineCount));
} else if (fullCount > 0) {
return isGroup
? tr::lng_chat_status_members(
tr::now,
lt_count_decimal,
fullCount)
: tr::lng_chat_status_subscribers(
tr::now,
lt_count_decimal,
fullCount);
}
return isGroup
? tr::lng_group_status(tr::now)
: tr::lng_channel_status(tr::now);
};
[[nodiscard]] auto ChannelTypeText(not_null<ChannelData*> channel) {
const auto isPublic = channel->isPublic();
const auto isMegagroup = channel->isMegagroup();
return (isPublic
? (isMegagroup
? tr::lng_create_public_group_title(tr::now)
: tr::lng_create_public_channel_title(tr::now))
: (isMegagroup
? tr::lng_create_private_group_title(tr::now)
: tr::lng_create_private_channel_title(tr::now))).toLower();
};
[[nodiscard]] bool PeerHiddenInCommunity(not_null<PeerData*> peer) {
const auto communityId = Data::PeerLinkedCommunityId(peer);
if (!communityId) {
return false;
}
const auto community = peer->owner().channel(communityId);
const auto info = community->communityInfo();
return info && info->isHidden(peer);
}
[[nodiscard]] TextWithEntities MaybeHiddenPrefixed(
TextWithEntities body,
bool hidden) {
if (!hidden) {
return body;
}
using namespace Ui::Text;
return IconEmoji(&st::infoStatusHiddenIcon)
.append(' ')
.append(Link(tr::lng_community_hidden_status(tr::now), 2))
.append(QString::fromUtf8(" \xC2\xB7 "))
.append(std::move(body));
}
} // namespace
StatusLabel::StatusLabel(
not_null<Ui::FlatLabel*> label,
not_null<PeerData*> peer)
: _label(label)
, _peer(peer)
, _refreshTimer([=] { refresh(); }) {
if (const auto communityId = Data::PeerLinkedCommunityId(_peer)) {
const auto community = _peer->owner().channel(communityId);
community->session().changes().peerFlagsValue(
community,
Data::PeerUpdate::Flag::FullInfo
) | rpl::on_next([=] {
refresh();
}, _lifetime);
}
}
void StatusLabel::setOnlineCount(int count) {
_onlineCount = count;
refresh();
}
void StatusLabel::refresh() {
const auto hidden = PeerHiddenInCommunity(_peer);
auto hasMembersLink = [&] {
if (auto megagroup = _peer->asMegagroup()) {
return megagroup->canViewMembers();
}
return false;
}();
auto statusText = [&]() -> TextWithEntities {
using namespace Ui::Text;
auto currentTime = base::unixtime::now();
if (auto user = _peer->asUser()) {
const auto result = Data::OnlineTextFull(user, currentTime);
const auto showOnline = Data::OnlineTextActive(
user,
currentTime);
const auto updateIn = Data::OnlineChangeTimeout(
user,
currentTime);
if (showOnline) {
_refreshTimer.callOnce(updateIn);
}
return MaybeHiddenPrefixed(
(showOnline && _colorized)
? Ui::Text::Colorized(result)
: TextWithEntities{ .text = result },
hidden);
} else if (auto chat = _peer->asChat()) {
if (!chat->amIn()) {
return tr::lng_chat_status_unaccessible(
{},
WithEntities);
}
const auto onlineCount = _onlineCount;
const auto fullCount = std::max(
chat->count,
int(chat->participants.size()));
return MaybeHiddenPrefixed(
{ .text = ChatStatusText(fullCount, onlineCount, true) },
hidden);
} else if (auto broadcast = _peer->monoforumBroadcast()) {
if (!broadcast->membersCountKnown()) {
return TextWithEntities{ .text = ChannelTypeText(broadcast) };
}
auto result = ChatStatusText(
broadcast->membersCount(),
0,
false);
return TextWithEntities{ .text = result };
} else if (auto channel = _peer->asChannel()) {
if (!channel->membersCountKnown()) {
auto result = ChannelTypeText(channel);
return MaybeHiddenPrefixed(
hasMembersLink
? tr::link(result)
: TextWithEntities{ .text = result },
hidden);
}
const auto onlineCount = _onlineCount;
const auto fullCount = channel->membersCount();
auto result = ChatStatusText(
fullCount,
onlineCount,
channel->isMegagroup());
return MaybeHiddenPrefixed(
hasMembersLink
? tr::link(result)
: TextWithEntities{ .text = result },
hidden);
}
return tr::lng_chat_status_unaccessible(tr::now, WithEntities);
}();
_label->setMarkedText(statusText);
if (hasMembersLink && _membersLinkCallback) {
_label->setLink(
1,
std::make_shared<LambdaClickHandler>(_membersLinkCallback));
}
if (hidden && _hiddenLinkCallback) {
_label->setLink(
2,
std::make_shared<LambdaClickHandler>(_hiddenLinkCallback));
}
}
void StatusLabel::setHiddenLinkCallback(Fn<void()> callback) {
_hiddenLinkCallback = std::move(callback);
}
Fn<void()> StatusLabel::hiddenLinkCallback() const {
return _hiddenLinkCallback;
}
void StatusLabel::setMembersLinkCallback(Fn<void()> callback) {
_membersLinkCallback = std::move(callback);
}
Fn<void()> StatusLabel::membersLinkCallback() const {
return _membersLinkCallback;
}
void StatusLabel::setColorized(bool enabled) {
_colorized = enabled;
refresh();
}
} // namespace Info::Profile