2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 06:35:14 +00:00

Add pinned messages section.

This commit is contained in:
John Preston
2020-10-20 19:29:24 +03:00
parent aefef948cd
commit fc92e3fadd
26 changed files with 1142 additions and 343 deletions

View File

@@ -383,7 +383,6 @@ void ChannelData::setUnavailableReasons(
void ChannelData::setAvailableMinId(MsgId availableMinId) {
if (_availableMinId != availableMinId) {
_availableMinId = availableMinId;
clearPinnedMessages(_availableMinId + 1);
}
}

View File

@@ -38,6 +38,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_element.h"
#include "history/history_item.h"
#include "storage/file_download.h"
#include "storage/storage_facade.h"
#include "storage/storage_shared_media.h"
#include "facades.h" // Ui::showPeerProfile
#include "app.h"
@@ -468,14 +470,15 @@ MsgId PeerData::topPinnedMessageId() const {
void PeerData::ensurePinnedMessagesCreated() {
if (!_pinnedMessages) {
_pinnedMessages = std::make_unique<Data::PinnedMessages>(
peerToChannel(id));
_pinnedMessages = std::make_unique<Data::PinnedMessages>(this);
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
}
}
void PeerData::removeEmptyPinnedMessages() {
if (_pinnedMessages && _pinnedMessages->empty()) {
_pinnedMessages = nullptr;
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
}
}
@@ -491,69 +494,24 @@ void PeerData::setTopPinnedMessageId(MsgId messageId) {
clearPinnedMessages();
return;
}
if (session().settings().hiddenPinnedMessageId(id) != messageId) {
const auto hiddenId = session().settings().hiddenPinnedMessageId(id);
if (hiddenId != 0 && hiddenId != messageId) {
session().settings().setHiddenPinnedMessageId(id, 0);
session().saveSettingsDelayed();
}
ensurePinnedMessagesCreated();
_pinnedMessages->setTopId(messageId);
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
}
void PeerData::clearPinnedMessages(MsgId lessThanId) {
if (lessThanId == ServerMaxMsgId
&& session().settings().hiddenPinnedMessageId(id) != 0) {
void PeerData::clearPinnedMessages() {
if (session().settings().hiddenPinnedMessageId(id) != 0) {
session().settings().setHiddenPinnedMessageId(id, 0);
session().saveSettingsDelayed();
}
if (!_pinnedMessages) {
return;
}
_pinnedMessages->clearLessThanId(lessThanId);
session().storage().remove(Storage::SharedMediaRemoveAll(
id,
Storage::SharedMediaType::Pinned));
removeEmptyPinnedMessages();
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
}
void PeerData::addPinnedMessage(MsgId messageId) {
if (messageIdTooSmall(messageId)) {
return;
}
ensurePinnedMessagesCreated();
_pinnedMessages->add(messageId);
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
}
void PeerData::addPinnedSlice(
std::vector<MsgId> &&ids,
MsgRange noSkipRange,
std::optional<int> count) {
const auto min = [&] {
if (const auto channel = asChannel()) {
return channel->availableMinId();
}
return 0;
}();
ids.erase(
ranges::remove_if(ids, [&](MsgId id) { return id <= min; }),
end(ids));
if (noSkipRange.from <= min) {
noSkipRange.from = 0;
}
if (ids.empty() && !_pinnedMessages) {
return;
}
ensurePinnedMessagesCreated();
_pinnedMessages->add(std::move(ids), noSkipRange, count);
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
}
void PeerData::removePinnedMessage(MsgId messageId) {
if (!_pinnedMessages) {
return;
}
_pinnedMessages->remove(messageId);
removeEmptyPinnedMessages();
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
}
bool PeerData::canExportChatHistory() const {

View File

@@ -330,13 +330,7 @@ public:
[[nodiscard]] bool canEditMessagesIndefinitely() const;
[[nodiscard]] MsgId topPinnedMessageId() const;
void setTopPinnedMessageId(MsgId messageId);
void clearPinnedMessages(MsgId lessThanId = ServerMaxMsgId);
void addPinnedMessage(MsgId messageId);
void addPinnedSlice(
std::vector<MsgId> &&ids,
MsgRange noSkipRange,
std::optional<int> count);
void removePinnedMessage(MsgId messageId);
void clearPinnedMessages();
Data::PinnedMessages *currentPinnedMessages() const {
return _pinnedMessages.get();
}

View File

@@ -7,94 +7,76 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "data/data_pinned_messages.h"
namespace Data {
#include "data/data_peer.h"
#include "main/main_session.h"
#include "storage/storage_facade.h"
#include "storage/storage_shared_media.h"
PinnedMessages::PinnedMessages(ChannelId channelId) : _channelId(channelId) {
namespace Data {
namespace {
constexpr auto PinnedType = Storage::SharedMediaType::Pinned;
using Storage::SharedMediaQuery;
using Storage::SharedMediaKey;
using Storage::SharedMediaResult;
} // namespace
PinnedMessages::PinnedMessages(not_null<PeerData*> peer)
: _peer(peer)
, _storage(_peer->session().storage()) {
}
bool PinnedMessages::empty() const {
return _list.empty();
return _storage.empty(SharedMediaKey(_peer->id, PinnedType, 0));
}
MsgId PinnedMessages::topId() const {
const auto slice = _list.snapshot(MessagesQuery{
.aroundId = MaxMessagePosition,
.limitBefore = 1,
.limitAfter = 1
});
return slice.messageIds.empty() ? 0 : slice.messageIds.back().fullId.msg;
const auto slice = _storage.snapshot(
SharedMediaQuery(
SharedMediaKey(_peer->id, PinnedType, ServerMaxMsgId),
1,
1));
return slice.messageIds.empty() ? 0 : slice.messageIds.back();
}
rpl::producer<PinnedAroundId> PinnedMessages::viewer(
MsgId aroundId,
int limit) const {
return _list.viewer(MessagesQuery{
.aroundId = position(aroundId),
.limitBefore = limit,
.limitAfter = limit
}) | rpl::map([](const MessagesResult &result) {
return _storage.query(
SharedMediaQuery(
SharedMediaKey(_peer->id, PinnedType, aroundId),
limit,
limit)
) | rpl::map([](const SharedMediaResult &result) {
auto data = PinnedAroundId();
data.fullCount = result.count;
data.skippedBefore = result.skippedBefore;
data.skippedAfter = result.skippedAfter;
data.ids = result.messageIds | ranges::view::transform(
[](MessagePosition position) { return position.fullId.msg; }
) | ranges::to_vector;
data.ids = result.messageIds | ranges::to_vector;
return data;
});
}
MessagePosition PinnedMessages::position(MsgId id) const {
return MessagePosition{
.fullId = FullMsgId(_channelId, id),
};
}
void PinnedMessages::add(MsgId messageId) {
_list.addOne(position(messageId));
}
void PinnedMessages::add(
std::vector<MsgId> &&ids,
MsgRange range,
std::optional<int> count) {
auto positions = ids | ranges::view::transform([&](MsgId id) {
return position(id);
}) | ranges::to_vector;
_list.addSlice(
std::move(positions),
MessagesRange{
.from = range.from ? position(range.from) : MinMessagePosition,
.till = position(range.till)
},
count);
}
void PinnedMessages::remove(MsgId messageId) {
_list.removeOne(position(messageId));
}
void PinnedMessages::setTopId(MsgId messageId) {
while (true) {
auto top = topId();
if (top > messageId) {
remove(top);
_storage.remove(Storage::SharedMediaRemoveOne(
_peer->id,
PinnedType,
top));
} else if (top == messageId) {
return;
} else {
break;
}
}
const auto wrapped = position(messageId);
_list.addSlice(
{ wrapped },
{ .from = wrapped, .till = MaxMessagePosition },
std::nullopt);
}
void PinnedMessages::clearLessThanId(MsgId messageId) {
_list.removeLessThan(position(messageId));
_storage.add(Storage::SharedMediaAddNew(
_peer->id,
PinnedType,
messageId));
}
} // namespace Data

View File

@@ -10,6 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_messages.h"
#include "base/weak_ptr.h"
namespace Storage {
class Facade;
} // namespace Storage
namespace Data {
struct PinnedAroundId {
@@ -21,30 +25,18 @@ struct PinnedAroundId {
class PinnedMessages final : public base::has_weak_ptr {
public:
explicit PinnedMessages(ChannelId channelId);
explicit PinnedMessages(not_null<PeerData*> peer);
[[nodiscard]] bool empty() const;
[[nodiscard]] MsgId topId() const;
[[nodiscard]] rpl::producer<PinnedAroundId> viewer(
MsgId aroundId,
int limit) const;
void add(MsgId messageId);
void add(
std::vector<MsgId> &&ids,
MsgRange range,
std::optional<int> count);
void remove(MsgId messageId);
void setTopId(MsgId messageId);
void clearLessThanId(MsgId messageId);
private:
[[nodiscard]] MessagePosition position(MsgId id) const;
MessagesList _list;
ChannelId _channelId = 0;
const not_null<PeerData*> _peer;
Storage::Facade &_storage;
};

View File

@@ -55,6 +55,8 @@ std::optional<MTPmessages_Search> PrepareSearchRequest(
return MTP_inputMessagesFilterUrl();
case Type::ChatPhoto:
return MTP_inputMessagesFilterChatPhotos();
case Type::Pinned:
return MTP_inputMessagesFilterPinned();
}
return MTP_inputMessagesFilterEmpty();
}();

View File

@@ -123,7 +123,8 @@ rpl::producer<SparseIdsSlice> SharedMediaViewer(
using AllRemoved = Storage::SharedMediaRemoveAll;
session->storage().sharedMediaAllRemoved(
) | rpl::filter([=](const AllRemoved &update) {
return (update.peerId == key.peerId);
return (update.peerId == key.peerId)
&& (update.types.test(key.type));
}) | rpl::filter([=] {
return builder->removeAll();
}) | rpl::start_with_next(pushNextSnapshot, lifetime);