Added api support of default list of group emoji for userpic builder.
This commit is contained in:
parent
5ba7b3906c
commit
0578fb421f
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue