mirror of https://github.com/procxx/kepka.git
Count unread messages in Dialogs::MainList.
This commit is contained in:
parent
9636617798
commit
38a744fe5b
|
@ -303,14 +303,16 @@ bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) {
|
|||
|| (filter.always() != updated.always())
|
||||
|| (filter.never() != updated.never());
|
||||
if (rulesChanged) {
|
||||
const auto id = filter.id();
|
||||
const auto filterList = _owner->chatsFilters().chatsList(id);
|
||||
const auto feedHistory = [&](not_null<History*> history) {
|
||||
const auto now = updated.contains(history);
|
||||
const auto was = filter.contains(history);
|
||||
if (now != was) {
|
||||
if (now) {
|
||||
history->addToChatList(filter.id());
|
||||
history->addToChatList(id, filterList);
|
||||
} else {
|
||||
history->removeFromChatList(filter.id());
|
||||
history->removeFromChatList(id, filterList);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -322,8 +324,7 @@ bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) {
|
|||
}
|
||||
};
|
||||
feedList(_owner->chatsList());
|
||||
const auto id = Data::Folder::kId;
|
||||
if (const auto folder = _owner->folderLoaded(id)) {
|
||||
if (const auto folder = _owner->folderLoaded(Data::Folder::kId)) {
|
||||
feedList(folder->chatsList());
|
||||
}
|
||||
} else if (filter.title() == updated.title()) {
|
||||
|
|
|
@ -72,6 +72,22 @@ Folder::Folder(not_null<Data::Session*> owner, FolderId id)
|
|||
}
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
_chatsList.setAllAreMuted(true);
|
||||
|
||||
_chatsList.unreadStateChanges(
|
||||
) | rpl::filter([=] {
|
||||
return inChatList();
|
||||
}) | rpl::start_with_next([=](const Dialogs::UnreadState &old) {
|
||||
++_chatListViewVersion;
|
||||
notifyUnreadStateChange(old);
|
||||
updateChatListEntry();
|
||||
}, _lifetime);
|
||||
|
||||
_chatsList.fullSize().changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateChatListEntry();
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
FolderId Folder::id() const {
|
||||
|
@ -108,7 +124,7 @@ void Folder::indexNameParts() {
|
|||
void Folder::registerOne(not_null<History*> history) {
|
||||
if (_chatsList.indexed()->size() == 1) {
|
||||
updateChatListSortPosition();
|
||||
if (!_cloudUnread.known) {
|
||||
if (!_chatsList.cloudUnreadKnown()) {
|
||||
owner().histories().requestDialogEntry(this);
|
||||
}
|
||||
} else {
|
||||
|
@ -291,29 +307,6 @@ void Folder::paintUserpic(
|
|||
//}
|
||||
}
|
||||
|
||||
bool Folder::chatsListLoaded() const {
|
||||
return _chatsList.loaded();
|
||||
}
|
||||
|
||||
void Folder::setChatsListLoaded(bool loaded) {
|
||||
if (_chatsList.loaded() == loaded) {
|
||||
return;
|
||||
}
|
||||
const auto notifier = unreadStateChangeNotifier(true);
|
||||
_chatsList.setLoaded(loaded);
|
||||
}
|
||||
|
||||
void Folder::setCloudChatsListSize(int size) {
|
||||
_cloudChatsListSize = size;
|
||||
updateChatListEntry();
|
||||
}
|
||||
|
||||
int Folder::chatsListSize() const {
|
||||
return std::max(
|
||||
_chatsList.indexed()->size(),
|
||||
_chatsList.loaded() ? 0 : _cloudChatsListSize);
|
||||
}
|
||||
|
||||
const std::vector<not_null<History*>> &Folder::lastHistories() const {
|
||||
return _lastHistories;
|
||||
}
|
||||
|
@ -333,7 +326,7 @@ TimeId Folder::adjustedChatListTimeId() const {
|
|||
}
|
||||
|
||||
void Folder::applyDialog(const MTPDdialogFolder &data) {
|
||||
updateCloudUnread(data);
|
||||
_chatsList.updateCloudUnread(data);
|
||||
if (const auto peerId = peerFromMTP(data.vpeer())) {
|
||||
const auto history = owner().history(peerId);
|
||||
const auto fullId = FullMsgId(
|
||||
|
@ -349,39 +342,6 @@ void Folder::applyDialog(const MTPDdialogFolder &data) {
|
|||
}
|
||||
}
|
||||
|
||||
void Folder::updateCloudUnread(const MTPDdialogFolder &data) {
|
||||
const auto notifier = unreadStateChangeNotifier(!_chatsList.loaded());
|
||||
|
||||
_cloudUnread.messages = data.vunread_muted_messages_count().v
|
||||
+ data.vunread_unmuted_messages_count().v;
|
||||
_cloudUnread.chats = data.vunread_muted_peers_count().v
|
||||
+ data.vunread_unmuted_peers_count().v;
|
||||
finalizeCloudUnread();
|
||||
|
||||
_cloudUnread.known = true;
|
||||
}
|
||||
|
||||
void Folder::finalizeCloudUnread() {
|
||||
// Cloud state for archive folder always counts everything as muted.
|
||||
_cloudUnread.messagesMuted = _cloudUnread.messages;
|
||||
_cloudUnread.chatsMuted = _cloudUnread.chats;
|
||||
|
||||
// We don't know the real value of marked chats counts in _cloudUnread.
|
||||
_cloudUnread.marksMuted = _cloudUnread.marks = 0;
|
||||
}
|
||||
|
||||
Dialogs::UnreadState Folder::chatListUnreadState() const {
|
||||
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 in _cloudUnread.
|
||||
result.marksMuted = result.marks = localUnread.marks;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Folder::applyPinnedUpdate(const MTPDupdateDialogPinned &data) {
|
||||
const auto folderId = data.vfolder_id().value_or_empty();
|
||||
if (folderId != 0) {
|
||||
|
@ -390,48 +350,6 @@ void Folder::applyPinnedUpdate(const MTPDupdateDialogPinned &data) {
|
|||
owner().setChatPinned(this, data.is_pinned());
|
||||
}
|
||||
|
||||
void Folder::unreadStateChanged(
|
||||
const Dialogs::Key &key,
|
||||
const Dialogs::UnreadState &wasState,
|
||||
const Dialogs::UnreadState &nowState) {
|
||||
if (const auto history = key.history()) {
|
||||
if (wasState.empty() != nowState.empty()) {
|
||||
++_chatListViewVersion;
|
||||
updateChatListEntry();
|
||||
}
|
||||
}
|
||||
|
||||
const auto updateCloudUnread = _cloudUnread.known && wasState.known;
|
||||
const auto notify = _chatsList.loaded() || updateCloudUnread;
|
||||
const auto notifier = unreadStateChangeNotifier(notify);
|
||||
|
||||
_chatsList.unreadStateChanged(wasState, nowState);
|
||||
if (updateCloudUnread) {
|
||||
Assert(nowState.known);
|
||||
_cloudUnread += nowState - wasState;
|
||||
finalizeCloudUnread();
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::unreadEntryChanged(
|
||||
const Dialogs::Key &key,
|
||||
const Dialogs::UnreadState &state,
|
||||
bool added) {
|
||||
const auto updateCloudUnread = _cloudUnread.known && state.known;
|
||||
const auto notify = _chatsList.loaded() || updateCloudUnread;
|
||||
const auto notifier = unreadStateChangeNotifier(notify);
|
||||
|
||||
_chatsList.unreadEntryChanged(state, added);
|
||||
if (updateCloudUnread) {
|
||||
if (added) {
|
||||
_cloudUnread += state;
|
||||
} else {
|
||||
_cloudUnread -= state;
|
||||
}
|
||||
finalizeCloudUnread();
|
||||
}
|
||||
}
|
||||
|
||||
// #feed
|
||||
//MessagePosition Folder::unreadPosition() const {
|
||||
// return _unreadPosition.current();
|
||||
|
@ -457,6 +375,10 @@ int Folder::chatListUnreadCount() const {
|
|||
: state.chats);
|
||||
}
|
||||
|
||||
Dialogs::UnreadState Folder::chatListUnreadState() const {
|
||||
return _chatsList.unreadState();
|
||||
}
|
||||
|
||||
bool Folder::chatListUnreadMark() const {
|
||||
return false; // #feed unread mark
|
||||
}
|
||||
|
|
|
@ -45,16 +45,6 @@ public:
|
|||
//MessagePosition unreadPosition() const; // #feed
|
||||
//rpl::producer<MessagePosition> unreadPositionChanges() const; // #feed
|
||||
|
||||
void updateCloudUnread(const MTPDdialogFolder &data);
|
||||
void unreadStateChanged(
|
||||
const Dialogs::Key &key,
|
||||
const Dialogs::UnreadState &wasState,
|
||||
const Dialogs::UnreadState &nowState);
|
||||
void unreadEntryChanged(
|
||||
const Dialogs::Key &key,
|
||||
const Dialogs::UnreadState &state,
|
||||
bool added);
|
||||
|
||||
TimeId adjustedChatListTimeId() const override;
|
||||
|
||||
int fixedOnTopIndex() const override;
|
||||
|
@ -85,11 +75,6 @@ public:
|
|||
const style::color &overrideBg,
|
||||
const style::color &overrideFg) const;
|
||||
|
||||
bool chatsListLoaded() const;
|
||||
void setChatsListLoaded(bool loaded = true);
|
||||
void setCloudChatsListSize(int size);
|
||||
|
||||
int chatsListSize() const;
|
||||
const std::vector<not_null<History*>> &lastHistories() const;
|
||||
uint32 chatListViewVersion() const;
|
||||
|
||||
|
@ -99,7 +84,6 @@ private:
|
|||
void computeChatListMessage();
|
||||
|
||||
void reorderLastHistories();
|
||||
void finalizeCloudUnread();
|
||||
|
||||
void paintUserpic(
|
||||
Painter &p,
|
||||
|
@ -116,8 +100,6 @@ private:
|
|||
base::flat_set<QString> _nameWords;
|
||||
base::flat_set<QChar> _nameFirstLetters;
|
||||
|
||||
Dialogs::UnreadState _cloudUnread;
|
||||
int _cloudChatsListSize = 0;
|
||||
std::vector<not_null<History*>> _lastHistories;
|
||||
HistoryItem *_chatListMessage = nullptr;
|
||||
uint32 _chatListViewVersion = 0;
|
||||
|
|
|
@ -214,6 +214,11 @@ Session::Session(not_null<Main::Session*> session)
|
|||
setupChannelLeavingViewer();
|
||||
setupPeerNameViewer();
|
||||
setupUserIsContactViewer();
|
||||
|
||||
_chatsList.unreadStateChanges(
|
||||
) | rpl::start_with_next([] {
|
||||
Notify::unreadCounterUpdated();
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void Session::clear() {
|
||||
|
@ -833,7 +838,7 @@ void Session::chatsListChanged(Data::Folder *folder) {
|
|||
|
||||
void Session::chatsListDone(Data::Folder *folder) {
|
||||
if (folder) {
|
||||
folder->setChatsListLoaded();
|
||||
folder->chatsList()->setLoaded();
|
||||
} else {
|
||||
_chatsList.setLoaded();
|
||||
}
|
||||
|
@ -1506,7 +1511,7 @@ void Session::applyDialogs(
|
|||
});
|
||||
}
|
||||
if (requestFolder && count) {
|
||||
requestFolder->setCloudChatsListSize(*count);
|
||||
requestFolder->chatsList()->setCloudListSize(*count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2016,35 +2021,6 @@ bool Session::computeUnreadBadgeMuted(
|
|||
: (state.chatsMuted >= state.chats));
|
||||
}
|
||||
|
||||
void Session::unreadStateChanged(
|
||||
const Dialogs::Key &key,
|
||||
const Dialogs::UnreadState &wasState) {
|
||||
Expects(key.entry()->folderKnown());
|
||||
Expects(key.entry()->inChatList());
|
||||
|
||||
const auto nowState = key.entry()->chatListUnreadState();
|
||||
if (const auto folder = key.entry()->folder()) {
|
||||
folder->unreadStateChanged(key, wasState, nowState);
|
||||
} else {
|
||||
_chatsList.unreadStateChanged(wasState, nowState);
|
||||
}
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
|
||||
void Session::unreadEntryChanged(const Dialogs::Key &key, bool added) {
|
||||
Expects(key.entry()->folderKnown());
|
||||
|
||||
const auto state = key.entry()->chatListUnreadState();
|
||||
if (!state.empty()) {
|
||||
if (const auto folder = key.entry()->folder()) {
|
||||
folder->unreadEntryChanged(key, state, added);
|
||||
} else {
|
||||
_chatsList.unreadEntryChanged(state, added);
|
||||
}
|
||||
}
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
|
||||
void Session::selfDestructIn(not_null<HistoryItem*> item, crl::time delay) {
|
||||
_selfDestructItems.push_back(item->fullId());
|
||||
if (!_selfDestructTimer.isActive()
|
||||
|
@ -3347,33 +3323,42 @@ auto Session::refreshChatListEntry(
|
|||
Dialogs::Key key,
|
||||
FilterId filterIdForResult)
|
||||
-> RefreshChatListEntryResult {
|
||||
Expects(key.entry()->folderKnown());
|
||||
|
||||
using namespace Dialogs;
|
||||
|
||||
const auto entry = key.entry();
|
||||
const auto history = key.history();
|
||||
const auto mainList = chatsList(entry->folder());
|
||||
auto mainListResult = RefreshChatListEntryResult();
|
||||
mainListResult.changed = !entry->inChatList();
|
||||
if (mainListResult.changed) {
|
||||
const auto mainRow = entry->addToChatList(0);
|
||||
const auto mainRow = entry->addToChatList(0, mainList);
|
||||
_contactsNoChatsList.del(key, mainRow);
|
||||
} else {
|
||||
mainListResult.moved = entry->adjustByPosInChatList(0);
|
||||
mainListResult.moved = entry->adjustByPosInChatList(0, mainList);
|
||||
}
|
||||
auto result = filterIdForResult
|
||||
? RefreshChatListEntryResult()
|
||||
: mainListResult;
|
||||
if (!history) {
|
||||
return result;
|
||||
}
|
||||
for (const auto &filter : _chatsFilters->list()) {
|
||||
const auto id = filter.id();
|
||||
const auto filterList = chatsFilters().chatsList(id);
|
||||
auto filterResult = RefreshChatListEntryResult();
|
||||
if (history && filter.contains(history)) {
|
||||
if (filter.contains(history)) {
|
||||
filterResult.changed = !entry->inChatList(id);
|
||||
if (filterResult.changed) {
|
||||
entry->addToChatList(id);
|
||||
entry->addToChatList(id, filterList);
|
||||
} else {
|
||||
filterResult.moved = entry->adjustByPosInChatList(id);
|
||||
filterResult.moved = entry->adjustByPosInChatList(
|
||||
id,
|
||||
filterList);
|
||||
}
|
||||
} else if (entry->inChatList(id)) {
|
||||
entry->removeFromChatList(id);
|
||||
entry->removeFromChatList(id, filterList);
|
||||
filterResult.changed = true;
|
||||
}
|
||||
if (id == filterIdForResult) {
|
||||
|
@ -3387,9 +3372,17 @@ void Session::removeChatListEntry(Dialogs::Key key) {
|
|||
using namespace Dialogs;
|
||||
|
||||
const auto entry = key.entry();
|
||||
entry->removeFromChatList(0);
|
||||
if (!entry->inChatList()) {
|
||||
return;
|
||||
}
|
||||
Assert(entry->folderKnown());
|
||||
const auto mainList = chatsList(entry->folder());
|
||||
entry->removeFromChatList(0, mainList);
|
||||
for (const auto &filter : _chatsFilters->list()) {
|
||||
entry->removeFromChatList(filter.id());
|
||||
const auto id = filter.id();
|
||||
if (entry->inChatList(id)) {
|
||||
entry->removeFromChatList(id, chatsFilters().chatsList(id));
|
||||
}
|
||||
}
|
||||
if (_contactsList.contains(key)) {
|
||||
if (!_contactsNoChatsList.contains(key)) {
|
||||
|
|
|
@ -449,11 +449,6 @@ public:
|
|||
bool unreadBadgeMutedIgnoreOne(const Dialogs::Key &key) const;
|
||||
int unreadOnlyMutedBadge() const;
|
||||
|
||||
void unreadStateChanged(
|
||||
const Dialogs::Key &key,
|
||||
const Dialogs::UnreadState &wasState);
|
||||
void unreadEntryChanged(const Dialogs::Key &key, bool added);
|
||||
|
||||
void selfDestructIn(not_null<HistoryItem*> item, crl::time delay);
|
||||
|
||||
[[nodiscard]] not_null<PhotoData*> photo(PhotoId id);
|
||||
|
|
|
@ -112,7 +112,15 @@ void Entry::updateChatListExistence() {
|
|||
}
|
||||
|
||||
void Entry::notifyUnreadStateChange(const UnreadState &wasState) {
|
||||
owner().unreadStateChanged(_key, wasState);
|
||||
Expects(folderKnown());
|
||||
Expects(inChatList());
|
||||
|
||||
const auto nowState = chatListUnreadState();
|
||||
owner().chatsList(folder())->unreadStateChanged(wasState, nowState);
|
||||
auto &filters = owner().chatsFilters();
|
||||
for (const auto &[filterId, links] : _chatListLinks) {
|
||||
filters.chatsList(filterId)->unreadStateChanged(wasState, nowState);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::setChatListExistence(bool exists) {
|
||||
|
@ -154,11 +162,13 @@ Row *Entry::maybeMainChatListLink(FilterId filterId) const {
|
|||
return links ? links->main.get() : nullptr;
|
||||
}
|
||||
|
||||
PositionChange Entry::adjustByPosInChatList(FilterId filterId) {
|
||||
PositionChange Entry::adjustByPosInChatList(
|
||||
FilterId filterId,
|
||||
not_null<MainList*> list) {
|
||||
const auto links = chatListLinks(filterId);
|
||||
Assert(links != nullptr);
|
||||
const auto from = links->main->pos();
|
||||
myChatsList(filterId)->adjustByDate(*links);
|
||||
list->indexed()->adjustByDate(*links);
|
||||
const auto to = links->main->pos();
|
||||
return { from, to };
|
||||
}
|
||||
|
@ -175,30 +185,27 @@ int Entry::posInChatList(FilterId filterId) const {
|
|||
return mainChatListLink(filterId)->pos();
|
||||
}
|
||||
|
||||
not_null<Row*> Entry::addToChatList(FilterId filterId) {
|
||||
not_null<Row*> Entry::addToChatList(
|
||||
FilterId filterId,
|
||||
not_null<MainList*> list) {
|
||||
if (const auto main = maybeMainChatListLink(filterId)) {
|
||||
return main;
|
||||
}
|
||||
const auto result = _chatListLinks.emplace(
|
||||
return _chatListLinks.emplace(
|
||||
filterId,
|
||||
myChatsList(filterId)->addToEnd(_key)
|
||||
list->addEntry(_key)
|
||||
).first->second.main;
|
||||
if (!filterId) {
|
||||
owner().unreadEntryChanged(_key, true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Entry::removeFromChatList(FilterId filterId) {
|
||||
void Entry::removeFromChatList(
|
||||
FilterId filterId,
|
||||
not_null<MainList*> list) {
|
||||
const auto i = _chatListLinks.find(filterId);
|
||||
if (i == end(_chatListLinks)) {
|
||||
return;
|
||||
}
|
||||
myChatsList(filterId)->del(_key);
|
||||
_chatListLinks.erase(i);
|
||||
if (!filterId) {
|
||||
owner().unreadEntryChanged(_key, false);
|
||||
}
|
||||
list->removeEntry(_key);
|
||||
}
|
||||
|
||||
void Entry::removeChatListEntryByLetter(FilterId filterId, QChar letter) {
|
||||
|
@ -230,10 +237,4 @@ void Entry::updateChatListEntry() const {
|
|||
}
|
||||
}
|
||||
|
||||
not_null<IndexedList*> Entry::myChatsList(FilterId filterId) const {
|
||||
return filterId
|
||||
? owner().chatsFilters().chatsList(filterId)->indexed()
|
||||
: owner().chatsList(folder())->indexed();
|
||||
}
|
||||
|
||||
} // namespace Dialogs
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Dialogs {
|
|||
|
||||
class Row;
|
||||
class IndexedList;
|
||||
class MainList;
|
||||
|
||||
struct RowsByLetter {
|
||||
not_null<Row*> main;
|
||||
|
@ -97,13 +98,19 @@ public:
|
|||
[[nodiscard]] Data::Session &owner() const;
|
||||
[[nodiscard]] Main::Session &session() const;
|
||||
|
||||
PositionChange adjustByPosInChatList(FilterId filterId);
|
||||
PositionChange adjustByPosInChatList(
|
||||
FilterId filterId,
|
||||
not_null<MainList*> list);
|
||||
[[nodiscard]] bool inChatList(FilterId filterId = 0) const {
|
||||
return _chatListLinks.contains(filterId);
|
||||
}
|
||||
[[nodiscard]] int posInChatList(FilterId filterId) const;
|
||||
not_null<Row*> addToChatList(FilterId filterId);
|
||||
void removeFromChatList(FilterId filterId);
|
||||
not_null<Row*> addToChatList(
|
||||
FilterId filterId,
|
||||
not_null<MainList*> list);
|
||||
void removeFromChatList(
|
||||
FilterId filterId,
|
||||
not_null<MainList*> list);
|
||||
void removeChatListEntryByLetter(FilterId filterId, QChar letter);
|
||||
void addChatListEntryByLetter(
|
||||
FilterId filterId,
|
||||
|
@ -176,6 +183,7 @@ public:
|
|||
mutable Ui::Text::String lastItemTextCache;
|
||||
|
||||
protected:
|
||||
void notifyUnreadStateChange(const UnreadState &wasState);
|
||||
auto unreadStateChangeNotifier(bool required) {
|
||||
const auto notify = required && inChatList();
|
||||
const auto wasState = notify ? chatListUnreadState() : UnreadState();
|
||||
|
@ -189,16 +197,12 @@ protected:
|
|||
private:
|
||||
virtual void changedChatListPinHook();
|
||||
|
||||
void notifyUnreadStateChange(const UnreadState &wasState);
|
||||
|
||||
void setChatListExistence(bool exists);
|
||||
RowsByLetter *chatListLinks(FilterId filterId);
|
||||
const RowsByLetter *chatListLinks(FilterId filterId) const;
|
||||
not_null<Row*> mainChatListLink(FilterId filterId) const;
|
||||
Row *maybeMainChatListLink(FilterId filterId) const;
|
||||
|
||||
not_null<IndexedList*> myChatsList(FilterId filterId) const;
|
||||
|
||||
not_null<Data::Session*> _owner;
|
||||
Dialogs::Key _key;
|
||||
base::flat_map<FilterId, RowsByLetter> _chatListLinks;
|
||||
|
|
|
@ -1728,7 +1728,9 @@ void InnerWidget::fillSupportSearchMenu(not_null<Ui::PopupMenu*> menu) {
|
|||
|
||||
void InnerWidget::fillArchiveSearchMenu(not_null<Ui::PopupMenu*> menu) {
|
||||
const auto folder = session().data().folderLoaded(Data::Folder::kId);
|
||||
if (!folder || !folder->chatsListSize() || _searchInChat) {
|
||||
if (!folder
|
||||
|| !folder->chatsList()->fullSize().current()
|
||||
|| _searchInChat) {
|
||||
return;
|
||||
}
|
||||
const auto skip = session().settings().skipArchiveInSearch();
|
||||
|
|
|
@ -42,32 +42,149 @@ bool MainList::loaded() const {
|
|||
}
|
||||
|
||||
void MainList::setLoaded(bool loaded) {
|
||||
if (_loaded == loaded) {
|
||||
return;
|
||||
}
|
||||
const auto notifier = unreadStateChangeNotifier(true);
|
||||
_loaded = loaded;
|
||||
recomputeFullListSize();
|
||||
}
|
||||
|
||||
void MainList::setAllAreMuted(bool allAreMuted) {
|
||||
if (_allAreMuted == allAreMuted) {
|
||||
return;
|
||||
}
|
||||
const auto notifier = unreadStateChangeNotifier(true);
|
||||
_allAreMuted = allAreMuted;
|
||||
}
|
||||
|
||||
void MainList::setCloudListSize(int size) {
|
||||
if (_cloudListSize == size) {
|
||||
return;
|
||||
}
|
||||
_cloudListSize = size;
|
||||
recomputeFullListSize();
|
||||
}
|
||||
|
||||
const rpl::variable<int> &MainList::fullSize() const {
|
||||
return _fullListSize;
|
||||
}
|
||||
|
||||
void MainList::clear() {
|
||||
const auto notifier = unreadStateChangeNotifier(true);
|
||||
_all.clear();
|
||||
_unreadState = UnreadState();
|
||||
_cloudUnreadState = UnreadState();
|
||||
_unreadState.known = true;
|
||||
_cloudUnreadState.known = true;
|
||||
_cloudListSize = 0;
|
||||
recomputeFullListSize();
|
||||
}
|
||||
|
||||
RowsByLetter MainList::addEntry(const Key &key) {
|
||||
const auto result = _all.addToEnd(key);
|
||||
|
||||
const auto unread = key.entry()->chatListUnreadState();
|
||||
unreadEntryChanged(unread, true);
|
||||
recomputeFullListSize();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MainList::removeEntry(const Key &key) {
|
||||
_all.del(key);
|
||||
|
||||
const auto unread = key.entry()->chatListUnreadState();
|
||||
unreadEntryChanged(unread, false);
|
||||
recomputeFullListSize();
|
||||
}
|
||||
|
||||
void MainList::recomputeFullListSize() {
|
||||
_fullListSize = std::max(_all.size(), loaded() ? 0 : _cloudListSize);
|
||||
}
|
||||
|
||||
void MainList::unreadStateChanged(
|
||||
const UnreadState &wasState,
|
||||
const UnreadState &nowState) {
|
||||
const auto updateCloudUnread = _cloudUnreadState.known && wasState.known;
|
||||
const auto notify = loaded() || updateCloudUnread;
|
||||
const auto notifier = unreadStateChangeNotifier(notify);
|
||||
_unreadState += nowState - wasState;
|
||||
if (updateCloudUnread) {
|
||||
Assert(nowState.known);
|
||||
_cloudUnreadState += nowState - wasState;
|
||||
finalizeCloudUnread();
|
||||
}
|
||||
}
|
||||
|
||||
void MainList::unreadEntryChanged(
|
||||
const Dialogs::UnreadState &state,
|
||||
bool added) {
|
||||
if (state.empty()) {
|
||||
return;
|
||||
}
|
||||
const auto updateCloudUnread = _cloudUnreadState.known && state.known;
|
||||
const auto notify = loaded() || updateCloudUnread;
|
||||
const auto notifier = unreadStateChangeNotifier(notify);
|
||||
if (added) {
|
||||
_unreadState += state;
|
||||
} else {
|
||||
_unreadState -= state;
|
||||
}
|
||||
if (updateCloudUnread) {
|
||||
if (added) {
|
||||
_cloudUnreadState += state;
|
||||
} else {
|
||||
_cloudUnreadState -= state;
|
||||
}
|
||||
finalizeCloudUnread();
|
||||
}
|
||||
}
|
||||
|
||||
void MainList::updateCloudUnread(const MTPDdialogFolder &data) {
|
||||
const auto notifier = unreadStateChangeNotifier(!loaded());
|
||||
|
||||
_cloudUnreadState.messages = data.vunread_muted_messages_count().v
|
||||
+ data.vunread_unmuted_messages_count().v;
|
||||
_cloudUnreadState.chats = data.vunread_muted_peers_count().v
|
||||
+ data.vunread_unmuted_peers_count().v;
|
||||
finalizeCloudUnread();
|
||||
|
||||
_cloudUnreadState.known = true;
|
||||
}
|
||||
|
||||
bool MainList::cloudUnreadKnown() const {
|
||||
return _cloudUnreadState.known;
|
||||
}
|
||||
|
||||
void MainList::finalizeCloudUnread() {
|
||||
// Cloud state for archive folder always counts everything as muted.
|
||||
_cloudUnreadState.messagesMuted = _cloudUnreadState.messages;
|
||||
_cloudUnreadState.chatsMuted = _cloudUnreadState.chats;
|
||||
|
||||
// We don't know the real value of marked chats counts in cloud unread.
|
||||
_cloudUnreadState.marksMuted = _cloudUnreadState.marks = 0;
|
||||
}
|
||||
|
||||
UnreadState MainList::unreadState() const {
|
||||
return _unreadState;
|
||||
const auto useCloudState = _cloudUnreadState.known && !loaded();
|
||||
auto result = useCloudState ? _cloudUnreadState : _unreadState;
|
||||
|
||||
// We don't know the real value of marked chats counts in cloud unread.
|
||||
if (useCloudState) {
|
||||
result.marks = _unreadState.marks;
|
||||
result.marksMuted = _unreadState.marksMuted;
|
||||
}
|
||||
if (_allAreMuted) {
|
||||
result.messagesMuted = result.messages;
|
||||
result.chatsMuted = result.chats;
|
||||
result.marksMuted = result.marks;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
rpl::producer<UnreadState> MainList::unreadStateChanges() const {
|
||||
return _unreadStateChanges.events();
|
||||
}
|
||||
|
||||
not_null<IndexedList*> MainList::indexed() {
|
||||
|
|
|
@ -19,28 +19,55 @@ public:
|
|||
bool empty() const;
|
||||
bool loaded() const;
|
||||
void setLoaded(bool loaded = true);
|
||||
void setAllAreMuted(bool allAreMuted = true);
|
||||
void clear();
|
||||
|
||||
RowsByLetter addEntry(const Key &key);
|
||||
void removeEntry(const Key &key);
|
||||
|
||||
void unreadStateChanged(
|
||||
const UnreadState &wasState,
|
||||
const UnreadState &nowState);
|
||||
void unreadEntryChanged(
|
||||
const Dialogs::UnreadState &state,
|
||||
bool added);
|
||||
void updateCloudUnread(const MTPDdialogFolder &data);
|
||||
[[nodiscard]] bool cloudUnreadKnown() const;
|
||||
[[nodiscard]] UnreadState unreadState() const;
|
||||
[[nodiscard]] rpl::producer<UnreadState> unreadStateChanges() const;
|
||||
|
||||
not_null<IndexedList*> indexed();
|
||||
not_null<const IndexedList*> indexed() const;
|
||||
not_null<PinnedList*> pinned();
|
||||
not_null<const PinnedList*> pinned() const;
|
||||
[[nodiscard]] not_null<IndexedList*> indexed();
|
||||
[[nodiscard]] not_null<const IndexedList*> indexed() const;
|
||||
[[nodiscard]] not_null<PinnedList*> pinned();
|
||||
[[nodiscard]] not_null<const PinnedList*> pinned() const;
|
||||
|
||||
void setCloudListSize(int size);
|
||||
[[nodiscard]] const rpl::variable<int> &fullSize() const;
|
||||
|
||||
private:
|
||||
void finalizeCloudUnread();
|
||||
void recomputeFullListSize();
|
||||
|
||||
auto unreadStateChangeNotifier(bool notify) {
|
||||
const auto wasState = notify ? unreadState() : UnreadState();
|
||||
return gsl::finally([=] {
|
||||
if (notify) {
|
||||
_unreadStateChanges.fire_copy(wasState);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
FilterId _filterId = 0;
|
||||
IndexedList _all;
|
||||
PinnedList _pinned;
|
||||
UnreadState _unreadState;
|
||||
UnreadState _cloudUnreadState;
|
||||
rpl::event_stream<UnreadState> _unreadStateChanges;
|
||||
rpl::variable<int> _fullListSize = 0;
|
||||
int _cloudListSize = 0;
|
||||
|
||||
bool _loaded = false;
|
||||
bool _allAreMuted = false;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ QString ComposeFolderListEntryText(not_null<Data::Folder*> folder) {
|
|||
|
||||
const auto count = std::max(
|
||||
int(list.size()),
|
||||
folder->chatsListSize());
|
||||
folder->chatsList()->fullSize().current());
|
||||
|
||||
const auto throwAwayLastName = (list.size() > 1)
|
||||
&& (count == list.size() + 1);
|
||||
|
|
|
@ -280,7 +280,7 @@ Widget::Widget(
|
|||
onSearchMore();
|
||||
} else {
|
||||
const auto folder = _inner->shownFolder();
|
||||
if (!folder || !folder->chatsListLoaded()) {
|
||||
if (!folder || !folder->chatsList()->loaded()) {
|
||||
session().api().requestDialogs(folder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1924,12 +1924,16 @@ void History::setFolderPointer(Data::Folder *folder) {
|
|||
if (isPinnedDialog()) {
|
||||
owner().setChatPinned(this, false);
|
||||
}
|
||||
auto &filters = owner().chatsFilters();
|
||||
const auto wasKnown = folderKnown();
|
||||
const auto wasInList = inChatList();
|
||||
if (wasInList) {
|
||||
removeFromChatList(0);
|
||||
for (const auto &filter : owner().chatsFilters().list()) {
|
||||
removeFromChatList(filter.id());
|
||||
removeFromChatList(0, owner().chatsList(this->folder()));
|
||||
for (const auto &filter : filters.list()) {
|
||||
const auto id = filter.id();
|
||||
if (inChatList(id)) {
|
||||
removeFromChatList(id, filters.chatsList(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto was = _folder.value_or(nullptr);
|
||||
|
@ -1938,10 +1942,11 @@ void History::setFolderPointer(Data::Folder *folder) {
|
|||
was->unregisterOne(this);
|
||||
}
|
||||
if (wasInList) {
|
||||
addToChatList(0);
|
||||
for (const auto &filter : owner().chatsFilters().list()) {
|
||||
addToChatList(0, owner().chatsList(folder));
|
||||
for (const auto &filter : filters.list()) {
|
||||
if (filter.contains(this)) {
|
||||
addToChatList(filter.id());
|
||||
const auto id = filter.id();
|
||||
addToChatList(id, filters.chatsList(id));
|
||||
}
|
||||
}
|
||||
owner().chatsListChanged(was);
|
||||
|
|
Loading…
Reference in New Issue