Count unread marks in non-fully loaded folders.

This commit is contained in:
John Preston 2019-04-24 19:28:01 +04:00
parent 4c571f5bff
commit 5f62c2100c
6 changed files with 109 additions and 156 deletions

View file

@ -104,7 +104,7 @@ void Folder::registerOne(not_null<History*> history) {
++_chatListViewVersion; ++_chatListViewVersion;
if (_chatsList.indexed()->size() == 1) { if (_chatsList.indexed()->size() == 1) {
updateChatListSortPosition(); updateChatListSortPosition();
if (!_cloudUnread.messagesCount.has_value()) { if (!_cloudUnread.known) {
session().api().requestDialogEntry(this); session().api().requestDialogEntry(this);
} }
} else { } else {
@ -337,22 +337,24 @@ void Folder::applyDialog(const MTPDdialogFolder &data) {
void Folder::updateCloudUnread(const MTPDdialogFolder &data) { void Folder::updateCloudUnread(const MTPDdialogFolder &data) {
const auto notifier = unreadStateChangeNotifier(!_chatsList.loaded()); const auto notifier = unreadStateChangeNotifier(!_chatsList.loaded());
_cloudUnread.messagesCountMuted = data.vunread_muted_messages_count.v; _cloudUnread.messagesMuted = data.vunread_muted_messages_count.v;
_cloudUnread.messagesCount = _cloudUnread.messagesCountMuted _cloudUnread.messages = _cloudUnread.messagesMuted
+ data.vunread_unmuted_messages_count.v; + data.vunread_unmuted_messages_count.v;
_cloudUnread.chatsCountMuted = data.vunread_muted_peers_count.v; _cloudUnread.chatsMuted = data.vunread_muted_peers_count.v;
_cloudUnread.chatsCount = _cloudUnread.chatsCountMuted _cloudUnread.chats = _cloudUnread.chatsMuted
+ data.vunread_unmuted_peers_count.v; + data.vunread_unmuted_peers_count.v;
_cloudUnread.known = true;
} }
Dialogs::UnreadState Folder::chatListUnreadState() const { Dialogs::UnreadState Folder::chatListUnreadState() const {
const auto state = _chatsList.loaded() const auto localUnread = _chatsList.unreadState();
? _chatsList.unreadState() auto result = _chatsList.loaded() ? localUnread : _cloudUnread;
: _cloudUnread; result.messagesMuted = result.messages;
auto result = Dialogs::UnreadState(); result.chatsMuted = result.chats;
result.messagesCount = state.messagesCount;
result.messagesCountMuted = result.messagesCount.value_or(0); // We don't know the real value of marked chats counts.
result.chatsCount = result.chatsCountMuted = state.chatsCount; result.marksMuted = result.marks = localUnread.marks;
return result; return result;
} }
@ -376,25 +378,18 @@ void Folder::unreadStateChanged(
} }
} }
const auto updateCloudUnread = _cloudUnread.messagesCount.has_value() const auto updateCloudUnread = _cloudUnread.known && wasState.known;
&& wasState.messagesCount.has_value();
const auto notify = _chatsList.loaded() || updateCloudUnread; const auto notify = _chatsList.loaded() || updateCloudUnread;
const auto notifier = unreadStateChangeNotifier(notify); const auto notifier = unreadStateChangeNotifier(notify);
_chatsList.unreadStateChanged(wasState, nowState); _chatsList.unreadStateChanged(wasState, nowState);
if (!_cloudUnread.messagesCount.has_value() if (updateCloudUnread) {
|| !wasState.messagesCount.has_value()) { Assert(nowState.known);
return; _cloudUnread += nowState - wasState;
}
Assert(nowState.messagesCount.has_value());
*_cloudUnread.messagesCount += *nowState.messagesCount // We don't know the real value of marked chats counts.
- *wasState.messagesCount; _cloudUnread.marks = _cloudUnread.marksMuted = 0;
_cloudUnread.messagesCountMuted += nowState.messagesCountMuted }
- wasState.messagesCountMuted;
_cloudUnread.chatsCount += nowState.chatsCount - wasState.chatsCount;
_cloudUnread.chatsCountMuted += nowState.chatsCountMuted
- wasState.chatsCountMuted;
} }
void Folder::unreadEntryChanged( void Folder::unreadEntryChanged(
@ -411,21 +406,21 @@ void Folder::unreadEntryChanged(
} }
} }
const auto updateCloudUnread = _cloudUnread.messagesCount.has_value() const auto updateCloudUnread = _cloudUnread.known && state.known;
&& state.messagesCount.has_value();
const auto notify = _chatsList.loaded() || updateCloudUnread; const auto notify = _chatsList.loaded() || updateCloudUnread;
const auto notifier = unreadStateChangeNotifier(notify); const auto notifier = unreadStateChangeNotifier(notify);
_chatsList.unreadEntryChanged(state, added); _chatsList.unreadEntryChanged(state, added);
if (!_cloudUnread.messagesCount.has_value() if (updateCloudUnread) {
|| !state.messagesCount.has_value()) { if (added) {
return; _cloudUnread += state;
} else {
_cloudUnread -= state;
}
// We don't know the real value of marked chats counts.
_cloudUnread.marks = _cloudUnread.marksMuted = 0;
} }
const auto delta = (added ? 1 : -1);
*_cloudUnread.messagesCount += delta * *state.messagesCount;
_cloudUnread.messagesCountMuted += delta * state.messagesCountMuted;
_cloudUnread.chatsCount += delta * state.chatsCount;
_cloudUnread.chatsCountMuted += delta * state.chatsCountMuted;
} }
// #feed // #feed
@ -450,9 +445,11 @@ bool Folder::shouldBeInChatList() const {
} }
int Folder::chatListUnreadCount() const { int Folder::chatListUnreadCount() const {
return session().settings().countUnreadMessages() const auto state = chatListUnreadState();
? chatListUnreadState().messagesCount.value_or(0) return state.marks
: chatListUnreadState().chatsCount; + (session().settings().countUnreadMessages()
? state.messages
: state.chats);
} }
bool Folder::chatListUnreadMark() const { bool Folder::chatListUnreadMark() const {

View file

@ -1578,36 +1578,18 @@ void Session::updateSendActionAnimation(
} }
int Session::unreadBadge() const { int Session::unreadBadge() const {
const auto state = _chatsList.unreadState(); return computeUnreadBadge(_chatsList.unreadState());
return computeUnreadBadge(
state.messagesCount.value_or(0),
state.messagesCountMuted,
state.chatsCount,
state.chatsCountMuted);
} }
bool Session::unreadBadgeMuted() const { bool Session::unreadBadgeMuted() const {
const auto state = _chatsList.unreadState(); return computeUnreadBadgeMuted(_chatsList.unreadState());
return computeUnreadBadgeMuted(
state.messagesCount.value_or(0),
state.messagesCountMuted,
state.chatsCount,
state.chatsCountMuted);
} }
int Session::unreadBadgeIgnoreOne(const Dialogs::Key &key) const { int Session::unreadBadgeIgnoreOne(const Dialogs::Key &key) const {
const auto remove = (key && key.entry()->inChatList()) const auto remove = (key && key.entry()->inChatList())
? key.entry()->chatListUnreadState() ? key.entry()->chatListUnreadState()
: Dialogs::UnreadState(); : Dialogs::UnreadState();
if (remove.empty()) { return computeUnreadBadge(_chatsList.unreadState() - remove);
return unreadBadge();
}
const auto state = _chatsList.unreadState();
return computeUnreadBadge(
state.messagesCount.value_or(0) - remove.messagesCount.value_or(0),
state.messagesCountMuted - remove.messagesCountMuted,
state.chatsCount - remove.chatsCount,
state.chatsCountMuted - remove.chatsCountMuted);
} }
bool Session::unreadBadgeMutedIgnoreOne(const Dialogs::Key &key) const { bool Session::unreadBadgeMutedIgnoreOne(const Dialogs::Key &key) const {
@ -1617,46 +1599,33 @@ bool Session::unreadBadgeMutedIgnoreOne(const Dialogs::Key &key) const {
const auto remove = (key && key.entry()->inChatList()) const auto remove = (key && key.entry()->inChatList())
? key.entry()->chatListUnreadState() ? key.entry()->chatListUnreadState()
: Dialogs::UnreadState(); : Dialogs::UnreadState();
if (remove.empty()) { return computeUnreadBadgeMuted(_chatsList.unreadState() - remove);
return unreadBadgeMuted();
}
const auto state = _chatsList.unreadState();
return computeUnreadBadgeMuted(
state.messagesCount.value_or(0) - remove.messagesCount.value_or(0),
state.messagesCountMuted - remove.messagesCountMuted,
state.chatsCount - remove.chatsCount,
state.chatsCountMuted - remove.chatsCountMuted);
} }
int Session::unreadOnlyMutedBadge() const { int Session::unreadOnlyMutedBadge() const {
const auto state = _chatsList.unreadState(); const auto state = _chatsList.unreadState();
return _session->settings().countUnreadMessages() return _session->settings().countUnreadMessages()
? state.messagesCountMuted ? state.messagesMuted
: state.chatsCountMuted; : state.chatsMuted;
} }
int Session::computeUnreadBadge( int Session::computeUnreadBadge(const Dialogs::UnreadState &state) const {
int full, const auto all = _session->settings().includeMutedCounter();
int muted, return std::max(state.marks - (all ? 0 : state.marksMuted), 0)
int entriesFull, + (_session->settings().countUnreadMessages()
int entriesMuted) const { ? std::max(state.messages - (all ? 0 : state.messagesMuted), 0)
const auto withMuted = _session->settings().includeMutedCounter(); : std::max(state.chats - (all ? 0 : state.chatsMuted), 0));
return _session->settings().countUnreadMessages()
? (full - (withMuted ? 0 : muted))
: (entriesFull - (withMuted ? 0 : entriesMuted));
} }
bool Session::computeUnreadBadgeMuted( bool Session::computeUnreadBadgeMuted(
int full, const Dialogs::UnreadState &state) const {
int muted,
int entriesFull,
int entriesMuted) const {
if (!_session->settings().includeMutedCounter()) { if (!_session->settings().includeMutedCounter()) {
return false; return false;
} }
return _session->settings().countUnreadMessages() return (state.marksMuted >= state.marks)
? (muted >= full) && (_session->settings().countUnreadMessages()
: (entriesMuted >= entriesFull); ? (state.messagesMuted >= state.messages)
: (state.chatsMuted >= state.chats));
} }
void Session::unreadStateChanged( void Session::unreadStateChanged(

View file

@ -599,16 +599,8 @@ private:
void checkSelfDestructItems(); void checkSelfDestructItems();
int computeUnreadBadge( int computeUnreadBadge(const Dialogs::UnreadState &state) const;
int full, bool computeUnreadBadgeMuted(const Dialogs::UnreadState &state) const;
int muted,
int entriesFull,
int entriesMuted) const;
bool computeUnreadBadgeMuted(
int full,
int muted,
int entriesFull,
int entriesMuted) const;
void applyDialog(Data::Folder *requestFolder, const MTPDdialog &data); void applyDialog(Data::Folder *requestFolder, const MTPDdialog &data);
void applyDialog( void applyDialog(

View file

@ -41,18 +41,50 @@ struct PositionChange {
}; };
struct UnreadState { struct UnreadState {
std::optional<int> messagesCount; int messages = 0;
int messagesCountMuted = 0; int messagesMuted = 0;
int chatsCount = 0; int chats = 0;
int chatsCountMuted = 0; int chatsMuted = 0;
bool mark = false; int marks = 0;
bool markMuted = false; int marksMuted = 0;
bool known = false;
UnreadState &operator+=(const UnreadState &other) {
messages += other.messages;
messagesMuted += other.messagesMuted;
chats += other.chats;
chatsMuted += other.chatsMuted;
marks += other.marks;
marksMuted += other.marksMuted;
return *this;
}
UnreadState &operator-=(const UnreadState &other) {
messages -= other.messages;
messagesMuted -= other.messagesMuted;
chats -= other.chats;
chatsMuted -= other.chatsMuted;
marks -= other.marks;
marksMuted -= other.marksMuted;
return *this;
}
bool empty() const { bool empty() const {
return !messagesCount.value_or(0) && !chatsCount && !mark; return !messages && !chats && !marks;
} }
}; };
inline UnreadState operator+(const UnreadState &a, const UnreadState &b) {
auto result = a;
result += b;
return result;
}
inline UnreadState operator-(const UnreadState &a, const UnreadState &b) {
auto result = a;
result -= b;
return result;
}
class Entry { class Entry {
public: public:
Entry(not_null<Data::Session*> owner, const Key &key); Entry(not_null<Data::Session*> owner, const Key &key);

View file

@ -11,41 +11,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h" #include "history/history.h"
namespace Dialogs { namespace Dialogs {
namespace {
UnreadState ApplyMarkToCounters(const UnreadState &state) {
auto result = UnreadState();
const auto count = state.messagesCount.value_or(0);
result.messagesCount = (count > 0)
? count
: state.mark
? 1
: 0;
result.messagesCountMuted = (state.messagesCountMuted > 0)
? state.messagesCountMuted
: state.markMuted
? 1
: 0;
result.chatsCount = (state.chatsCount > 0)
? state.chatsCount
: state.mark
? 1
: 0;
result.chatsCountMuted = (state.chatsCountMuted > 0)
? state.chatsCountMuted
: state.markMuted
? 1
: 0;
return result;
}
} // namespace
MainList::MainList(rpl::producer<int> pinnedLimit) MainList::MainList(rpl::producer<int> pinnedLimit)
: _all(SortMode::Date) : _all(SortMode::Date)
, _important(SortMode::Date) , _important(SortMode::Date)
, _pinned(1) { , _pinned(1) {
_unreadState.messagesCount = 0; _unreadState.known = true;
std::move( std::move(
pinnedLimit pinnedLimit
@ -84,27 +55,17 @@ void MainList::clear() {
void MainList::unreadStateChanged( void MainList::unreadStateChanged(
const UnreadState &wasState, const UnreadState &wasState,
const UnreadState &nowState) { const UnreadState &nowState) {
const auto wasWithMark = ApplyMarkToCounters(wasState); _unreadState += nowState - wasState;
const auto nowWithMark = ApplyMarkToCounters(nowState);
*_unreadState.messagesCount += *nowWithMark.messagesCount
- *wasWithMark.messagesCount;
_unreadState.messagesCountMuted += nowWithMark.messagesCountMuted
- wasWithMark.messagesCountMuted;
_unreadState.chatsCount += nowWithMark.chatsCount
- wasWithMark.chatsCount;
_unreadState.chatsCountMuted += nowWithMark.chatsCountMuted
- wasWithMark.chatsCountMuted;
} }
void MainList::unreadEntryChanged( void MainList::unreadEntryChanged(
const Dialogs::UnreadState &state, const Dialogs::UnreadState &state,
bool added) { bool added) {
const auto withMark = ApplyMarkToCounters(state); if (added) {
const auto delta = (added ? 1 : -1); _unreadState += state;
*_unreadState.messagesCount += delta * *withMark.messagesCount; } else {
_unreadState.messagesCountMuted += delta * withMark.messagesCountMuted; _unreadState -= state;
_unreadState.chatsCount += delta * withMark.chatsCount; }
_unreadState.chatsCountMuted += delta * withMark.chatsCountMuted;
} }
UnreadState MainList::unreadState() const { UnreadState MainList::unreadState() const {

View file

@ -2029,12 +2029,14 @@ bool History::chatListMutedBadge() const {
Dialogs::UnreadState History::chatListUnreadState() const { Dialogs::UnreadState History::chatListUnreadState() const {
auto result = Dialogs::UnreadState(); auto result = Dialogs::UnreadState();
const auto count = _unreadCount.value_or(0); const auto count = _unreadCount.value_or(0);
result.messagesCount = _unreadCount; const auto mark = !count && _unreadMark;
result.messagesCountMuted = (_unreadCount && mute()) ? count : 0; result.messages = count;
result.chatsCount = count ? 1 : 0; result.messagesMuted = mute() ? count : 0;
result.chatsCountMuted = (count && mute()) ? 1 : 0; result.chats = count ? 1 : 0;
result.mark = _unreadMark; result.chatsMuted = (count && mute()) ? 1 : 0;
result.markMuted = mute() ? _unreadMark : false; result.marks = mark ? 1 : 0;
result.marksMuted = (mark && mute()) ? 1 : 0;
result.known = _unreadCount.has_value();
return result; return result;
} }