Allow emoji status edit from self profile.

This commit is contained in:
John Preston 2022-08-09 20:15:42 +03:00
parent 21fd381778
commit 165d3143de
9 changed files with 158 additions and 55 deletions

View file

@ -400,11 +400,6 @@ ChannelData *Session::channelLoaded(ChannelId id) const {
return nullptr; return nullptr;
} }
AssertIsDebug();
base::flat_map<
not_null<Data::Session*>,
base::flat_set<not_null<DocumentData*>>> Emojis;
not_null<UserData*> Session::processUser(const MTPUser &data) { not_null<UserData*> Session::processUser(const MTPUser &data) {
const auto result = user(data.match([](const auto &data) { const auto result = user(data.match([](const auto &data) {
return data.vid().v; return data.vid().v;
@ -564,20 +559,10 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
const MTPDemojiStatus &data) { const MTPDemojiStatus &data) {
return DocumentId(data.vdocument_id().v); return DocumentId(data.vdocument_id().v);
}, [&](const MTPDemojiStatusEmpty &) { }, [&](const MTPDemojiStatusEmpty &) {
//return DocumentId(); return DocumentId();
auto &emojis = Emojis[this];
return emojis.empty()
? DocumentId()
: (*(emojis.begin()
+ base::RandomIndex(emojis.size())))->id;
})); }));
} else { } else {
//result->setEmojiStatus(0); result->setEmojiStatus(0);
auto &emojis = Emojis[this];
result->setEmojiStatus(emojis.empty()
? DocumentId()
: (*(emojis.begin()
+ base::RandomIndex(emojis.size())))->id);
} }
if (!minimal) { if (!minimal) {
if (const auto botInfoVersion = data.vbot_info_version()) { if (const auto botInfoVersion = data.vbot_info_version()) {
@ -2968,23 +2953,6 @@ void Session::documentApplyFields(
if (dc != 0 && access != 0) { if (dc != 0 && access != 0) {
document->setRemoteLocation(dc, access, fileReference); document->setRemoteLocation(dc, access, fileReference);
} }
AssertIsDebug();
if (document->isPremiumEmoji()) {
auto &emojis = Emojis[this];
if (emojis.emplace(document).second) {
const auto size = int(emojis.size());
crl::on_main(_session, [=] {
for (auto &[id, peer] : _peers) {
if (const auto user = peer->asUser()) {
if (user->isPremium() && !base::RandomIndex(size)) {
user->setEmojiStatus(document->id);
}
}
}
});
}
}
} }
not_null<WebPageData*> Session::webpage(WebPageId id) { not_null<WebPageData*> Session::webpage(WebPageId id) {

View file

@ -232,11 +232,13 @@ InnerWidget::InnerWidget(
| UpdateFlag::Photo | UpdateFlag::Photo
| UpdateFlag::IsContact | UpdateFlag::IsContact
| UpdateFlag::FullInfo | UpdateFlag::FullInfo
| UpdateFlag::EmojiStatus
) | rpl::start_with_next([=](const Data::PeerUpdate &update) { ) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
if (update.flags if (update.flags
& (UpdateFlag::Name & (UpdateFlag::Name
| UpdateFlag::Photo | UpdateFlag::Photo
| UpdateFlag::FullInfo)) { | UpdateFlag::FullInfo
| UpdateFlag::EmojiStatus)) {
const auto peer = update.peer; const auto peer = update.peer;
const auto history = peer->owner().historyLoaded(peer); const auto history = peer->owner().historyLoaded(peer);
if (_state == WidgetState::Default) { if (_state == WidgetState::Default) {
@ -2066,7 +2068,6 @@ void InnerWidget::visibleTopBottomUpdated(
_loadMoreCallback(); _loadMoreCallback();
} }
} }
} }
void InnerWidget::itemRemoved(not_null<const HistoryItem*> item) { void InnerWidget::itemRemoved(not_null<const HistoryItem*> item) {

View file

@ -165,6 +165,7 @@ TopBarWidget::TopBarWidget(
| UpdateFlag::Members | UpdateFlag::Members
| UpdateFlag::SupportInfo | UpdateFlag::SupportInfo
| UpdateFlag::Rights | UpdateFlag::Rights
| UpdateFlag::EmojiStatus
) | rpl::start_with_next([=](const Data::PeerUpdate &update) { ) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
if (update.flags & UpdateFlag::HasCalls) { if (update.flags & UpdateFlag::HasCalls) {
if (update.peer->isUser() if (update.peer->isUser()
@ -182,6 +183,10 @@ TopBarWidget::TopBarWidget(
| UpdateFlag::SupportInfo)) { | UpdateFlag::SupportInfo)) {
updateOnlineDisplay(); updateOnlineDisplay();
} }
if ((update.flags & UpdateFlag::EmojiStatus)
&& (_activeChat.key.peer() == update.peer)) {
this->update();
}
}, lifetime()); }, lifetime());
rpl::combine( rpl::combine(

View file

@ -11,7 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_user.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_session.h"
#include "data/data_document.h"
#include "data/stickers/data_custom_emoji.h"
#include "editor/photo_editor_layer_widget.h" #include "editor/photo_editor_layer_widget.h"
#include "info/profile/info_profile_values.h" #include "info/profile/info_profile_values.h"
#include "info/info_controller.h" #include "info/info_controller.h"
@ -25,13 +29,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/unread_badge.h" #include "ui/unread_badge.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "window/window_controller.h"
#include "core/application.h" #include "core/application.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_premium.h" #include "settings/settings_premium.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "mainwindow.h"
#include "api/api_peer_photo.h" #include "api/api_peer_photo.h"
#include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_selector.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_chat_helpers.h"
namespace Info { namespace Info {
namespace Profile { namespace Profile {
@ -174,14 +183,11 @@ void Cover::initViewers(rpl::producer<QString> title) {
} else if (_peer->isSelf()) { } else if (_peer->isSelf()) {
refreshUploadPhotoOverlay(); refreshUploadPhotoOverlay();
} }
BadgeValue( rpl::combine(
_peer BadgeValue(_peer),
) | rpl::start_with_next([=](Badge badge) { EmojiStatusIdValue(_peer)
if (badge == Badge::Premium ) | rpl::start_with_next([=](Badge badge, DocumentId emojiStatusId) {
&& !_peer->session().premiumBadgesShown()) { setBadge(badge, emojiStatusId);
badge = Badge::None;
}
setBadge(badge);
}, lifetime()); }, lifetime());
} }
@ -196,11 +202,19 @@ void Cover::refreshUploadPhotoOverlay() {
}()); }());
} }
void Cover::setBadge(Badge badge) { void Cover::setBadge(Badge badge, DocumentId emojiStatusId) {
if (_badge == badge) { if (!_peer->session().premiumBadgesShown() && badge == Badge::Premium) {
badge = Badge::None;
}
if (badge != Badge::Premium) {
emojiStatusId = 0;
}
if (_badge == badge && _emojiStatusId == emojiStatusId) {
return; return;
} }
_badge = badge; _badge = badge;
_emojiStatusId = emojiStatusId;
_emojiStatus = nullptr;
_verifiedCheck.destroy(); _verifiedCheck.destroy();
_scamFakeBadge.destroy(); _scamFakeBadge.destroy();
switch (_badge) { switch (_badge) {
@ -212,17 +226,41 @@ void Cover::setBadge(Badge badge) {
_verifiedCheck.create(this); _verifiedCheck.create(this);
_verifiedCheck->show(); _verifiedCheck->show();
_verifiedCheck->resize(icon->size()); _verifiedCheck->resize(icon->size());
if (_emojiStatusId) {
auto &owner = _controller->session().data();
_emojiStatus = owner.customEmojiManager().create(
_emojiStatusId,
[raw = _verifiedCheck.data()]{ raw->update(); },
Data::CustomEmojiManager::SizeTag::Normal);
}
_verifiedCheck->paintRequest( _verifiedCheck->paintRequest(
) | rpl::start_with_next([icon, check = _verifiedCheck.data()] { ) | rpl::start_with_next([=, check = _verifiedCheck.data()] {
Painter p(check); Painter p(check);
icon->paint(p, 0, 0, check->width()); if (_emojiStatus) {
_emojiStatus->paint(
p,
0,
0,
crl::now(),
st::windowBgOver->c,
_controller->isGifPausedAtLeastFor(
Window::GifPauseReason::Layer));
} else {
icon->paint(p, 0, 0, check->width());
}
}, _verifiedCheck->lifetime()); }, _verifiedCheck->lifetime());
if (_badge == Badge::Premium) { if (_badge == Badge::Premium) {
const auto userId = peerToUser(_peer->id).bare; const auto userId = peerToUser(_peer->id).bare;
_verifiedCheck->setClickedCallback([=] { _verifiedCheck->setClickedCallback([=] {
::Settings::ShowPremium( if (_peer->isSelf()) {
_controller, showEmojiStatusSelector();
u"profile__%1"_q.arg(userId)); } else {
::Settings::ShowPremium(
_controller,
u"profile__%1"_q.arg(userId));
}
}); });
} else { } else {
_verifiedCheck->setAttribute(Qt::WA_TransparentForMouseEvents); _verifiedCheck->setAttribute(Qt::WA_TransparentForMouseEvents);
@ -253,6 +291,49 @@ void Cover::setBadge(Badge badge) {
refreshNameGeometry(width()); refreshNameGeometry(width());
} }
void Cover::showEmojiStatusSelector() {
Expects(_verifiedCheck != nullptr);
if (!_emojiStatusPanel) {
createEmojiStatusSelector();
}
const auto parent = _emojiStatusPanel->parentWidget();
const auto global = _verifiedCheck->mapToGlobal({ 0, 0 });
const auto local = parent->mapFromGlobal(global);
_emojiStatusPanel->moveBottomRight(
local.y(),
local.x() + _verifiedCheck->width() * 3);
_emojiStatusPanel->toggleAnimated();
}
void Cover::createEmojiStatusSelector() {
const auto container = _controller->window().widget()->bodyWidget();
using Selector = ChatHelpers::TabbedSelector;
_emojiStatusPanel = base::make_unique_q<ChatHelpers::TabbedPanel>(
container,
_controller,
object_ptr<Selector>(
nullptr,
_controller,
Window::GifPauseReason::Layer,
ChatHelpers::TabbedSelector::Mode::EmojiOnly));
_emojiStatusPanel->setDesiredHeightValues(
1.,
st::emojiPanMinHeight / 2,
st::emojiPanMinHeight);
_emojiStatusPanel->hide();
_emojiStatusPanel->selector()->setAllowEmojiWithoutPremium(false);
_emojiStatusPanel->selector()->customEmojiChosen(
) | rpl::start_with_next([=](Selector::FileChosen data) {
_controller->session().user()->setEmojiStatus(data.document->id);
_controller->session().api().request(MTPaccount_UpdateEmojiStatus(
MTP_emojiStatus(MTP_long(data.document->id))
)).send();
_emojiStatusPanel->hideAnimated();
}, _emojiStatusPanel->lifetime());
_emojiStatusPanel->selector()->showPromoForPremiumEmoji();
}
void Cover::refreshStatusText() { void Cover::refreshStatusText() {
auto hasMembersLink = [&] { auto hasMembersLink = [&] {
if (auto megagroup = _peer->asMegagroup()) { if (auto megagroup = _peer->asMegagroup()) {

View file

@ -19,6 +19,10 @@ namespace style {
struct InfoToggle; struct InfoToggle;
} // namespace style } // namespace style
namespace ChatHelpers {
class TabbedPanel;
} // namespace ChatHelpers
namespace Ui { namespace Ui {
class AbstractButton; class AbstractButton;
class UserpicButton; class UserpicButton;
@ -64,10 +68,15 @@ private:
void refreshNameGeometry(int newWidth); void refreshNameGeometry(int newWidth);
void refreshStatusGeometry(int newWidth); void refreshStatusGeometry(int newWidth);
void refreshUploadPhotoOverlay(); void refreshUploadPhotoOverlay();
void setBadge(Badge badge); void setBadge(Badge badge, DocumentId emojiStatusId);
void createEmojiStatusSelector();
void showEmojiStatusSelector();
const not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;
const not_null<PeerData*> _peer; const not_null<PeerData*> _peer;
DocumentId _emojiStatusId = 0;
std::unique_ptr<Ui::Text::CustomEmoji> _emojiStatus;
base::unique_qptr<ChatHelpers::TabbedPanel> _emojiStatusPanel;
int _onlineCount = 0; int _onlineCount = 0;
Badge _badge = Badge(); Badge _badge = Badge();

View file

@ -500,5 +500,16 @@ rpl::producer<Badge> BadgeValue(not_null<PeerData*> peer) {
return rpl::single(Badge::None); return rpl::single(Badge::None);
} }
rpl::producer<DocumentId> EmojiStatusIdValue(not_null<PeerData*> peer) {
if (const auto user = peer->asUser()) {
return user->session().changes().peerFlagsValue(
peer,
Data::PeerUpdate::Flag::EmojiStatus
) | rpl::map([=] { return user->emojiStatusId(); });
}
return rpl::single(DocumentId(0));
}
} // namespace Profile } // namespace Profile
} // namespace Info } // namespace Info

View file

@ -98,6 +98,8 @@ enum class Badge {
Fake, Fake,
}; };
[[nodiscard]] rpl::producer<Badge> BadgeValue(not_null<PeerData*> peer); [[nodiscard]] rpl::producer<Badge> BadgeValue(not_null<PeerData*> peer);
[[nodiscard]] rpl::producer<DocumentId> EmojiStatusIdValue(
not_null<PeerData*> peer);
} // namespace Profile } // namespace Profile
} // namespace Info } // namespace Info

View file

@ -764,8 +764,6 @@ void MainMenu::paintEvent(QPaintEvent *e) {
- st::mainMenuCoverNameLeft - st::mainMenuCoverNameLeft
- _toggleAccounts->rightSkip(); - _toggleAccounts->rightSkip();
p.setFont(st::semiboldFont);
p.setPen(st::windowBoldFg);
const auto user = _controller->session().user(); const auto user = _controller->session().user();
if (_nameVersion < user->nameVersion()) { if (_nameVersion < user->nameVersion()) {
_nameVersion = user->nameVersion(); _nameVersion = user->nameVersion();
@ -774,11 +772,37 @@ void MainMenu::paintEvent(QPaintEvent *e) {
user->name(), user->name(),
Ui::NameTextOptions()); Ui::NameTextOptions());
} }
const auto paused = _controller->isGifPausedAtLeastFor(
GifPauseReason::Layer);
const auto badgeWidth = user->emojiStatusId()
? _badge.drawGetWidth(
p,
QRect(
st::mainMenuCoverNameLeft,
st::mainMenuCoverNameTop,
widthText,
st::msgNameStyle.font->height),
_name.maxWidth(),
width(),
{
.peer = user,
.verified = nullptr,
.premium = &st::dialogsPremiumIcon,
.scam = nullptr,
.preview = st::windowBgOver->c,
.customEmojiRepaint = [=] { update(); },
.now = crl::now(),
.paused = paused,
})
: 0;
p.setFont(st::semiboldFont);
p.setPen(st::windowBoldFg);
_name.drawLeftElided( _name.drawLeftElided(
p, p,
st::mainMenuCoverNameLeft, st::mainMenuCoverNameLeft,
st::mainMenuCoverNameTop, st::mainMenuCoverNameTop,
widthText, widthText - badgeWidth,
width()); width());
p.setFont(st::mainMenuPhoneFont); p.setFont(st::mainMenuPhoneFont);
p.setPen(st::windowSubTextFg); p.setPen(st::windowSubTextFg);

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/object_ptr.h" #include "base/object_ptr.h"
#include "base/binary_guard.h" #include "base/binary_guard.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/unread_badge.h"
#include "ui/layers/layer_widget.h" #include "ui/layers/layer_widget.h"
namespace Ui { namespace Ui {
@ -66,6 +67,7 @@ private:
const not_null<SessionController*> _controller; const not_null<SessionController*> _controller;
object_ptr<Ui::UserpicButton> _userpicButton; object_ptr<Ui::UserpicButton> _userpicButton;
Ui::PeerBadge _badge;
Ui::Text::String _name; Ui::Text::String _name;
int _nameVersion = 0; int _nameVersion = 0;
object_ptr<ToggleAccountsButton> _toggleAccounts; object_ptr<ToggleAccountsButton> _toggleAccounts;