Show cloud stickers by emoji.

This commit is contained in:
John Preston 2018-03-07 16:53:12 +03:00
parent c3ff5f2603
commit f0a95032a5
5 changed files with 120 additions and 40 deletions

View file

@ -59,6 +59,7 @@ constexpr auto kFeedMessagesLimit = 50;
constexpr auto kReadFeaturedSetsTimeout = TimeMs(1000);
constexpr auto kFileLoaderQueueStopTimeout = TimeMs(5000);
constexpr auto kFeedReadTimeout = TimeMs(1000);
constexpr auto kStickersByEmojiInvalidateTimeout = TimeMs(60 * 60 * 1000);
bool IsSilentPost(not_null<HistoryItem*> item, bool silent) {
const auto history = item->history();
@ -2199,11 +2200,60 @@ void ApiWrap::updateStickers() {
void ApiWrap::setGroupStickerSet(not_null<ChannelData*> megagroup, const MTPInputStickerSet &set) {
Expects(megagroup->mgInfo != nullptr);
megagroup->mgInfo->stickerSet = set;
request(MTPchannels_SetStickers(megagroup->inputChannel, set)).send();
_session->data().notifyStickersUpdated();
}
std::vector<not_null<DocumentData*>> *ApiWrap::stickersByEmoji(
not_null<EmojiPtr> emoji) {
const auto it = _stickersByEmoji.find(emoji);
const auto sendRequest = [&] {
if (it == _stickersByEmoji.end()) {
return true;
}
const auto received = it->second.received;
const auto now = getms(true);
return (received > 0)
&& (received + kStickersByEmojiInvalidateTimeout) <= now;
}();
if (sendRequest) {
const auto hash = (it != _stickersByEmoji.end())
? it->second.hash
: QString();
request(MTPmessages_GetStickers(
MTP_flags(MTPmessages_GetStickers::Flag::f_exclude_featured),
MTP_string(emoji->text()),
MTP_string(hash)
)).done([=](const MTPmessages_Stickers &result) {
if (result.type() == mtpc_messages_stickersNotModified) {
return;
}
Assert(result.type() == mtpc_messages_stickers);
const auto &data = result.c_messages_stickers();
auto &entry = _stickersByEmoji[emoji];
entry.list.clear();
entry.list.reserve(data.vstickers.v.size());
for (const auto &sticker : data.vstickers.v) {
const auto document = Auth().data().document(sticker);
if (document->sticker()) {
entry.list.push_back(document);
}
}
entry.hash = qs(data.vhash);
entry.received = getms(true);
_session->data().notifyStickersUpdated();
}).send();
}
if (it == _stickersByEmoji.end()) {
_stickersByEmoji.emplace(emoji, StickersByEmoji());
} else if (it->second.received > 0) {
return &it->second.list;
}
return nullptr;
}
void ApiWrap::requestStickers(TimeId now) {
if (!_session->data().stickersUpdateNeeded(now)
|| _stickersUpdateRequest) {

View file

@ -129,6 +129,8 @@ public:
void setGroupStickerSet(
not_null<ChannelData*> megagroup,
const MTPInputStickerSet &set);
std::vector<not_null<DocumentData*>> *stickersByEmoji(
not_null<EmojiPtr> emoji);
void joinChannel(ChannelData *channel);
void leaveChannel(ChannelData *channel);
@ -279,6 +281,12 @@ private:
using MessageDataRequests = QMap<MsgId, MessageDataRequest>;
using SharedMediaType = Storage::SharedMediaType;
struct StickersByEmoji {
std::vector<not_null<DocumentData*>> list;
QString hash;
TimeMs received = 0;
};
void updatesReceived(const MTPUpdates &updates);
void checkQuitPreventFinished();
@ -489,6 +497,8 @@ private:
base::Timer _featuredSetsReadTimer;
base::flat_set<uint64> _featuredSetsRead;
base::flat_map<not_null<EmojiPtr>, StickersByEmoji> _stickersByEmoji;
base::flat_map<mtpTypeId, mtpRequestId> _privacySaveRequests;
mtpRequestId _contactsRequestId = 0;

View file

@ -324,6 +324,7 @@ void FieldAutocomplete::rowsUpdated(const internal::MentionRows &mrows, const in
if (!isHidden()) {
hideAnimated();
}
_scroll->scrollToY(0);
_mrows.clear();
_hrows.clear();
_brows.clear();

View file

@ -670,33 +670,52 @@ Pack GetListByEmoji(not_null<EmojiPtr> emoji) {
result = faved;
}
}
auto &order = Auth().data().stickerSetsOrder();
for (auto i = 0, l = order.size(); i != l; ++i) {
auto it = sets.find(order[i]);
if (it != sets.cend()) {
const auto addList = [&](const Order &order, MTPDstickerSet::Flag skip) {
for (const auto setId : order) {
auto it = sets.find(setId);
if (it == sets.cend() || (it->flags & skip)) {
continue;
}
if (it->emoji.isEmpty()) {
setsToRequest.insert(it->id, it->access);
it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded;
} else if (!(it->flags & MTPDstickerSet::Flag::f_archived)) {
auto i = it->emoji.constFind(original);
if (i != it->emoji.cend()) {
result.reserve(result.size() + i->size());
for_const (auto sticker, *i) {
if (!faved.contains(sticker)) {
result.push_back(sticker);
}
}
continue;
}
auto i = it->emoji.constFind(original);
if (i == it->emoji.cend()) {
continue;
}
result.reserve(result.size() + i->size());
for_const (const auto document, *i) {
if (!faved.contains(document)) {
result.push_back(document);
}
}
}
}
};
addList(
Auth().data().stickerSetsOrder(),
MTPDstickerSet::Flag::f_archived);
addList(
Auth().data().featuredStickerSetsOrder(),
MTPDstickerSet::Flag::f_installed_date);
if (!setsToRequest.isEmpty()) {
for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
Auth().api().scheduleStickerSetRequest(i.key(), i.value());
}
Auth().api().requestStickerSets();
}
return result;
if (const auto pack = Auth().api().stickersByEmoji(original)) {
for (const auto document : *pack) {
if (!base::contains(result, document)) {
result.push_back(document);
}
}
return result;
}
return Pack();
}
base::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(

View file

@ -43,13 +43,13 @@ public:
return *_session;
}
base::Variable<bool> &contactsLoaded() {
[[nodiscard]] base::Variable<bool> &contactsLoaded() {
return _contactsLoaded;
}
base::Variable<bool> &allChatsLoaded() {
[[nodiscard]] base::Variable<bool> &allChatsLoaded() {
return _allChatsLoaded;
}
base::Observable<void> &moreChatsLoaded() {
[[nodiscard]] base::Observable<void> &moreChatsLoaded() {
return _moreChatsLoaded;
}
@ -57,7 +57,7 @@ public:
not_null<HistoryItem*> item;
not_null<bool*> isVisible;
};
base::Observable<ItemVisibilityQuery> &queryItemVisibility() {
[[nodiscard]] base::Observable<ItemVisibilityQuery> &queryItemVisibility() {
return _queryItemVisibility;
}
struct IdChange {
@ -65,32 +65,32 @@ public:
MsgId oldId = 0;
};
void notifyItemIdChange(IdChange event);
rpl::producer<IdChange> itemIdChanged() const;
[[nodiscard]] rpl::producer<IdChange> itemIdChanged() const;
void notifyItemLayoutChange(not_null<const HistoryItem*> item);
rpl::producer<not_null<const HistoryItem*>> itemLayoutChanged() const;
[[nodiscard]] rpl::producer<not_null<const HistoryItem*>> itemLayoutChanged() const;
void notifyViewLayoutChange(not_null<const ViewElement*> view);
rpl::producer<not_null<const ViewElement*>> viewLayoutChanged() const;
[[nodiscard]] rpl::producer<not_null<const ViewElement*>> viewLayoutChanged() const;
void requestItemRepaint(not_null<const HistoryItem*> item);
rpl::producer<not_null<const HistoryItem*>> itemRepaintRequest() const;
[[nodiscard]] rpl::producer<not_null<const HistoryItem*>> itemRepaintRequest() const;
void requestViewRepaint(not_null<const ViewElement*> view);
rpl::producer<not_null<const ViewElement*>> viewRepaintRequest() const;
[[nodiscard]] rpl::producer<not_null<const ViewElement*>> viewRepaintRequest() const;
void requestItemResize(not_null<const HistoryItem*> item);
rpl::producer<not_null<const HistoryItem*>> itemResizeRequest() const;
[[nodiscard]] rpl::producer<not_null<const HistoryItem*>> itemResizeRequest() const;
void requestViewResize(not_null<ViewElement*> view);
rpl::producer<not_null<ViewElement*>> viewResizeRequest() const;
[[nodiscard]] rpl::producer<not_null<ViewElement*>> viewResizeRequest() const;
void requestItemViewRefresh(not_null<HistoryItem*> item);
rpl::producer<not_null<HistoryItem*>> itemViewRefreshRequest() const;
[[nodiscard]] rpl::producer<not_null<HistoryItem*>> itemViewRefreshRequest() const;
void requestAnimationPlayInline(not_null<HistoryItem*> item);
rpl::producer<not_null<HistoryItem*>> animationPlayInlineRequest() const;
[[nodiscard]] rpl::producer<not_null<HistoryItem*>> animationPlayInlineRequest() const;
void notifyHistoryUnloaded(not_null<const History*> history);
rpl::producer<not_null<const History*>> historyUnloaded() const;
[[nodiscard]] rpl::producer<not_null<const History*>> historyUnloaded() const;
void notifyItemRemoved(not_null<const HistoryItem*> item);
rpl::producer<not_null<const HistoryItem*>> itemRemoved() const;
[[nodiscard]] rpl::producer<not_null<const HistoryItem*>> itemRemoved() const;
void notifyHistoryCleared(not_null<const History*> history);
rpl::producer<not_null<const History*>> historyCleared() const;
[[nodiscard]] rpl::producer<not_null<const History*>> historyCleared() const;
void notifyHistoryChangeDelayed(not_null<History*> history);
rpl::producer<not_null<History*>> historyChanged() const;
[[nodiscard]] rpl::producer<not_null<History*>> historyChanged() const;
void sendHistoryChangeNotifications();
using MegagroupParticipant = std::tuple<
@ -99,23 +99,23 @@ public:
void removeMegagroupParticipant(
not_null<ChannelData*> channel,
not_null<UserData*> user);
rpl::producer<MegagroupParticipant> megagroupParticipantRemoved() const;
rpl::producer<not_null<UserData*>> megagroupParticipantRemoved(
[[nodiscard]] rpl::producer<MegagroupParticipant> megagroupParticipantRemoved() const;
[[nodiscard]] rpl::producer<not_null<UserData*>> megagroupParticipantRemoved(
not_null<ChannelData*> channel) const;
void addNewMegagroupParticipant(
not_null<ChannelData*> channel,
not_null<UserData*> user);
rpl::producer<MegagroupParticipant> megagroupParticipantAdded() const;
rpl::producer<not_null<UserData*>> megagroupParticipantAdded(
[[nodiscard]] rpl::producer<MegagroupParticipant> megagroupParticipantAdded() const;
[[nodiscard]] rpl::producer<not_null<UserData*>> megagroupParticipantAdded(
not_null<ChannelData*> channel) const;
void notifyFeedUpdated(not_null<Feed*> feed, FeedUpdateFlag update);
rpl::producer<FeedUpdate> feedUpdated() const;
[[nodiscard]] rpl::producer<FeedUpdate> feedUpdated() const;
void notifyStickersUpdated();
rpl::producer<> stickersUpdated() const;
[[nodiscard]] rpl::producer<> stickersUpdated() const;
void notifySavedGifsUpdated();
rpl::producer<> savedGifsUpdated() const;
[[nodiscard]] rpl::producer<> savedGifsUpdated() const;
bool stickersUpdateNeeded(TimeMs now) const {
return stickersUpdateNeeded(_lastStickersUpdate, now);
@ -153,7 +153,7 @@ public:
void setFeaturedStickerSetsUnreadCount(int count) {
_featuredStickerSetsUnreadCount = count;
}
rpl::producer<int> featuredStickerSetsUnreadCountValue() const {
[[nodiscard]] rpl::producer<int> featuredStickerSetsUnreadCountValue() const {
return _featuredStickerSetsUnreadCount.value();
}
const Stickers::Sets &stickerSets() const {