mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Track forum unread state by topics inside.
This commit is contained in:
parent
a292f8a34e
commit
08ba277327
12 changed files with 116 additions and 30 deletions
|
@ -66,7 +66,9 @@ Data::ChatBotCommands::Changed MegagroupInfo::setBotCommands(
|
|||
|
||||
void MegagroupInfo::ensureForum(not_null<ChannelData*> that) {
|
||||
if (!_forum) {
|
||||
_forum = std::make_unique<Data::Forum>(that->owner().history(that));
|
||||
const auto history = that->owner().history(that);
|
||||
_forum = std::make_unique<Data::Forum>(history);
|
||||
history->forumChanged(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +77,12 @@ Data::Forum *MegagroupInfo::forum() const {
|
|||
}
|
||||
|
||||
std::unique_ptr<Data::Forum> MegagroupInfo::takeForumData() {
|
||||
return std::move(_forum);
|
||||
if (auto result = base::take(_forum)) {
|
||||
result->history()->forumChanged(result.get());
|
||||
return result;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
ChannelData::ChannelData(not_null<Data::Session*> owner, PeerId id)
|
||||
|
|
|
@ -212,7 +212,7 @@ bool ChatFilter::contains(not_null<History*> history) const {
|
|||
&& history->folderKnown()
|
||||
&& !history->folder()))
|
||||
&& (!(_flags & Flag::NoRead)
|
||||
|| history->unreadCount()
|
||||
|| history->chatListUnreadCount()
|
||||
|| history->unreadMark()
|
||||
|| history->unreadMentions().has()
|
||||
|| history->fakeUnreadWhileOpened())
|
||||
|
|
|
@ -71,17 +71,6 @@ Folder::Folder(not_null<Data::Session*> owner, FolderId id)
|
|||
}, _lifetime);
|
||||
}
|
||||
|
||||
void Folder::updateChatListEntryPostponed() {
|
||||
if (_updateChatListEntryPostponed) {
|
||||
return;
|
||||
}
|
||||
_updateChatListEntryPostponed = true;
|
||||
Ui::PostponeCall(this, [=] {
|
||||
updateChatListEntry();
|
||||
_updateChatListEntryPostponed = false;
|
||||
});
|
||||
}
|
||||
|
||||
FolderId Folder::id() const {
|
||||
return _id;
|
||||
}
|
||||
|
|
|
@ -81,7 +81,6 @@ private:
|
|||
int chatListNameVersion() const override;
|
||||
|
||||
void reorderLastHistories();
|
||||
void updateChatListEntryPostponed();
|
||||
|
||||
void paintUserpic(
|
||||
Painter &p,
|
||||
|
@ -101,7 +100,6 @@ private:
|
|||
std::vector<not_null<History*>> _lastHistories;
|
||||
HistoryItem *_chatListMessage = nullptr;
|
||||
uint32 _chatListViewVersion = 0;
|
||||
bool _updateChatListEntryPostponed = false;
|
||||
//rpl::variable<MessagePosition> _unreadPosition;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace Data {
|
|||
namespace {
|
||||
|
||||
constexpr auto kTopicsFirstLoad = 20;
|
||||
constexpr auto kLoadedTopicsMinCount = 20;
|
||||
constexpr auto kTopicsPerPage = 500;
|
||||
constexpr auto kGeneralColorId = 0xA9A9A9;
|
||||
|
||||
|
@ -39,6 +40,10 @@ Forum::Forum(not_null<History*> history)
|
|||
: _history(history)
|
||||
, _topicsList(&session(), FilterId(0), rpl::single(1)) {
|
||||
Expects(_history->peer->isChannel());
|
||||
|
||||
if (_history->inChatList()) {
|
||||
preloadTopics();
|
||||
}
|
||||
}
|
||||
|
||||
Forum::~Forum() {
|
||||
|
@ -89,6 +94,12 @@ rpl::producer<not_null<ForumTopic*>> Forum::topicDestroyed() const {
|
|||
return _topicDestroyed.events();
|
||||
}
|
||||
|
||||
void Forum::preloadTopics() {
|
||||
if (topicsList()->indexed()->size() < kLoadedTopicsMinCount) {
|
||||
requestTopics();
|
||||
}
|
||||
}
|
||||
|
||||
void Forum::requestTopics() {
|
||||
if (_allLoaded || _requestId) {
|
||||
return;
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
[[nodiscard]] auto topicDestroyed() const
|
||||
-> rpl::producer<not_null<ForumTopic*>>;
|
||||
|
||||
void preloadTopics();
|
||||
void requestTopics();
|
||||
[[nodiscard]] rpl::producer<> chatsListChanges() const;
|
||||
[[nodiscard]] rpl::producer<> chatsListLoadedEvents() const;
|
||||
|
@ -68,6 +69,10 @@ public:
|
|||
void clearAllUnreadReactions();
|
||||
void enumerateTopics(Fn<void(not_null<ForumTopic*>)> action) const;
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime() {
|
||||
return _lifetime;
|
||||
}
|
||||
|
||||
private:
|
||||
struct TopicRequest {
|
||||
mtpRequestId id = 0;
|
||||
|
@ -97,6 +102,8 @@ private:
|
|||
rpl::event_stream<> _chatsListChanges;
|
||||
rpl::event_stream<> _chatsListLoadedEvents;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -652,11 +652,7 @@ not_null<HistoryView::SendActionPainter*> ForumTopic::sendActionPainter() {
|
|||
}
|
||||
|
||||
int ForumTopic::chatListUnreadCount() const {
|
||||
const auto state = chatListUnreadState();
|
||||
return state.marks
|
||||
+ (Core::App().settings().countUnreadMessages()
|
||||
? state.messages
|
||||
: state.chats);
|
||||
return unreadCount();
|
||||
}
|
||||
|
||||
Dialogs::UnreadState ForumTopic::chatListUnreadState() const {
|
||||
|
|
|
@ -46,7 +46,11 @@ uint64 PinnedDialogPos(int pinnedIndex) {
|
|||
|
||||
Entry::Entry(not_null<Data::Session*> owner, Type type)
|
||||
: _owner(owner)
|
||||
, _type(type) {
|
||||
, _flags((type == Type::History)
|
||||
? (Flag::IsThread | Flag::IsHistory)
|
||||
: (type == Type::ForumTopic)
|
||||
? Flag::IsThread
|
||||
: Flag(0)) {
|
||||
}
|
||||
|
||||
Entry::~Entry() = default;
|
||||
|
@ -60,23 +64,23 @@ Main::Session &Entry::session() const {
|
|||
}
|
||||
|
||||
History *Entry::asHistory() {
|
||||
return (_type == Type::History) ? static_cast<History*>(this) : nullptr;
|
||||
return (_flags & Flag::IsHistory) ? static_cast<History*>(this) : nullptr;
|
||||
}
|
||||
|
||||
Data::Folder *Entry::asFolder() {
|
||||
return (_type == Type::Folder)
|
||||
? static_cast<Data::Folder*>(this)
|
||||
: nullptr;
|
||||
return (_flags & Flag::IsThread)
|
||||
? nullptr
|
||||
: static_cast<Data::Folder*>(this);
|
||||
}
|
||||
|
||||
Data::Thread *Entry::asThread() {
|
||||
return (_type == Type::History || _type == Type::ForumTopic)
|
||||
return (_flags & Flag::IsThread)
|
||||
? static_cast<Data::Thread*>(this)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
Data::ForumTopic *Entry::asTopic() {
|
||||
return (_type == Type::ForumTopic)
|
||||
return ((_flags & Flag::IsThread) && !(_flags & Flag::IsHistory))
|
||||
? static_cast<Data::ForumTopic*>(this)
|
||||
: nullptr;
|
||||
}
|
||||
|
@ -298,7 +302,20 @@ void Entry::addChatListEntryByLetter(
|
|||
}
|
||||
|
||||
void Entry::updateChatListEntry() {
|
||||
_flags &= ~Flag::UpdatePostponed;
|
||||
session().changes().entryUpdated(this, Data::EntryUpdate::Flag::Repaint);
|
||||
}
|
||||
|
||||
void Entry::updateChatListEntryPostponed() {
|
||||
if (_flags & Flag::UpdatePostponed) {
|
||||
return;
|
||||
}
|
||||
_flags |= Flag::UpdatePostponed;
|
||||
Ui::PostponeCall(this, [=] {
|
||||
if (_flags & Flag::UpdatePostponed) {
|
||||
updateChatListEntry();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Dialogs
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "base/flat_map.h"
|
||||
#include "base/weak_ptr.h"
|
||||
#include "base/flags.h"
|
||||
#include "dialogs/dialogs_key.h"
|
||||
#include "ui/unread_badge.h"
|
||||
|
||||
|
@ -145,6 +146,7 @@ public:
|
|||
QChar letter,
|
||||
not_null<Row*> row);
|
||||
void updateChatListEntry();
|
||||
void updateChatListEntryPostponed();
|
||||
[[nodiscard]] bool isPinnedDialog(FilterId filterId) const {
|
||||
return lookupPinnedIndex(filterId) != 0;
|
||||
}
|
||||
|
@ -214,6 +216,14 @@ protected:
|
|||
[[nodiscard]] int lookupPinnedIndex(FilterId filterId) const;
|
||||
|
||||
private:
|
||||
enum class Flag : uchar {
|
||||
IsThread = (1 << 0),
|
||||
IsHistory = (1 << 1),
|
||||
UpdatePostponed = (1 << 2),
|
||||
};
|
||||
friend inline constexpr bool is_flag_type(Flag) { return true; }
|
||||
using Flags = base::flags<Flag>;
|
||||
|
||||
virtual void changedChatListPinHook();
|
||||
void pinnedIndexChanged(FilterId filterId, int was, int now);
|
||||
[[nodiscard]] uint64 computeSortPosition(FilterId filterId) const;
|
||||
|
@ -233,7 +243,7 @@ private:
|
|||
mutable Ui::Text::String _chatListNameText;
|
||||
mutable int _chatListNameVersion = 0;
|
||||
TimeId _timeId = 0;
|
||||
const Type _type;
|
||||
Flags _flags;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace {
|
|||
const auto name = history->peer->name();
|
||||
return TextWithEntities{
|
||||
.text = name,
|
||||
.entities = (history->unreadCount() > 0)
|
||||
.entities = (history->chatListUnreadCount() > 0)
|
||||
? EntitiesInText{
|
||||
{ EntityType::Semibold, 0, int(name.size()), QString() },
|
||||
{ EntityType::PlainLink, 0, int(name.size()), QString() },
|
||||
|
|
|
@ -2067,6 +2067,13 @@ History *History::migrateSibling() const {
|
|||
}
|
||||
|
||||
int History::chatListUnreadCount() const {
|
||||
if (peer->isForum()) {
|
||||
const auto state = chatListUnreadState();
|
||||
return state.marks
|
||||
+ (Core::App().settings().countUnreadMessages()
|
||||
? state.messages
|
||||
: state.chats);
|
||||
}
|
||||
const auto result = unreadCount();
|
||||
if (const auto migrated = migrateSibling()) {
|
||||
return result + migrated->unreadCount();
|
||||
|
@ -2084,10 +2091,24 @@ bool History::chatListUnreadMark() const {
|
|||
}
|
||||
|
||||
bool History::chatListMutedBadge() const {
|
||||
if (const auto forum = peer->forum()) {
|
||||
const auto state = forum->topicsList()->unreadState();
|
||||
return (state.marksMuted >= state.marks)
|
||||
&& (Core::App().settings().countUnreadMessages()
|
||||
? (state.messagesMuted >= state.messages)
|
||||
: (state.chatsMuted >= state.chats));
|
||||
}
|
||||
return muted();
|
||||
}
|
||||
|
||||
Dialogs::UnreadState History::chatListUnreadState() const {
|
||||
if (const auto forum = peer->forum()) {
|
||||
return forum->topicsList()->unreadState();
|
||||
}
|
||||
return computeUnreadState();
|
||||
}
|
||||
|
||||
Dialogs::UnreadState History::computeUnreadState() const {
|
||||
auto result = Dialogs::UnreadState();
|
||||
const auto count = _unreadCount.value_or(0);
|
||||
const auto mark = !count && unreadMark();
|
||||
|
@ -2639,6 +2660,10 @@ void History::applyDialog(
|
|||
draft->c_draftMessage());
|
||||
}
|
||||
owner().histories().dialogEntryApplied(this);
|
||||
|
||||
if (const auto forum = inChatList() ? peer->forum() : nullptr) {
|
||||
forum->preloadTopics();
|
||||
}
|
||||
}
|
||||
|
||||
void History::dialogEntryApplied() {
|
||||
|
@ -2868,6 +2893,28 @@ const Data::Thread *History::threadFor(MsgId topicRootId) const {
|
|||
return const_cast<History*>(this)->threadFor(topicRootId);
|
||||
}
|
||||
|
||||
void History::forumChanged(Data::Forum *old) {
|
||||
if (inChatList()) {
|
||||
notifyUnreadStateChange(old
|
||||
? old->topicsList()->unreadState()
|
||||
: computeUnreadState());
|
||||
}
|
||||
|
||||
if (const auto forum = peer->forum()) {
|
||||
_flags |= Flag::IsForum;
|
||||
|
||||
forum->topicsList()->unreadStateChanges(
|
||||
) | rpl::filter([=] {
|
||||
return (_flags & Flag::IsForum) && inChatList();
|
||||
}) | rpl::start_with_next([=](const Dialogs::UnreadState &old) {
|
||||
notifyUnreadStateChange(old);
|
||||
updateChatListEntryPostponed();
|
||||
}, forum->lifetime());
|
||||
} else {
|
||||
_flags &= ~Flag::IsForum;
|
||||
}
|
||||
}
|
||||
|
||||
not_null<History*> History::migrateToOrMe() const {
|
||||
if (const auto to = peer->migrateTo()) {
|
||||
return owner().history(to);
|
||||
|
|
|
@ -88,6 +88,8 @@ public:
|
|||
return _delegateMixin.get();
|
||||
}
|
||||
|
||||
void forumChanged(Data::Forum *old);
|
||||
|
||||
not_null<History*> migrateToOrMe() const;
|
||||
History *migrateFrom() const;
|
||||
MsgRange rangeForDifferenceRequest() const;
|
||||
|
@ -461,6 +463,7 @@ private:
|
|||
enum class Flag : uchar {
|
||||
HasPendingResizedItems = (1 << 0),
|
||||
IsTopPromoted = (1 << 1),
|
||||
IsForum = (1 << 2),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) {
|
||||
|
@ -571,6 +574,7 @@ private:
|
|||
HistoryService *insertJoinedMessage();
|
||||
void insertMessageToBlocks(not_null<HistoryItem*> item);
|
||||
|
||||
[[nodiscard]] Dialogs::UnreadState computeUnreadState() const;
|
||||
void setFolderPointer(Data::Folder *folder);
|
||||
|
||||
int chatListNameVersion() const override;
|
||||
|
|
Loading…
Add table
Reference in a new issue