mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-31 06:26:18 +00:00
Allow editing tag names in Saved Messages.
This commit is contained in:
@@ -356,6 +356,15 @@ const std::vector<MyTagInfo> &Reactions::myTagsInfo() const {
|
||||
return _myTagsInfo;
|
||||
}
|
||||
|
||||
const QString &Reactions::myTagTitle(const ReactionId &id) const {
|
||||
const auto i = ranges::find(_myTagsInfo, id, &::Data::MyTagInfo::id);
|
||||
if (i != end(_myTagsInfo)) {
|
||||
return i->title;
|
||||
}
|
||||
static const auto kEmpty = QString();
|
||||
return kEmpty;
|
||||
}
|
||||
|
||||
ReactionId Reactions::favoriteId() const {
|
||||
return _favoriteId;
|
||||
}
|
||||
@@ -415,6 +424,23 @@ void Reactions::decrementMyTag(const ReactionId &id) {
|
||||
scheduleMyTagsUpdate();
|
||||
}
|
||||
|
||||
void Reactions::renameTag(const ReactionId &id, const QString &name) {
|
||||
auto i = ranges::find(_myTagsInfo, id, &MyTagInfo::id);
|
||||
if (i == end(_myTagsInfo) || i->title == name) {
|
||||
return;
|
||||
}
|
||||
i->title = name;
|
||||
scheduleMyTagsUpdate();
|
||||
_myTagRenamed.fire_copy(id);
|
||||
|
||||
using Flag = MTPmessages_UpdateSavedReactionTag::Flag;
|
||||
_owner->session().api().request(MTPmessages_UpdateSavedReactionTag(
|
||||
MTP_flags(name.isEmpty() ? Flag(0) : Flag::f_title),
|
||||
ReactionToMTP(id),
|
||||
MTP_string(name)
|
||||
)).send();
|
||||
}
|
||||
|
||||
void Reactions::scheduleMyTagsUpdate() {
|
||||
_myTagsUpdateScheduled = true;
|
||||
crl::on_main(&session(), [=] {
|
||||
@@ -496,6 +522,10 @@ rpl::producer<> Reactions::tagsUpdates() const {
|
||||
return _tagsUpdated.events();
|
||||
}
|
||||
|
||||
rpl::producer<ReactionId> Reactions::myTagRenamed() const {
|
||||
return _myTagRenamed.events();
|
||||
}
|
||||
|
||||
void Reactions::preloadImageFor(const ReactionId &id) {
|
||||
if (_images.contains(id) || id.emoji().isEmpty()) {
|
||||
return;
|
||||
@@ -850,9 +880,21 @@ void Reactions::updateGeneric(const MTPDmessages_stickerSet &data) {
|
||||
|
||||
void Reactions::updateMyTags(const MTPDmessages_savedReactionTags &data) {
|
||||
_myTagsHash = data.vhash().v;
|
||||
_myTagsInfo = ListFromMTP(data);
|
||||
auto list = ListFromMTP(data);
|
||||
auto renamed = base::flat_set<ReactionId>();
|
||||
for (const auto &info : list) {
|
||||
const auto j = ranges::find(_myTagsInfo, info.id, &MyTagInfo::id);
|
||||
const auto was = (j != end(_myTagsInfo)) ? j->title : QString();
|
||||
if (info.title != was) {
|
||||
renamed.emplace(info.id);
|
||||
}
|
||||
}
|
||||
_myTagsInfo = std::move(list);
|
||||
_myTags = resolveByInfos(_myTagsInfo, _unresolvedMyTags);
|
||||
_myTagsUpdated.fire({});
|
||||
for (const auto &id : renamed) {
|
||||
_myTagRenamed.fire_copy(id);
|
||||
}
|
||||
}
|
||||
|
||||
void Reactions::updateTags(const MTPDmessages_reactions &data) {
|
||||
@@ -1304,6 +1346,7 @@ void MessageReactions::remove(const ReactionId &id) {
|
||||
return;
|
||||
}
|
||||
i->my = false;
|
||||
const auto tags = _item->reactionsAreTags();
|
||||
const auto removed = !--i->count;
|
||||
if (removed) {
|
||||
_list.erase(i);
|
||||
@@ -1321,6 +1364,9 @@ void MessageReactions::remove(const ReactionId &id) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tags) {
|
||||
history->owner().reactions().decrementMyTag(id);
|
||||
}
|
||||
auto &owner = history->owner();
|
||||
owner.reactions().send(_item, false);
|
||||
owner.notifyItemDataChange(_item);
|
||||
|
@@ -93,11 +93,13 @@ public:
|
||||
};
|
||||
[[nodiscard]] const std::vector<Reaction> &list(Type type) const;
|
||||
[[nodiscard]] const std::vector<MyTagInfo> &myTagsInfo() const;
|
||||
[[nodiscard]] const QString &myTagTitle(const ReactionId &id) const;
|
||||
[[nodiscard]] ReactionId favoriteId() const;
|
||||
[[nodiscard]] const Reaction *favorite() const;
|
||||
void setFavorite(const ReactionId &id);
|
||||
void incrementMyTag(const ReactionId &id);
|
||||
void decrementMyTag(const ReactionId &id);
|
||||
void renameTag(const ReactionId &id, const QString &name);
|
||||
[[nodiscard]] DocumentData *chooseGenericAnimation(
|
||||
not_null<DocumentData*> custom) const;
|
||||
|
||||
@@ -107,6 +109,7 @@ public:
|
||||
[[nodiscard]] rpl::producer<> favoriteUpdates() const;
|
||||
[[nodiscard]] rpl::producer<> myTagsUpdates() const;
|
||||
[[nodiscard]] rpl::producer<> tagsUpdates() const;
|
||||
[[nodiscard]] rpl::producer<ReactionId> myTagRenamed() const;
|
||||
|
||||
enum class ImageSize {
|
||||
BottomInfo,
|
||||
@@ -223,6 +226,7 @@ private:
|
||||
rpl::event_stream<> _favoriteUpdated;
|
||||
rpl::event_stream<> _myTagsUpdated;
|
||||
rpl::event_stream<> _tagsUpdated;
|
||||
rpl::event_stream<ReactionId> _myTagRenamed;
|
||||
|
||||
// We need &i->second stay valid while inserting new items.
|
||||
// So we use std::map instead of base::flat_map here.
|
||||
|
@@ -295,6 +295,16 @@ Session::Session(not_null<Main::Session*> session)
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
_reactions->myTagRenamed(
|
||||
) | rpl::start_with_next([=](const ReactionId &id) {
|
||||
const auto i = _viewsByTag.find(id);
|
||||
if (i != end(_viewsByTag)) {
|
||||
for (const auto &view : i->second) {
|
||||
notifyItemDataChange(view->data());
|
||||
}
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
Spellchecker::HighlightReady(
|
||||
) | rpl::start_with_next([=](uint64 processId) {
|
||||
highlightProcessDone(processId);
|
||||
@@ -4608,6 +4618,28 @@ rpl::producer<not_null<PeerData*>> Session::peerDecorationsUpdated() const {
|
||||
return _peerDecorationsUpdated.events();
|
||||
}
|
||||
|
||||
void Session::viewTagsChanged(
|
||||
not_null<ViewElement*> view,
|
||||
std::vector<Data::ReactionId> &&was,
|
||||
std::vector<Data::ReactionId> &&now) {
|
||||
for (const auto &id : now) {
|
||||
const auto i = ranges::remove(was, id);
|
||||
if (i != end(was)) {
|
||||
was.erase(i, end(was));
|
||||
} else {
|
||||
_viewsByTag[id].emplace(view);
|
||||
}
|
||||
}
|
||||
for (const auto &id : was) {
|
||||
const auto i = _viewsByTag.find(id);
|
||||
if (i != end(_viewsByTag)
|
||||
&& i->second.remove(view)
|
||||
&& i->second.empty()) {
|
||||
_viewsByTag.erase(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::clearLocalStorage() {
|
||||
_cache->close();
|
||||
_cache->clear();
|
||||
|
@@ -62,6 +62,7 @@ class NotifySettings;
|
||||
class CustomEmojiManager;
|
||||
class Stories;
|
||||
class SavedMessages;
|
||||
struct ReactionId;
|
||||
|
||||
struct RepliesReadTillUpdate {
|
||||
FullMsgId id;
|
||||
@@ -742,6 +743,11 @@ public:
|
||||
void applyStatsDcId(not_null<ChannelData*>, MTP::DcId);
|
||||
[[nodiscard]] MTP::DcId statsDcId(not_null<ChannelData*>);
|
||||
|
||||
void viewTagsChanged(
|
||||
not_null<ViewElement*> view,
|
||||
std::vector<ReactionId> &&was,
|
||||
std::vector<ReactionId> &&now);
|
||||
|
||||
void clearLocalStorage();
|
||||
|
||||
private:
|
||||
@@ -1005,9 +1011,14 @@ private:
|
||||
|
||||
base::flat_map<uint64, not_null<GroupCall*>> _groupCalls;
|
||||
rpl::event_stream<InviteToCall> _invitesToCalls;
|
||||
base::flat_map<uint64, base::flat_set<not_null<UserData*>>> _invitedToCallUsers;
|
||||
base::flat_map<
|
||||
uint64,
|
||||
base::flat_set<not_null<UserData*>>> _invitedToCallUsers;
|
||||
|
||||
base::flat_set<not_null<ViewElement*>> _shownSpoilers;
|
||||
base::flat_map<
|
||||
ReactionId,
|
||||
base::flat_set<not_null<ViewElement*>>> _viewsByTag;
|
||||
|
||||
History *_topPromoted = nullptr;
|
||||
|
||||
|
Reference in New Issue
Block a user