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);
}
void PeerPhoto::requestProfileEmojiList() {
_api.request(MTPaccount_GetDefaultProfilePhotoEmojis(
)).done([=](const MTPEmojiList &result) {
void PeerPhoto::requestEmojiList(EmojiListType type) {
if (_requestIdEmojiList) {
return;
}
const auto isGroup = (type == EmojiListType::Group);
const auto d = [=](const MTPEmojiList &result) {
_requestIdEmojiList = 0;
result.match([](const MTPDemojiListNotModified &data) {
}, [&](const MTPDemojiList &data) {
_profileEmojiList = ranges::views::all(
auto &list = isGroup ? _profileEmojiList : _groupEmojiList;
list = ranges::views::all(
data.vdocument_id().v
) | 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 {
return _profileEmojiList;
rpl::producer<PeerPhoto::EmojiList> PeerPhoto::emojiListValue(
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.

View File

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

View File

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

View File

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

View File

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

View File

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