Added initial implementation of masks panel.

This commit is contained in:
23rd 2021-03-25 14:05:33 +03:00
parent d9a29b6f15
commit 1cdb83462e
15 changed files with 394 additions and 102 deletions

View File

@ -61,10 +61,14 @@ int32 CountStickersHash(
: 0;
}
int32 CountRecentStickersHash(not_null<Main::Session*> session) {
int32 CountRecentStickersHash(
not_null<Main::Session*> session,
bool attached) {
return CountSpecialStickerSetHash(
session,
Data::Stickers::CloudRecentSetId);
attached
? Data::Stickers::CloudRecentAttachedSetId
: Data::Stickers::CloudRecentSetId);
}
int32 CountFavedStickersHash(not_null<Main::Session*> session) {

View File

@ -17,7 +17,8 @@ namespace Api {
not_null<Main::Session*> session,
bool checkOutdatedInfo = false);
[[nodiscard]] int32 CountRecentStickersHash(
not_null<Main::Session*> session);
not_null<Main::Session*> session,
bool attached = false);
[[nodiscard]] int32 CountFavedStickersHash(not_null<Main::Session*> session);
[[nodiscard]] int32 CountFeaturedStickersHash(
not_null<Main::Session*> session);

View File

@ -1857,9 +1857,14 @@ void ApiWrap::requestStickerSets() {
if (i.value().second) continue;
auto waitMs = (j == e) ? 0 : kSmallDelayMs;
i.value().second = request(MTPmessages_GetStickerSet(MTP_inputStickerSetID(MTP_long(i.key()), MTP_long(i.value().first)))).done([this, setId = i.key()](const MTPmessages_StickerSet &result) {
const auto id = MTP_inputStickerSetID(
MTP_long(i.key()),
MTP_long(i.value().first));
i.value().second = request(MTPmessages_GetStickerSet(
id
)).done([=, setId = i.key()](const MTPmessages_StickerSet &result) {
gotStickerSet(setId, result);
}).fail([this, setId = i.key()](const MTP::Error &error) {
}).fail([=, setId = i.key()](const MTP::Error &error) {
_stickerSetRequests.remove(setId);
}).afterDelay(waitMs).send();
}
@ -1873,17 +1878,27 @@ void ApiWrap::saveStickerSets(
}
request(base::take(_stickersReorderRequestId)).cancel();
request(base::take(_stickersClearRecentRequestId)).cancel();
request(base::take(_stickersClearRecentAttachedRequestId)).cancel();
auto writeInstalled = true, writeRecent = false, writeCloudRecent = false, writeFaved = false, writeArchived = false;
auto writeInstalled = true,
writeRecent = false,
writeCloudRecent = false,
writeCloudRecentAttached = false,
writeFaved = false,
writeArchived = false;
auto &recent = _session->data().stickers().getRecentPack();
auto &sets = _session->data().stickers().setsRef();
_stickersOrder = localOrder;
for (const auto removedSetId : localRemoved) {
if (removedSetId == Data::Stickers::CloudRecentSetId) {
if ((removedSetId == Data::Stickers::CloudRecentSetId)
|| (removedSetId == Data::Stickers::CloudRecentAttachedSetId)) {
if (sets.remove(Data::Stickers::CloudRecentSetId) != 0) {
writeCloudRecent = true;
}
if (sets.remove(Data::Stickers::CloudRecentAttachedSetId) != 0) {
writeCloudRecentAttached = true;
}
if (sets.remove(Data::Stickers::CustomSetId)) {
writeInstalled = true;
}
@ -1892,12 +1907,25 @@ void ApiWrap::saveStickerSets(
writeRecent = true;
}
_stickersClearRecentRequestId = request(MTPmessages_ClearRecentStickers(
MTP_flags(0)
)).done([this](const MTPBool &result) {
_stickersClearRecentRequestId = 0;
}).fail([this](const MTP::Error &error) {
_stickersClearRecentRequestId = 0;
const auto isAttached =
(removedSetId == Data::Stickers::CloudRecentAttachedSetId);
const auto flags = isAttached
? MTPmessages_ClearRecentStickers::Flag::f_attached
: MTPmessages_ClearRecentStickers::Flags(0);
auto &requestId = isAttached
? _stickersClearRecentAttachedRequestId
: _stickersClearRecentRequestId;
const auto finish = [=] {
(isAttached
? _stickersClearRecentAttachedRequestId
: _stickersClearRecentRequestId) = 0;
};
requestId = request(MTPmessages_ClearRecentStickers(
MTP_flags(flags)
)).done([=](const MTPBool &result) {
finish();
}).fail([=](const MTP::Error &error) {
finish();
}).send();
continue;
}
@ -1994,11 +2022,24 @@ void ApiWrap::saveStickerSets(
}
auto &storage = local();
if (writeInstalled) storage.writeInstalledStickers();
if (writeRecent) session().saveSettings();
if (writeArchived) storage.writeArchivedStickers();
if (writeCloudRecent) storage.writeRecentStickers();
if (writeFaved) storage.writeFavedStickers();
if (writeInstalled) {
storage.writeInstalledStickers();
}
if (writeRecent) {
session().saveSettings();
}
if (writeArchived) {
storage.writeArchivedStickers();
}
if (writeCloudRecent) {
storage.writeRecentStickers();
}
if (writeCloudRecentAttached) {
storage.writeRecentMasks();
}
if (writeFaved) {
storage.writeFavedStickers();
}
_session->data().stickers().notifyUpdated();
if (_stickerSetDisenableRequests.empty()) {
@ -2825,12 +2866,24 @@ void ApiWrap::refreshFileReference(
}, [&](Data::FileOriginPeerPhoto data) {
fail();
}, [&](Data::FileOriginStickerSet data) {
const auto isRecentAttached =
(data.setId == Data::Stickers::CloudRecentAttachedSetId);
if (data.setId == Data::Stickers::CloudRecentSetId
|| data.setId == Data::Stickers::RecentSetId) {
|| data.setId == Data::Stickers::RecentSetId
|| isRecentAttached) {
auto done = [=] { crl::on_main(_session, [=] {
if (isRecentAttached) {
local().writeRecentMasks();
} else {
local().writeRecentStickers();
}
}); };
request(MTPmessages_GetRecentStickers(
MTP_flags(0),
MTP_flags(isRecentAttached
? MTPmessages_GetRecentStickers::Flag::f_attached
: MTPmessages_GetRecentStickers::Flags(0)),
MTP_int(0)),
[=] { crl::on_main(_session, [=] { local().writeRecentStickers(); }); });
std::move(done));
} else if (data.setId == Data::Stickers::FavedSetId) {
request(MTPmessages_GetFavedStickers(MTP_int(0)),
[=] { crl::on_main(_session, [=] { local().writeFavedStickers(); }); });
@ -2909,7 +2962,7 @@ void ApiWrap::stickersSaveOrder() {
}
void ApiWrap::updateStickers() {
auto now = crl::now();
const auto now = crl::now();
requestStickers(now);
requestRecentStickers(now);
requestFavedStickers(now);
@ -2917,8 +2970,14 @@ void ApiWrap::updateStickers() {
requestSavedGifs(now);
}
void ApiWrap::requestRecentStickersForce() {
requestRecentStickersWithHash(0);
void ApiWrap::updateMasks() {
const auto now = crl::now();
requestStickers(now, true);
requestRecentStickers(now, true);
}
void ApiWrap::requestRecentStickersForce(bool attached) {
requestRecentStickersWithHash(0, attached);
}
void ApiWrap::setGroupStickerSet(not_null<ChannelData*> megagroup, const MTPInputStickerSet &set) {
@ -2977,17 +3036,29 @@ std::vector<not_null<DocumentData*>> *ApiWrap::stickersByEmoji(
return nullptr;
}
void ApiWrap::requestStickers(TimeId now) {
if (!_session->data().stickers().updateNeeded(now)
|| _stickersUpdateRequest) {
void ApiWrap::requestStickers(TimeId now, bool masks) {
const auto requestId = [=]() -> mtpRequestId & {
return masks
? _masksUpdateRequest
: _stickersUpdateRequest;
};
const auto needed = masks
? _session->data().stickers().masksUpdateNeeded(now)
: _session->data().stickers().updateNeeded(now);
if (!needed || requestId()) {
return;
}
auto onDone = [this](const MTPmessages_AllStickers &result) {
_session->data().stickers().setLastUpdate(crl::now());
_stickersUpdateRequest = 0;
const auto onDone = [=](const MTPmessages_AllStickers &result) {
if (masks) {
_session->data().stickers().setLastMasksUpdate(crl::now());
} else {
_session->data().stickers().setLastUpdate(crl::now());
}
requestId() = 0;
switch (result.type()) {
case mtpc_messages_allStickersNotModified: return;
case mtpc_messages_getMaskStickers:
case mtpc_messages_allStickers: {
auto &d = result.c_messages_allStickers();
_session->data().stickers().setsReceived(
@ -2997,39 +3068,67 @@ void ApiWrap::requestStickers(TimeId now) {
default: Unexpected("Type in ApiWrap::stickersDone()");
}
};
_stickersUpdateRequest = request(MTPmessages_GetAllStickers(
MTP_int(Api::CountStickersHash(_session, true))
)).done(onDone).fail([=](const MTP::Error &error) {
LOG(("App Fail: Failed to get stickers!"));
const auto onFail = [=](const MTP::Error &error) {
LOG(("App Fail: Failed to get %1!"
).arg(masks ? "masks" : "stickers"));
onDone(MTP_messages_allStickersNotModified());
}).send();
};
auto hash = MTP_int(Api::CountStickersHash(_session, true));
requestId() = masks
? request(MTPmessages_GetMaskStickers(
std::move(hash))
).done(onDone).fail(onFail).send()
: request(MTPmessages_GetAllStickers(
std::move(hash))
).done(onDone).fail(onFail).send();
}
void ApiWrap::requestRecentStickers(TimeId now) {
if (!_session->data().stickers().recentUpdateNeeded(now)) {
void ApiWrap::requestRecentStickers(TimeId now, bool attached) {
const auto needed = attached
? _session->data().stickers().recentAttachedUpdateNeeded(now)
: _session->data().stickers().recentUpdateNeeded(now);
if (!needed) {
return;
}
requestRecentStickersWithHash(
Api::CountRecentStickersHash(_session));
Api::CountRecentStickersHash(_session, attached), attached);
}
void ApiWrap::requestRecentStickersWithHash(int32 hash) {
if (_recentStickersUpdateRequest) {
void ApiWrap::requestRecentStickersWithHash(int32 hash, bool attached) {
const auto requestId = [=]() -> mtpRequestId & {
return attached
? _recentAttachedStickersUpdateRequest
: _recentStickersUpdateRequest;
};
if (requestId()) {
return;
}
_recentStickersUpdateRequest = request(MTPmessages_GetRecentStickers(
MTP_flags(0),
const auto finish = [=] {
auto &stickers = _session->data().stickers();
if (attached) {
stickers.setLastRecentAttachedUpdate(crl::now());
} else {
stickers.setLastRecentUpdate(crl::now());
}
requestId() = 0;
};
const auto flags = attached
? MTPmessages_getRecentStickers::Flag::f_attached
: MTPmessages_getRecentStickers::Flags(0);
requestId() = request(MTPmessages_GetRecentStickers(
MTP_flags(flags),
MTP_int(hash)
)).done([=](const MTPmessages_RecentStickers &result) {
_session->data().stickers().setLastRecentUpdate(crl::now());
_recentStickersUpdateRequest = 0;
finish();
switch (result.type()) {
case mtpc_messages_recentStickersNotModified: return;
case mtpc_messages_recentStickers: {
auto &d = result.c_messages_recentStickers();
_session->data().stickers().specialSetReceived(
Data::Stickers::CloudRecentSetId,
attached
? Data::Stickers::CloudRecentAttachedSetId
: Data::Stickers::CloudRecentSetId,
tr::lng_recent_stickers(tr::now),
d.vstickers().v,
d.vhash().v,
@ -3039,8 +3138,7 @@ void ApiWrap::requestRecentStickersWithHash(int32 hash) {
default: Unexpected("Type in ApiWrap::recentStickersDone()");
}
}).fail([=](const MTP::Error &error) {
_session->data().stickers().setLastRecentUpdate(crl::now());
_recentStickersUpdateRequest = 0;
finish();
LOG(("App Fail: Failed to get recent stickers!"));
}).send();

View File

@ -282,7 +282,8 @@ public:
const Data::StickersSetsOrder &localOrder,
const Data::StickersSetsOrder &localRemoved);
void updateStickers();
void requestRecentStickersForce();
void updateMasks();
void requestRecentStickersForce(bool attached = false);
void setGroupStickerSet(
not_null<ChannelData*> megagroup,
const MTPInputStickerSet &set);
@ -547,9 +548,9 @@ private:
void stickerSetDisenabled(mtpRequestId requestId);
void stickersSaveOrder();
void requestStickers(TimeId now);
void requestRecentStickers(TimeId now);
void requestRecentStickersWithHash(int32 hash);
void requestStickers(TimeId now, bool masks = false);
void requestRecentStickers(TimeId now, bool attached = false);
void requestRecentStickersWithHash(int32 hash, bool attached = false);
void requestFavedStickers(TimeId now);
void requestFeaturedStickers(TimeId now);
void requestSavedGifs(TimeId now);
@ -690,9 +691,12 @@ private:
Data::StickersSetsOrder _stickersOrder;
mtpRequestId _stickersReorderRequestId = 0;
mtpRequestId _stickersClearRecentRequestId = 0;
mtpRequestId _stickersClearRecentAttachedRequestId = 0;
mtpRequestId _stickersUpdateRequest = 0;
mtpRequestId _masksUpdateRequest = 0;
mtpRequestId _recentStickersUpdateRequest = 0;
mtpRequestId _recentAttachedStickersUpdateRequest = 0;
mtpRequestId _favedStickersUpdateRequest = 0;
mtpRequestId _featuredStickersUpdateRequest = 0;
mtpRequestId _savedGifsUpdateRequest = 0;

View File

@ -896,10 +896,12 @@ bool StickersListWidget::Footer::iconsAnimationCallback(crl::time now) {
StickersListWidget::StickersListWidget(
QWidget *parent,
not_null<Window::SessionController*> controller)
not_null<Window::SessionController*> controller,
bool masks)
: Inner(parent, controller)
, _api(&controller->session().mtp())
, _section(Section::Stickers)
, _isMasks(masks)
, _pathGradient(std::make_unique<Ui::PathShiftGradient>(
st::windowBgRipple,
st::windowBgOver,
@ -935,7 +937,11 @@ StickersListWidget::StickersListWidget(
}, lifetime());
session().data().stickers().recentUpdated(
) | rpl::start_with_next([=] {
) | rpl::start_with_next([=](Data::Stickers::Recent recent) {
const auto attached = (recent == Data::Stickers::Recent::Attached);
if (attached != _isMasks) {
return;
}
refreshRecent();
}, lifetime());
}
@ -2377,12 +2383,12 @@ void StickersListWidget::refreshStickers() {
void StickersListWidget::refreshMySets() {
auto wasSets = base::take(_mySets);
_favedStickersMap.clear();
_mySets.reserve(session().data().stickers().setsOrder().size() + 3);
_mySets.reserve(defaultSetsOrder().size() + 3);
refreshFavedStickers();
refreshRecentStickers(false);
refreshMegagroupStickers(GroupStickersPlace::Visible);
for (const auto setId : session().data().stickers().setsOrder()) {
for (const auto setId : defaultSetsOrder()) {
const auto externalLayout = false;
appendSet(_mySets, setId, externalLayout, AppendSkip::Archived);
}
@ -2455,7 +2461,9 @@ void StickersListWidget::refreshSearchIndex() {
}
void StickersListWidget::refreshSettingsVisibility() {
const auto visible = (_section == Section::Stickers) && _mySets.empty();
const auto visible = (_section == Section::Stickers)
&& _mySets.empty()
&& !_isMasks;
_settings->setVisible(visible);
}
@ -2533,9 +2541,15 @@ auto StickersListWidget::collectRecentStickers() -> std::vector<Sticker> {
auto result = std::vector<Sticker>();
const auto &sets = session().data().stickers().sets();
const auto &recent = session().data().stickers().getRecentPack();
const auto customIt = sets.find(Data::Stickers::CustomSetId);
const auto cloudIt = sets.find(Data::Stickers::CloudRecentSetId);
const auto &recent = _isMasks
? RecentStickerPack()
: session().data().stickers().getRecentPack();
const auto customIt = _isMasks
? sets.cend()
: sets.find(Data::Stickers::CustomSetId);
const auto cloudIt = sets.find(_isMasks
? Data::Stickers::CloudRecentAttachedSetId
: Data::Stickers::CloudRecentSetId);
const auto customCount = (customIt != sets.cend())
? customIt->second->stickers.size()
: 0;
@ -2621,6 +2635,9 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
}
void StickersListWidget::refreshFavedStickers() {
if (_isMasks) {
return;
}
clearSelection();
const auto &sets = session().data().stickers().sets();
const auto it = sets.find(Data::Stickers::FavedSetId);
@ -2648,7 +2665,7 @@ void StickersListWidget::refreshFavedStickers() {
}
void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
if (!_megagroupSet) {
if (!_megagroupSet || _isMasks) {
return;
}
auto canEdit = _megagroupSet->canEditStickers();
@ -2851,7 +2868,8 @@ bool StickersListWidget::setHasTitle(const Set &set) const {
if (set.id == Data::Stickers::FavedSetId) {
return false;
} else if (set.id == Data::Stickers::RecentSetId) {
return !_mySets.empty() && _mySets[0].id == Data::Stickers::FavedSetId;
return !_mySets.empty()
&& (_isMasks || (_mySets[0].id == Data::Stickers::FavedSetId));
}
return true;
}
@ -3149,8 +3167,10 @@ void StickersListWidget::removeSet(uint64 setId) {
// && !(set->flags & MTPDstickerSet_ClientFlag::f_special)) {
// sets.erase(it);
//}
int removeIndex = session().data().stickers().setsOrder().indexOf(_removingSetId);
if (removeIndex >= 0) session().data().stickers().setsOrderRef().removeAt(removeIndex);
int removeIndex = defaultSetsOrder().indexOf(_removingSetId);
if (removeIndex >= 0) {
defaultSetsOrderRef().removeAt(removeIndex);
}
refreshStickers();
session().local().writeInstalledStickers();
if (writeRecent) session().saveSettings();
@ -3164,6 +3184,18 @@ void StickersListWidget::removeSet(uint64 setId) {
}
}
const Data::StickersSetsOrder &StickersListWidget::defaultSetsOrder() const {
return !_isMasks
? session().data().stickers().setsOrder()
: session().data().stickers().maskSetsOrder();
}
Data::StickersSetsOrder &StickersListWidget::defaultSetsOrderRef() {
return !_isMasks
? session().data().stickers().setsOrderRef()
: session().data().stickers().maskSetsOrderRef();
}
StickersListWidget::~StickersListWidget() = default;
} // namespace ChatHelpers

View File

@ -49,7 +49,8 @@ class StickersListWidget
public:
StickersListWidget(
QWidget *parent,
not_null<Window::SessionController*> controller);
not_null<Window::SessionController*> controller,
bool masks = false);
Main::Session &session() const;
@ -300,6 +301,9 @@ private:
void refreshMegagroupSetGeometry();
QRect megagroupSetButtonRectFinal() const;
const Data::StickersSetsOrder &defaultSetsOrder() const;
Data::StickersSetsOrder &defaultSetsOrderRef();
enum class AppendSkip {
None,
Archived,
@ -349,6 +353,7 @@ private:
int _officialOffset = 0;
Section _section = Section::Stickers;
const bool _isMasks;
bool _displayingSet = false;
uint64 _removingSetId = 0;

View File

@ -423,7 +423,7 @@ TabbedSelector::Tab TabbedSelector::createTab(SelectorTab type, int index) {
case SelectorTab::Gifs:
return object_ptr<GifsListWidget>(this, _controller);
case SelectorTab::Masks:
return object_ptr<StickersListWidget>(this, _controller);
return object_ptr<StickersListWidget>(this, _controller, true);
}
Unexpected("Type in TabbedSelector::createTab.");
};
@ -673,12 +673,17 @@ int TabbedSelector::marginBottom() const {
}
void TabbedSelector::refreshStickers() {
if (!hasStickersTab()) {
return;
if (hasStickersTab()) {
stickers()->refreshStickers();
if (isHidden() || _currentTabType != SelectorTab::Stickers) {
stickers()->preloadImages();
}
}
stickers()->refreshStickers();
if (isHidden() || _currentTabType != SelectorTab::Stickers) {
stickers()->preloadImages();
if (hasMasksTab()) {
masks()->refreshStickers();
if (isHidden() || _currentTabType != SelectorTab::Masks) {
masks()->preloadImages();
}
}
}
@ -738,6 +743,9 @@ void TabbedSelector::showStarted() {
if (hasStickersTab()) {
session().api().updateStickers();
}
if (hasMasksTab()) {
session().api().updateMasks();
}
currentTab()->widget()->refreshRecent();
currentTab()->widget()->preloadImages();
_a_slide.stop();

View File

@ -86,11 +86,11 @@ rpl::producer<> Stickers::updated() const {
return _updated.events();
}
void Stickers::notifyRecentUpdated() {
_recentUpdated.fire({});
void Stickers::notifyRecentUpdated(Recent recent) {
_recentUpdated.fire(std::move(recent));
}
rpl::producer<> Stickers::recentUpdated() const {
rpl::producer<Stickers::Recent> Stickers::recentUpdated() const {
return _recentUpdated.events();
}
@ -102,6 +102,7 @@ rpl::producer<> Stickers::savedGifsUpdated() const {
return _savedGifsUpdated.events();
}
// Increment attached sticker.
void Stickers::incrementSticker(not_null<DocumentData*> document) {
if (!document->sticker()
|| document->sticker()->set.type() == mtpc_inputStickerSetEmpty) {
@ -573,26 +574,41 @@ void Stickers::setFaved(not_null<DocumentData*> document, bool faved) {
}
void Stickers::setsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
auto &setsOrder = setsOrderRef();
const auto masksReceived = ranges::all_of(
data,
[](const MTPStickerSet &set) {
return set.c_stickerSet().is_masks();
});
auto &setsOrder = masksReceived
? maskSetsOrderRef()
: setsOrderRef();
setsOrder.clear();
using Flag = MTPDstickerSet::Flag;
using ClientFlag = MTPDstickerSet_ClientFlag;
auto &sets = setsRef();
QMap<uint64, uint64> setsToRequest;
for (auto &[id, set] : sets) {
if (!(set->flags & MTPDstickerSet::Flag::f_archived)) {
const auto archived = !!(set->flags & Flag::f_archived);
const auto masks = !!(set->flags & MTPDstickerSet::Flag::f_masks);
if (!archived && (masksReceived == masks)) {
// Mark for removing.
set->flags &= ~MTPDstickerSet::Flag::f_installed_date;
set->flags &= ~Flag::f_installed_date;
set->installDate = 0;
}
}
for (const auto &setData : data) {
if (setData.type() == mtpc_stickerSet) {
auto set = feedSet(setData.c_stickerSet());
if (!(set->flags & MTPDstickerSet::Flag::f_archived) || (set->flags & MTPDstickerSet::Flag::f_official)) {
setsOrder.push_back(set->id);
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
setsToRequest.insert(set->id, set->access);
}
if (setData.type() != mtpc_stickerSet) {
continue;
}
const auto set = feedSet(setData.c_stickerSet());
if (!(set->flags & Flag::f_archived)
|| (set->flags & Flag::f_official)) {
setsOrder.push_back(set->id);
if (set->stickers.isEmpty()
|| (set->flags & ClientFlag::f_not_loaded)) {
setsToRequest.insert(set->id, set->access);
}
}
}
@ -600,10 +616,10 @@ void Stickers::setsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
auto &recent = getRecentPack();
for (auto it = sets.begin(); it != sets.end();) {
const auto set = it->second.get();
bool installed = (set->flags & MTPDstickerSet::Flag::f_installed_date);
bool featured = (set->flags & MTPDstickerSet_ClientFlag::f_featured);
bool special = (set->flags & MTPDstickerSet_ClientFlag::f_special);
bool archived = (set->flags & MTPDstickerSet::Flag::f_archived);
const auto installed = !!(set->flags & Flag::f_installed_date);
const auto featured = !!(set->flags & ClientFlag::f_featured);
const auto special = !!(set->flags & ClientFlag::f_special);
const auto archived = !!(set->flags & Flag::f_archived);
if (!installed) { // remove not mine sets from recent stickers
for (auto i = recent.begin(); i != recent.cend();) {
if (set->stickers.indexOf(i->first) >= 0) {
@ -629,8 +645,14 @@ void Stickers::setsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
api.requestStickerSets();
}
session().local().writeInstalledStickers();
if (writeRecent) session().saveSettings();
if (masksReceived) {
session().local().writeInstalledMasks();
} else {
session().local().writeInstalledStickers();
}
if (writeRecent) {
session().saveSettings();
}
const auto counted = Api::CountStickersHash(&session());
if (counted != hash) {
@ -705,7 +727,8 @@ void Stickers::specialSetReceived(
auto dates = std::vector<TimeId>();
auto dateIndex = 0;
auto datesAvailable = (items.size() == usageDates.size())
&& (setId == CloudRecentSetId);
&& ((setId == CloudRecentSetId)
|| (setId == CloudRecentAttachedSetId));
auto customIt = sets.find(CustomSetId);
auto pack = StickersPack();
@ -768,6 +791,16 @@ void Stickers::specialSetReceived(
}
session().local().writeRecentStickers();
} break;
case CloudRecentAttachedSetId: {
const auto counted = Api::CountRecentStickersHash(&session(), true);
if (counted != hash) {
LOG(("API Error: "
"received recent attached stickers hash %1 "
"while counted hash is %2"
).arg(hash, counted));
}
session().local().writeRecentMasks();
} break;
case FavedSetId: {
const auto counted = Api::CountFavedStickersHash(&session());
if (counted != hash) {
@ -1263,9 +1296,16 @@ StickersSet *Stickers::feedSetFull(const MTPmessages_StickerSet &data) {
}
}
const auto isMasks = !!(set->flags & MTPDstickerSet::Flag::f_masks);
if (pack.isEmpty()) {
int removeIndex = setsOrder().indexOf(set->id);
if (removeIndex >= 0) setsOrderRef().removeAt(removeIndex);
const auto removeIndex = (isMasks
? maskSetsOrder()
: setsOrder()).indexOf(set->id);
if (removeIndex >= 0) {
(isMasks
? maskSetsOrderRef()
: setsOrderRef()).removeAt(removeIndex);
}
sets.remove(set->id);
set = nullptr;
} else {
@ -1299,7 +1339,9 @@ StickersSet *Stickers::feedSetFull(const MTPmessages_StickerSet &data) {
if (set) {
const auto isArchived = !!(set->flags & MTPDstickerSet::Flag::f_archived);
if (set->flags & MTPDstickerSet::Flag::f_installed_date) {
if (isMasks) {
session().local().writeInstalledMasks();
} else if (set->flags & MTPDstickerSet::Flag::f_installed_date) {
if (!isArchived) {
session().local().writeInstalledStickers();
}

View File

@ -41,6 +41,7 @@ public:
// For cloud-stored recent stickers.
static constexpr auto CloudRecentSetId = 0xFFFFFFFFFFFFFFFCULL;
static constexpr auto CloudRecentAttachedSetId = 0xFFFFFFFFFFFFFFF9ULL;
// For cloud-stored faved stickers.
static constexpr auto FavedSetId = 0xFFFFFFFFFFFFFFFAULL;
@ -48,10 +49,15 @@ public:
// For setting up megagroup sticker set.
static constexpr auto MegagroupSetId = 0xFFFFFFFFFFFFFFEFULL;
enum Recent {
Regular,
Attached,
};
void notifyUpdated();
[[nodiscard]] rpl::producer<> updated() const;
void notifyRecentUpdated();
[[nodiscard]] rpl::producer<> recentUpdated() const;
void notifyRecentUpdated(Recent recent = Recent::Regular);
[[nodiscard]] rpl::producer<Recent> recentUpdated() const;
void notifySavedGifsUpdated();
[[nodiscard]] rpl::producer<> savedGifsUpdated() const;
@ -72,6 +78,21 @@ public:
}
_lastRecentUpdate = update;
}
bool masksUpdateNeeded(crl::time now) const {
return updateNeeded(_lastMasksUpdate, now);
}
void setLastMasksUpdate(crl::time update) {
_lastMasksUpdate = update;
}
bool recentAttachedUpdateNeeded(crl::time now) const {
return updateNeeded(_lastRecentAttachedUpdate, now);
}
void setLastRecentAttachedUpdate(crl::time update) {
if (update) {
notifyRecentUpdated(Recent::Attached);
}
_lastRecentAttachedUpdate = update;
}
bool favedUpdateNeeded(crl::time now) const {
return updateNeeded(_lastFavedUpdate, now);
}
@ -111,6 +132,12 @@ public:
StickersSetsOrder &setsOrderRef() {
return _setsOrder;
}
const StickersSetsOrder &maskSetsOrder() const {
return _maskSetsOrder;
}
StickersSetsOrder &maskSetsOrderRef() {
return _maskSetsOrder;
}
const StickersSetsOrder &featuredSetsOrder() const {
return _featuredSetsOrder;
}
@ -196,16 +223,19 @@ private:
const not_null<Session*> _owner;
rpl::event_stream<> _updated;
rpl::event_stream<> _recentUpdated;
rpl::event_stream<Recent> _recentUpdated;
rpl::event_stream<> _savedGifsUpdated;
crl::time _lastUpdate = 0;
crl::time _lastRecentUpdate = 0;
crl::time _lastFavedUpdate = 0;
crl::time _lastFeaturedUpdate = 0;
crl::time _lastSavedGifsUpdate = 0;
crl::time _lastMasksUpdate = 0;
crl::time _lastRecentAttachedUpdate = 0;
rpl::variable<int> _featuredSetsUnreadCount = 0;
StickersSets _sets;
StickersSetsOrder _setsOrder;
StickersSetsOrder _maskSetsOrder;
StickersSetsOrder _featuredSetsOrder;
StickersSetsOrder _archivedSetsOrder;
SavedGifs _savedGifs;

View File

@ -23,7 +23,7 @@ StickersPanelController::StickersPanelController(
object_ptr<ChatHelpers::TabbedSelector>(
nullptr,
controller,
ChatHelpers::TabbedSelector::Mode::Full))) {
ChatHelpers::TabbedSelector::Mode::MediaEditor))) {
_stickersPanel->setDesiredHeightValues(
1.,
st::emojiPanMinHeight / 2,

View File

@ -134,8 +134,10 @@ Session::Session(
// Storage::Account uses Main::Account::session() in those methods.
// So they can't be called during Main::Session construction.
local().readInstalledStickers();
local().readInstalledMasks();
local().readFeaturedStickers();
local().readRecentStickers();
local().readRecentMasks();
local().readFavedStickers();
local().readSavedGifs();
data().stickers().notifyUpdated();

View File

@ -566,7 +566,10 @@ void AppendEmojiPacks(
rpl::merge(
rpl::merge(
_session->data().stickers().updated(),
_session->data().stickers().recentUpdated()
_session->data().stickers().recentUpdated(
) | rpl::filter([](Data::Stickers::Recent recent) {
return (recent != Data::Stickers::Recent::Attached);
}) | rpl::to_empty
) | rpl::map_to(ScrubberItemType::Sticker),
rpl::merge(
Core::App().settings().recentEmojiUpdated(),

View File

@ -101,6 +101,7 @@ DocumentData *Document::readFromStreamHelper(
} else if (info) {
if (info->setId == Data::Stickers::DefaultSetId
|| info->setId == Data::Stickers::CloudRecentSetId
|| info->setId == Data::Stickers::CloudRecentAttachedSetId
|| info->setId == Data::Stickers::FavedSetId
|| info->setId == Data::Stickers::CustomSetId) {
typeOfSet = StickerSetTypeEmpty;

View File

@ -76,6 +76,7 @@ enum { // Local Storage Keys
lskExportSettings = 0x13, // no data
lskBackgroundOld = 0x14, // no data
lskSelfSerialized = 0x15, // serialized self
lskMasksKeys = 0x16, // no data
};
[[nodiscard]] FileKey ComputeDataNameKey(const QString &dataName) {
@ -184,6 +185,8 @@ base::flat_set<QString> Account::collectGoodNames() const {
_recentHashtagsAndBotsKey,
_exportSettingsKey,
_trustedBotsKey,
_installedMasksKey,
_recentMasksKey,
};
auto result = base::flat_set<QString>{
"map0",
@ -264,6 +267,7 @@ Account::ReadMapResult Account::readMapWith(
quint64 locationsKey = 0, reportSpamStatusesKey = 0, trustedBotsKey = 0;
quint64 recentStickersKeyOld = 0;
quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, favedStickersKey = 0, archivedStickersKey = 0;
quint64 installedMasksKey = 0, recentMasksKey = 0;
quint64 savedGifsKey = 0;
quint64 legacyBackgroundKeyDay = 0, legacyBackgroundKeyNight = 0;
quint64 userSettingsKey = 0, recentHashtagsAndBotsKey = 0, exportSettingsKey = 0;
@ -360,6 +364,9 @@ Account::ReadMapResult Account::readMapWith(
case lskExportSettings: {
map.stream >> exportSettingsKey;
} break;
case lskMasksKeys: {
map.stream >> installedMasksKey >> recentMasksKey;
} break;
default:
LOG(("App Error: unknown key type in encrypted map: %1").arg(keyType));
return ReadMapResult::Failed;
@ -384,6 +391,8 @@ Account::ReadMapResult Account::readMapWith(
_favedStickersKey = favedStickersKey;
_archivedStickersKey = archivedStickersKey;
_savedGifsKey = savedGifsKey;
_installedMasksKey = installedMasksKey;
_recentMasksKey = recentMasksKey;
_legacyBackgroundKeyDay = legacyBackgroundKeyDay;
_legacyBackgroundKeyNight = legacyBackgroundKeyNight;
_settingsKey = userSettingsKey;
@ -488,6 +497,9 @@ void Account::writeMap() {
if (_settingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_recentHashtagsAndBotsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_exportSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_installedMasksKey || _recentMasksKey) {
mapSize += sizeof(quint32) + 2 * sizeof(quint64);
}
EncryptedDescriptor mapData(mapSize);
if (!self.isEmpty()) {
@ -533,6 +545,12 @@ void Account::writeMap() {
if (_exportSettingsKey) {
mapData.stream << quint32(lskExportSettings) << quint64(_exportSettingsKey);
}
if (_installedMasksKey || _recentMasksKey) {
mapData.stream << quint32(lskMasksKeys);
mapData.stream
<< quint64(_installedMasksKey)
<< quint64(_recentMasksKey);
}
map.writeEncrypted(mapData, _localKey);
_mapChanged = false;
@ -551,6 +569,8 @@ void Account::reset() {
_favedStickersKey = 0;
_archivedStickersKey = 0;
_savedGifsKey = 0;
_installedMasksKey = 0;
_recentMasksKey = 0;
_legacyBackgroundKeyDay = _legacyBackgroundKeyNight = 0;
_settingsKey = _recentHashtagsAndBotsKey = _exportSettingsKey = 0;
_oldMapVersion = 0;
@ -1694,7 +1714,8 @@ void Account::readStickerSets(
} else if (setId == Data::Stickers::CustomSetId) {
setTitle = qsl("Custom stickers");
setFlags |= MTPDstickerSet_ClientFlag::f_special;
} else if (setId == Data::Stickers::CloudRecentSetId) {
} else if ((setId == Data::Stickers::CloudRecentSetId)
|| (setId == Data::Stickers::CloudRecentAttachedSetId)) {
setTitle = tr::lng_recent_stickers(tr::now);
setFlags |= MTPDstickerSet_ClientFlag::f_special;
} else if (setId == Data::Stickers::FavedSetId) {
@ -1769,7 +1790,9 @@ void Account::readStickerSets(
if (datesCount != scnt) {
return failed();
}
const auto fillDates = (set->id == Data::Stickers::CloudRecentSetId)
const auto fillDates =
((set->id == Data::Stickers::CloudRecentSetId)
|| (set->id == Data::Stickers::CloudRecentAttachedSetId))
&& (set->stickers.size() == datesCount);
if (fillDates) {
set->dates.clear();
@ -1852,7 +1875,9 @@ void Account::readStickerSets(
void Account::writeInstalledStickers() {
writeStickerSets(_installedStickersKey, [](const Data::StickersSet &set) {
if (set.id == Data::Stickers::CloudRecentSetId || set.id == Data::Stickers::FavedSetId) { // separate files for them
if (set.id == Data::Stickers::CloudRecentSetId
|| set.id == Data::Stickers::FavedSetId
|| set.id == Data::Stickers::CloudRecentAttachedSetId) { // separate files for them
return StickerSetCheckResult::Skip;
} else if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
if (set.stickers.isEmpty()) { // all other special are "installed"
@ -1872,7 +1897,8 @@ void Account::writeInstalledStickers() {
void Account::writeFeaturedStickers() {
writeStickerSets(_featuredStickersKey, [](const Data::StickersSet &set) {
if (set.id == Data::Stickers::CloudRecentSetId
|| set.id == Data::Stickers::FavedSetId) { // separate files for them
|| set.id == Data::Stickers::FavedSetId
|| set.id == Data::Stickers::CloudRecentAttachedSetId) { // separate files for them
return StickerSetCheckResult::Skip;
} else if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
return StickerSetCheckResult::Skip;
@ -1914,6 +1940,25 @@ void Account::writeArchivedStickers() {
}, _owner->session().data().stickers().archivedSetsOrder());
}
void Account::writeInstalledMasks() {
writeStickerSets(_installedMasksKey, [](const Data::StickersSet &set) {
if (!(set.flags & MTPDstickerSet::Flag::f_masks) || set.stickers.isEmpty()) {
return StickerSetCheckResult::Skip;
}
return StickerSetCheckResult::Write;
}, _owner->session().data().stickers().maskSetsOrder());
}
void Account::writeRecentMasks() {
writeStickerSets(_recentMasksKey, [](const Data::StickersSet &set) {
if (set.id != Data::Stickers::CloudRecentAttachedSetId
|| set.stickers.isEmpty()) {
return StickerSetCheckResult::Skip;
}
return StickerSetCheckResult::Write;
}, Data::StickersSetsOrder());
}
void Account::importOldRecentStickers() {
if (!_recentStickersKeyOld) {
return;
@ -2069,6 +2114,10 @@ void Account::readRecentStickers() {
readStickerSets(_recentStickersKey);
}
void Account::readRecentMasks() {
readStickerSets(_recentMasksKey);
}
void Account::readFavedStickers() {
readStickerSets(_favedStickersKey);
}
@ -2081,6 +2130,13 @@ void Account::readArchivedStickers() {
}
}
void Account::readInstalledMasks() {
readStickerSets(
_installedMasksKey,
&_owner->session().data().stickers().maskSetsOrderRef(),
MTPDstickerSet::Flag::f_installed_date);
}
void Account::writeSavedGifs() {
auto &saved = _owner->session().data().stickers().savedGifs();
if (saved.isEmpty()) {

View File

@ -118,6 +118,10 @@ public:
void readArchivedStickers();
void writeSavedGifs();
void readSavedGifs();
void writeInstalledMasks();
void writeRecentMasks();
void readInstalledMasks();
void readRecentMasks();
void writeRecentHashtagsAndBots();
void readRecentHashtagsAndBots();
@ -255,6 +259,8 @@ private:
FileKey _settingsKey = 0;
FileKey _recentHashtagsAndBotsKey = 0;
FileKey _exportSettingsKey = 0;
FileKey _installedMasksKey = 0;
FileKey _recentMasksKey = 0;
qint64 _cacheTotalSizeLimit = 0;
qint64 _cacheBigFileTotalSizeLimit = 0;