/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "dialogs/dialogs_main_list.h" #include "data/data_changes.h" #include "main/main_session.h" #include "history/history.h" namespace Dialogs { MainList::MainList( not_null session, FilterId filterId, rpl::producer pinnedLimit) : _filterId(filterId) , _all(SortMode::Date, filterId) , _pinned(filterId, 1) { _unreadState.known = true; std::move( pinnedLimit ) | rpl::start_with_next([=](int limit) { _pinned.setLimit(limit); }, _lifetime); session->changes().realtimeNameUpdates( ) | rpl::start_with_next([=](const Data::NameUpdate &update) { _all.peerNameChanged(_filterId, update.peer, update.oldFirstLetters); }, _lifetime); } bool MainList::empty() const { return _all.empty(); } bool MainList::loaded() const { return _loaded; } void MainList::setLoaded(bool loaded) { if (_loaded == loaded) { return; } const auto recomputer = gsl::finally([&] { recomputeFullListSize(); }); const auto notifier = unreadStateChangeNotifier(true); _loaded = loaded; } 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 &MainList::fullSize() const { return _fullListSize; } void MainList::clear() { const auto recomputer = gsl::finally([&] { recomputeFullListSize(); }); const auto notifier = unreadStateChangeNotifier(true); _all.clear(); _unreadState = UnreadState(); _cloudUnreadState = UnreadState(); _unreadState.known = true; _cloudUnreadState.known = true; _cloudListSize = 0; } 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 useClouded = _cloudUnreadState.known && !loaded(); const auto updateCloudUnread = _cloudUnreadState.known && wasState.known; const auto notify = !useClouded || wasState.known; 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 = !_cloudUnreadState.known || loaded() || state.known; 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 { 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 MainList::unreadStateChanges() const { return _unreadStateChanges.events(); } not_null MainList::indexed() { return &_all; } not_null MainList::indexed() const { return &_all; } not_null MainList::pinned() { return &_pinned; } not_null MainList::pinned() const { return &_pinned; } } // namespace Dialogs