Added api support of default list of group emoji for userpic builder.

This commit is contained in:
23rd 2023-01-30 17:59:40 +03:00 committed by John Preston
parent 5ba7b3906c
commit 0578fb421f
7 changed files with 79 additions and 41 deletions

View File

@ -427,20 +427,40 @@ void PeerPhoto::requestUserPhotos(
_userPhotosRequests.emplace(user, requestId); _userPhotosRequests.emplace(user, requestId);
} }
void PeerPhoto::requestProfileEmojiList() { void PeerPhoto::requestEmojiList(EmojiListType type) {
_api.request(MTPaccount_GetDefaultProfilePhotoEmojis( if (_requestIdEmojiList) {
)).done([=](const MTPEmojiList &result) { return;
}
const auto isGroup = (type == EmojiListType::Group);
const auto d = [=](const MTPEmojiList &result) {
_requestIdEmojiList = 0;
result.match([](const MTPDemojiListNotModified &data) { result.match([](const MTPDemojiListNotModified &data) {
}, [&](const MTPDemojiList &data) { }, [&](const MTPDemojiList &data) {
_profileEmojiList = ranges::views::all( auto &list = isGroup ? _profileEmojiList : _groupEmojiList;
list = ranges::views::all(
data.vdocument_id().v data.vdocument_id().v
) | ranges::views::transform(&MTPlong::v) | ranges::to_vector; ) | ranges::views::transform(&MTPlong::v) | ranges::to_vector;
}); });
}).send(); };
const auto f = [=] { _requestIdEmojiList = 0; };
_requestIdEmojiList = isGroup
? _api.request(
MTPaccount_GetDefaultGroupPhotoEmojis()
).done(d).fail(f).send()
: _api.request(
MTPaccount_GetDefaultProfilePhotoEmojis()
).done(d).fail(f).send();
} }
std::vector<DocumentId> PeerPhoto::profileEmojiList() const { rpl::producer<PeerPhoto::EmojiList> PeerPhoto::emojiListValue(
return _profileEmojiList; EmojiListType type) {
auto &list = (type == EmojiListType::Group)
? _profileEmojiList
: _groupEmojiList;
if (list.current().empty() && !_requestIdEmojiList) {
requestEmojiList(type);
}
return list.value();
} }
// Non-personal photo in case a personal photo is set. // Non-personal photo in case a personal photo is set.

View File

@ -28,6 +28,11 @@ public:
using UserPhotoId = PhotoId; using UserPhotoId = PhotoId;
explicit PeerPhoto(not_null<ApiWrap*> api); explicit PeerPhoto(not_null<ApiWrap*> api);
enum class EmojiListType {
Profile,
Group,
};
void upload( void upload(
not_null<PeerData*> peer, not_null<PeerData*> peer,
QImage &&image, QImage &&image,
@ -44,8 +49,9 @@ public:
void requestUserPhotos(not_null<UserData*> user, UserPhotoId afterId); void requestUserPhotos(not_null<UserData*> user, UserPhotoId afterId);
void requestProfileEmojiList(); void requestEmojiList(EmojiListType type);
[[nodiscard]] std::vector<DocumentId> profileEmojiList() const; using EmojiList = std::vector<DocumentId>;
[[nodiscard]] rpl::producer<EmojiList> emojiListValue(EmojiListType type);
// Non-personal photo in case a personal photo is set. // Non-personal photo in case a personal photo is set.
void registerNonPersonalPhoto( void registerNonPersonalPhoto(
@ -86,7 +92,9 @@ private:
not_null<UserData*>, not_null<UserData*>,
not_null<PhotoData*>> _nonPersonalPhotos; not_null<PhotoData*>> _nonPersonalPhotos;
std::vector<DocumentId> _profileEmojiList; mtpRequestId _requestIdEmojiList = 0;
rpl::variable<EmojiList> _profileEmojiList;
rpl::variable<EmojiList> _groupEmojiList;
}; };

View File

@ -17,6 +17,7 @@ namespace UserpicBuilder {
struct StartData { struct StartData {
DocumentId documentId = DocumentId(0); DocumentId documentId = DocumentId(0);
int builderColorIndex = 0; int builderColorIndex = 0;
rpl::producer<std::vector<DocumentId>> documents;
std::vector<QColor> gradientEditorColors; std::vector<QColor> gradientEditorColors;
}; };

View File

@ -30,15 +30,19 @@ namespace UserpicBuilder {
void AddEmojiBuilderAction( void AddEmojiBuilderAction(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::PopupMenu*> menu, not_null<Ui::PopupMenu*> menu,
std::vector<DocumentId> documents, rpl::producer<std::vector<DocumentId>> documents,
Fn<void(QImage &&image)> &&done) { Fn<void(QImage &&image)> &&done) {
{
auto rd = std::random_device();
ranges::shuffle(documents, std::mt19937(rd()));
}
struct State final { struct State final {
void next() {
documentIndex = documentIndex.current() + 1;
if (documentIndex.current() >= shuffledDocuments.size()) {
documentIndex = 0;
}
colorIndex = base::RandomIndex(std::numeric_limits<int>::max());
}
rpl::variable<int> documentIndex; rpl::variable<int> documentIndex;
rpl::variable<int> colorIndex; rpl::variable<int> colorIndex;
std::vector<DocumentId> shuffledDocuments;
base::Timer timer; base::Timer timer;
}; };
@ -49,28 +53,28 @@ void AddEmojiBuilderAction(
Ui::Menu::CreateAction( Ui::Menu::CreateAction(
menu.get(), menu.get(),
tr::lng_attach_profile_emoji(tr::now), tr::lng_attach_profile_emoji(tr::now),
[=, done = std::move(done)] { [=, done = std::move(done), docs = rpl::duplicate(documents)] {
const auto index = state->documentIndex.current(); const auto index = state->documentIndex.current();
const auto id = index < documents.size() const auto id = index < state->shuffledDocuments.size()
? documents[index] ? state->shuffledDocuments[index]
: 0; : 0;
UserpicBuilder::ShowLayer( UserpicBuilder::ShowLayer(
controller, controller,
{ id, state->colorIndex.current() }, { id, state->colorIndex.current(), docs },
base::duplicate(done)); base::duplicate(done));
}), }),
nullptr, nullptr,
nullptr); nullptr);
const auto timerCallback = [=] { rpl::duplicate(
state->documentIndex = state->documentIndex.current() + 1; documents
if (state->documentIndex.current() >= documents.size()) { ) | rpl::start_with_next([=](std::vector<DocumentId> documents) {
state->shuffledDocuments = std::move(documents);
auto rd = std::random_device();
ranges::shuffle(state->shuffledDocuments, std::mt19937(rd()));
state->documentIndex = 0; state->documentIndex = 0;
} }, item->lifetime());
state->colorIndex = base::RandomIndex( state->next();
std::numeric_limits<int>::max()); state->timer.setCallback([=] { state->next(); });
};
timerCallback();
state->timer.setCallback(timerCallback);
constexpr auto kTimeout = crl::time(1500); constexpr auto kTimeout = crl::time(1500);
state->timer.callEach(kTimeout); state->timer.callEach(kTimeout);
const auto icon = UserpicBuilder::CreateEmojiUserpic( const auto icon = UserpicBuilder::CreateEmojiUserpic(
@ -78,9 +82,10 @@ void AddEmojiBuilderAction(
st::restoreUserpicIcon.size, st::restoreUserpicIcon.size,
state->documentIndex.value( state->documentIndex.value(
) | rpl::filter([=](int index) { ) | rpl::filter([=](int index) {
return index < documents.size(); return index < state->shuffledDocuments.size();
}) | rpl::map([=](int index) { }) | rpl::map([=](int index) {
return controller->session().data().document(documents[index]); return controller->session().data().document(
state->shuffledDocuments[index]);
}), }),
state->colorIndex.value()); state->colorIndex.value());
icon->setAttribute(Qt::WA_TransparentForMouseEvents); icon->setAttribute(Qt::WA_TransparentForMouseEvents);

View File

@ -20,7 +20,7 @@ namespace UserpicBuilder {
void AddEmojiBuilderAction( void AddEmojiBuilderAction(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::PopupMenu*> menu, not_null<Ui::PopupMenu*> menu,
std::vector<DocumentId> documents, rpl::producer<std::vector<DocumentId>> documents,
Fn<void(QImage &&image)> &&done); Fn<void(QImage &&image)> &&done);
} // namespace UserpicBuilder } // namespace UserpicBuilder

View File

@ -141,7 +141,8 @@ class EmojiSelector final : public Ui::RpWidget {
public: public:
EmojiSelector( EmojiSelector(
not_null<Ui::RpWidget*> parent, not_null<Ui::RpWidget*> parent,
not_null<Window::SessionController*> controller); not_null<Window::SessionController*> controller,
rpl::producer<std::vector<DocumentId>> recent);
[[nodiscard]] rpl::producer<not_null<DocumentData*>> chosen() const; [[nodiscard]] rpl::producer<not_null<DocumentData*>> chosen() const;
@ -163,15 +164,18 @@ private:
const not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;
base::unique_qptr<Ui::RpWidget> _container; base::unique_qptr<Ui::RpWidget> _container;
rpl::variable<std::vector<DocumentId>> _recent;
rpl::event_stream<not_null<DocumentData*>> _chosen; rpl::event_stream<not_null<DocumentData*>> _chosen;
}; };
EmojiSelector::EmojiSelector( EmojiSelector::EmojiSelector(
not_null<Ui::RpWidget*> parent, not_null<Ui::RpWidget*> parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller,
rpl::producer<std::vector<DocumentId>> recent)
: RpWidget(parent) : RpWidget(parent)
, _controller(controller) { , _controller(controller)
, _recent(std::move(recent)) {
createSelector(Type::Emoji); createSelector(Type::Emoji);
} }
@ -189,7 +193,7 @@ EmojiSelector::Selector EmojiSelector::createEmojiList(
.mode = ChatHelpers::EmojiListMode::UserpicBuilder, .mode = ChatHelpers::EmojiListMode::UserpicBuilder,
.controller = _controller, .controller = _controller,
.paused = [=] { return true; }, .paused = [=] { return true; },
.customRecentList = session->api().peerPhoto().profileEmojiList(), .customRecentList = _recent.current(),
.customRecentFactory = [=](DocumentId id, Fn<void()> repaint) { .customRecentFactory = [=](DocumentId id, Fn<void()> repaint) {
return manager->create(id, std::move(repaint), tag); return manager->create(id, std::move(repaint), tag);
}, },
@ -471,7 +475,8 @@ not_null<Ui::VerticalLayout*> CreateUserpicBuilder(
[=] { return controller->chatStyle(); }); [=] { return controller->chatStyle(); });
const auto selector = Ui::CreateChild<EmojiSelector>( const auto selector = Ui::CreateChild<EmojiSelector>(
selectorBg.get(), selectorBg.get(),
controller); controller,
base::take(data.documents));
selector->chosen( selector->chosen(
) | rpl::start_with_next([=](not_null<DocumentData*> document) { ) | rpl::start_with_next([=](not_null<DocumentData*> document) {
state->gradientEditorStartData.documentId = document->id; state->gradientEditorStartData.documentId = document->id;

View File

@ -219,9 +219,6 @@ void UserpicButton::prepare() {
: _peer : _peer
? &_peer->session().api() ? &_peer->session().api()
: nullptr; : nullptr;
if (api) {
api->peerPhoto().requestProfileEmojiList();
}
} }
} }
@ -358,7 +355,9 @@ void UserpicButton::choosePhotoLocally() {
UserpicBuilder::AddEmojiBuilderAction( UserpicBuilder::AddEmojiBuilderAction(
_controller, _controller,
_menu, _menu,
session.api().peerPhoto().profileEmojiList(), session.api().peerPhoto().emojiListValue(user
? Api::PeerPhoto::EmojiListType::Profile
: Api::PeerPhoto::EmojiListType::Group),
callback(ChosenType::Set)); callback(ChosenType::Set));
} }
} else { } else {