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

View File

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

View File

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

View File

@ -41,18 +41,50 @@ struct PositionChange {
};
struct UnreadState {
std::optional<int> messagesCount;
int messagesCountMuted = 0;
int chatsCount = 0;
int chatsCountMuted = 0;
bool mark = false;
bool markMuted = false;
int messages = 0;
int messagesMuted = 0;
int chats = 0;
int chatsMuted = 0;
int marks = 0;
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 {
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 {
public:
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"
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)
: _all(SortMode::Date)
, _important(SortMode::Date)
, _pinned(1) {
_unreadState.messagesCount = 0;
_unreadState.known = true;
std::move(
pinnedLimit
@ -84,27 +55,17 @@ void MainList::clear() {
void MainList::unreadStateChanged(
const UnreadState &wasState,
const UnreadState &nowState) {
const auto wasWithMark = ApplyMarkToCounters(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;
_unreadState += nowState - wasState;
}
void MainList::unreadEntryChanged(
const Dialogs::UnreadState &state,
bool added) {
const auto withMark = ApplyMarkToCounters(state);
const auto delta = (added ? 1 : -1);
*_unreadState.messagesCount += delta * *withMark.messagesCount;
_unreadState.messagesCountMuted += delta * withMark.messagesCountMuted;
_unreadState.chatsCount += delta * withMark.chatsCount;
_unreadState.chatsCountMuted += delta * withMark.chatsCountMuted;
if (added) {
_unreadState += state;
} else {
_unreadState -= state;
}
}
UnreadState MainList::unreadState() const {

View File

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