diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index d0354e293..fdca1a629 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -853,6 +853,7 @@ auto ApiWrap::dialogsLoadState(FolderId folderId) -> DialogsLoadState* { void ApiWrap::dialogsLoadFinish(FolderId folderId) { if (folderId) { + _session->data().folder(folderId)->setChatsListLoaded(true); _foldersLoadState.remove(folderId); } else { _dialogsLoadState = nullptr; diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index 3315dabb3..e7dd60c69 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -258,12 +258,12 @@ void ChatsListBoxController::rebuildRows() { ++added; } } - added += appendList(Auth().data().chatsList()); + added += appendList(Auth().data().chatsList(Dialogs::Mode::All)); added += appendList(Auth().data().contactsNoChatsList()); if (!wasEmpty && added > 0) { // Place dialogs list before contactsNoDialogs list. delegate()->peerListPartitionRows([](const PeerListRow &a) { - auto history = static_cast(a).history(); + const auto history = static_cast(a).history(); return history->inChatList(Dialogs::Mode::All); }); if (respectSavedMessagesChat()) { diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp index 359ebd9cb..8dad27891 100644 --- a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp @@ -1079,7 +1079,8 @@ void AddSpecialBoxSearchController::addChatsContacts() { } return result; }; - const auto dialogsIndex = getSmallestIndex(_peer->owner().chatsList()); + const auto dialogsIndex = getSmallestIndex( + _peer->owner().chatsList(Dialogs::Mode::All)); const auto contactsIndex = getSmallestIndex( _peer->owner().contactsNoChatsList()); diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 8562ad57e..24e714374 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -489,7 +489,7 @@ ShareBox::Inner::Inner( _rowHeight = st::shareRowHeight; setAttribute(Qt::WA_OpaquePaintEvent); - const auto dialogs = Auth().data().chatsList(); + const auto dialogs = Auth().data().chatsList(Dialogs::Mode::All); const auto self = Auth().user(); if (_filterCallback(self)) { _chatsIndexed->addToEnd(self->owner().history(self)); diff --git a/Telegram/SourceFiles/data/data_folder.cpp b/Telegram/SourceFiles/data/data_folder.cpp index 3e5b48574..9b3a1a81f 100644 --- a/Telegram/SourceFiles/data/data_folder.cpp +++ b/Telegram/SourceFiles/data/data_folder.cpp @@ -41,6 +41,7 @@ Folder::Folder(not_null owner, FolderId id) : Entry(owner, this) , _id(id) , _chatsList(Dialogs::SortMode::Date) +, _importantChatsList(Dialogs::SortMode::Date) , _name(lang(lng_archived_chats)) { indexNameParts(); } @@ -76,23 +77,9 @@ void Folder::indexNameParts() { } void Folder::registerOne(not_null history) { - if (_chatsList.contains(history)) { - return; - } - const auto invisible = _chatsList.empty(); - _chatsList.addToEnd(history); //session().storage().invalidate( // #feed // Storage::FeedMessagesInvalidate(_id)); - if (history->chatListMessageKnown()) { - if (const auto last = history->chatListMessage()) { - if (justUpdateChatListMessage(last)) { - updateChatListEntry(); - } - } - } else if (chatListMessageKnown()) { - history->requestChatListMessage(); - } if (unreadCountKnown()) { if (history->unreadCountKnown()) { // If history unreadCount is known that means that we've @@ -102,36 +89,20 @@ void Folder::registerOne(not_null history) { if (const auto count = history->unreadCount()) { unreadCountChanged(count, history->mute() ? count : 0); } - } else if (!_settingHistories) { + } else { session().api().requestDialogEntry(this); } } - if (invisible && !_chatsList.empty()) { + if (_chatsList.size() == 1) { updateChatListExistence(); - //for (const auto history : _histories) { // #TODO archived - // history->updateChatListExistence(); - //} - } else { - history->updateChatListExistence(); } owner().notifyFolderUpdated(this, FolderUpdateFlag::List); } void Folder::unregisterOne(not_null history) { - if (!_chatsList.contains(history)) { - return; - } - _chatsList.del(history); //session().storage().remove( // #feed // Storage::FeedMessagesRemoveAll(_id, channel->bareId())); - if (chatListMessageKnown()) { - if (const auto last = chatListMessage()) { - if (last->history() == history) { - recountChatListMessage(); - } - } - } if (unreadCountKnown()) { if (history->unreadCountKnown()) { if (const auto delta = -history->unreadCount()) { @@ -143,25 +114,14 @@ void Folder::unregisterOne(not_null history) { } if (_chatsList.empty()) { updateChatListExistence(); - //for (const auto history : _histories) { // #TODO archive - // history->updateChatListExistence(); - //} - } else { - history->updateChatListExistence(); } owner().notifyFolderUpdated(this, FolderUpdateFlag::List); } -not_null Folder::chatsList() { - return &_chatsList; -} - -void Folder::updateChatListMessage(not_null item) { - if (justUpdateChatListMessage(item)) { - if (_chatListMessage && *_chatListMessage) { - setChatListTimeId((*_chatListMessage)->date()); - } - } +not_null Folder::chatsList(Dialogs::Mode list) { + return (list == Dialogs::Mode::All) + ? &_chatsList + : &_importantChatsList; } void Folder::loadUserpic() { @@ -201,13 +161,13 @@ void Folder::paintUserpic( //} } -bool Folder::historiesLoaded() const { - return _historiesLoaded; +bool Folder::chatsListLoaded() const { + return _chatsListLoaded; } -void Folder::setHistoriesLoaded(bool loaded) { - if (_historiesLoaded != loaded) { - _historiesLoaded = loaded; +void Folder::setChatsListLoaded(bool loaded) { + if (_chatsListLoaded != loaded) { + _chatsListLoaded = loaded; owner().notifyFolderUpdated(this, FolderUpdateFlag::List); } } @@ -268,66 +228,12 @@ void Folder::setHistoriesLoaded(bool loaded) { // _chatListMessage = oldChatListMessage; //} -bool Folder::justUpdateChatListMessage(not_null item) { - if (!_chatListMessage) { - return false; - } else if (*_chatListMessage - && item->position() <= (*_chatListMessage)->position()) { - return false; - } - _chatListMessage = item; - return true; -} - -void Folder::messageRemoved(not_null item) { - if (chatListMessage() == item) { - recountChatListMessage(); - } -} - -void Folder::historyCleared(not_null history) { - if (const auto last = chatListMessage()) { - if (last->history() == history) { - messageRemoved(last); - } - } -} - void Folder::requestChatListMessage() { if (!chatListMessageKnown()) { session().api().requestDialogEntry(this); } } -void Folder::recountChatListMessage() { - _chatListMessage = std::nullopt; - for (const auto entry : _chatsList) { - if (entry->history() && !entry->history()->chatListMessageKnown()) { - requestChatListMessage(); - return; - } - } - setChatListMessageFromChannels(); -} - -void Folder::setChatListMessageFromChannels() { - _chatListMessage = nullptr; - for (const auto entry : _chatsList) { - if (entry->history()) { - if (const auto last = entry->history()->chatListMessage()) { - justUpdateChatListMessage(last); - } - } - } - updateChatListDate(); -} - -void Folder::updateChatListDate() { - if (_chatListMessage && *_chatListMessage) { - setChatListTimeId((*_chatListMessage)->date()); - } -} - int Folder::unreadCount() const { return _unreadCount ? *_unreadCount : 0; } @@ -352,17 +258,17 @@ void Folder::applyDialog(const MTPDdialogFolder &data) { // addChannel(channelId.v); //} - _chatListMessage = nullptr; if (const auto peerId = peerFromMTP(data.vpeer)) { - owner().history(peerId)->setFolder(this); + const auto history = owner().history(peerId); const auto fullId = FullMsgId( peerToChannel(peerId), data.vtop_message.v); - if (const auto item = App::histItemById(fullId)) { - justUpdateChatListMessage(item); - } + history->setFolder(this, App::histItemById(fullId)); + } else { + _chatsList.clear(); + _importantChatsList.clear(); + updateChatListExistence(); } - updateChatListDate(); setUnreadCounts( data.vunread_unmuted_messages_count.v, data.vunread_muted_messages_count.v); @@ -511,7 +417,7 @@ void Folder::unreadCountChanged(int unreadCountDelta, int mutedCountDelta) { //} bool Folder::toImportant() const { - return false; // TODO feeds workmode + return !_importantChatsList.empty(); } bool Folder::useProxyPromotion() const { @@ -535,11 +441,14 @@ bool Folder::chatListMutedBadge() const { } HistoryItem *Folder::chatListMessage() const { - return _chatListMessage ? *_chatListMessage : nullptr; + return _chatsList.empty() + ? nullptr + : (*_chatsList.begin())->key().entry()->chatListMessage(); } bool Folder::chatListMessageKnown() const { - return _chatListMessage.has_value(); + return _chatsList.empty() + || (*_chatsList.begin())->key().entry()->chatListMessageKnown(); } const QString &Folder::chatListName() const { diff --git a/Telegram/SourceFiles/data/data_folder.h b/Telegram/SourceFiles/data/data_folder.h index d13ceea35..daa455861 100644 --- a/Telegram/SourceFiles/data/data_folder.h +++ b/Telegram/SourceFiles/data/data_folder.h @@ -42,11 +42,7 @@ public: void registerOne(not_null history); void unregisterOne(not_null history); - not_null chatsList(); - - void updateChatListMessage(not_null item); - void messageRemoved(not_null item); - void historyCleared(not_null history); + not_null chatsList(Dialogs::Mode list); void applyDialog(const MTPDdialogFolder &data); void setUnreadCounts(int unreadNonMutedCount, int unreadMutedCount); @@ -86,17 +82,13 @@ public: int y, int size) const override; - bool historiesLoaded() const; - void setHistoriesLoaded(bool loaded); + bool chatsListLoaded() const; + void setChatsListLoaded(bool loaded); //int32 chatsHash() const; //void setChats(std::vector> chats); // #feed private: void indexNameParts(); - void recountChatListMessage(); - void setChatListMessageFromChannels(); - bool justUpdateChatListMessage(not_null item); - void updateChatListDate(); //void changeChatsList( // const std::vector> &add, // const std::vector> &remove); @@ -106,15 +98,14 @@ private: FolderId _id = 0; Dialogs::IndexedList _chatsList; - bool _settingHistories = false; - bool _historiesLoaded = false; + Dialogs::IndexedList _importantChatsList; + bool _chatsListLoaded = false; QString _name; base::flat_set _nameWords; base::flat_set _nameFirstLetters; - std::optional _chatListMessage; - rpl::variable _unreadPosition; + //rpl::variable _unreadPosition; std::optional _unreadCount; rpl::event_stream _unreadCountChanges; int _unreadMutedCount = 0; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 460b3c226..656cc00de 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -2949,12 +2949,10 @@ not_null Session::processFolder(const MTPDfolder &data) { // return _defaultFeedId.value(); //} -not_null Session::chatsList() { - return &_chatsList; -} - -not_null Session::importantChatsList() { - return &_importantChatsList; +not_null Session::chatsList(Dialogs::Mode list) { + return (list == Dialogs::Mode::All) + ? &_chatsList + : &_importantChatsList; } not_null Session::contactsList() { @@ -2973,25 +2971,22 @@ auto Session::refreshChatListEntry(Dialogs::Key key) auto result = RefreshChatListEntryResult(); result.changed = !entry->inChatList(Mode::All); if (result.changed) { - const auto mainRow = entry->addToChatList(Mode::All, &_chatsList); + const auto mainRow = entry->addToChatList(Mode::All); _contactsNoChatsList.del(key, mainRow); } else { - result.moved = entry->adjustByPosInChatList( - Mode::All, - &_chatsList); + result.moved = entry->adjustByPosInChatList(Mode::All); } if (Global::DialogsModeEnabled()) { if (entry->toImportant()) { result.importantChanged = !entry->inChatList(Mode::Important); if (result.importantChanged) { - entry->addToChatList(Mode::Important, &_importantChatsList); + entry->addToChatList(Mode::Important); } else { result.importantMoved = entry->adjustByPosInChatList( - Mode::Important, - &_importantChatsList); + Mode::Important); } } else if (entry->inChatList(Mode::Important)) { - entry->removeFromChatList(Mode::Important, &_importantChatsList); + entry->removeFromChatList(Mode::Important); result.importantChanged = true; } } @@ -3002,9 +2997,9 @@ void Session::removeChatListEntry(Dialogs::Key key) { using namespace Dialogs; const auto entry = key.entry(); - entry->removeFromChatList(Mode::All, &_chatsList); + entry->removeFromChatList(Mode::All); if (Global::DialogsModeEnabled()) { - entry->removeFromChatList(Mode::Important, &_importantChatsList); + entry->removeFromChatList(Mode::Important); } if (_contactsList.contains(key)) { if (!_contactsNoChatsList.contains(key)) { diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 0492dea59..fd3235030 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -516,8 +516,7 @@ public: //FeedId defaultFeedId() const; //rpl::producer defaultFeedIdValue() const; - not_null chatsList(); - not_null importantChatsList(); + not_null chatsList(Dialogs::Mode list); not_null contactsList(); not_null contactsNoChatsList(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp index c5d865033..331b03857 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_key.h" #include "dialogs/dialogs_indexed_list.h" #include "data/data_session.h" +#include "data/data_folder.h" #include "mainwidget.h" #include "auth_session.h" #include "history/history_item.h" @@ -135,12 +136,10 @@ Row *Entry::mainChatListLink(Mode list) const { return it->second; } -PositionChange Entry::adjustByPosInChatList( - Mode list, - not_null indexed) { +PositionChange Entry::adjustByPosInChatList(Mode list) { const auto lnk = mainChatListLink(list); const auto from = lnk->pos(); - indexed->adjustByDate(chatListLinks(list)); + myChatsList(list)->adjustByDate(chatListLinks(list)); const auto to = lnk->pos(); return { from, to }; } @@ -159,21 +158,17 @@ int Entry::posInChatList(Dialogs::Mode list) const { return mainChatListLink(list)->pos(); } -not_null Entry::addToChatList( - Mode list, - not_null indexed) { +not_null Entry::addToChatList(Mode list) { if (!inChatList(list)) { - chatListLinks(list) = indexed->addToEnd(_key); + chatListLinks(list) = myChatsList(list)->addToEnd(_key); changedInChatListHook(list, true); } return mainChatListLink(list); } -void Entry::removeFromChatList( - Dialogs::Mode list, - not_null indexed) { +void Entry::removeFromChatList(Dialogs::Mode list) { if (inChatList(list)) { - indexed->del(_key); + myChatsList(list)->del(_key); chatListLinks(list).clear(); changedInChatListHook(list, false); } @@ -217,4 +212,11 @@ void Entry::updateChatListEntry() const { } } +not_null Entry::myChatsList(Mode list) const { + if (const auto current = folder()) { + return current->chatsList(list); + } + return owner().chatsList(list); +} + } // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.h b/Telegram/SourceFiles/dialogs/dialogs_entry.h index a73cd9d25..0148006e3 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.h +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.h @@ -15,6 +15,7 @@ class AuthSession; namespace Data { class Session; +class Folder; } // namespace Data namespace Dialogs { @@ -49,15 +50,13 @@ public: Data::Session &owner() const; AuthSession &session() const; - PositionChange adjustByPosInChatList( - Mode list, - not_null indexed); + PositionChange adjustByPosInChatList(Mode list); bool inChatList(Mode list) const { return !chatListLinks(list).empty(); } int posInChatList(Mode list) const; - not_null addToChatList(Mode list, not_null indexed); - void removeFromChatList(Mode list, not_null indexed); + not_null addToChatList(Mode list); + void removeFromChatList(Mode list); void removeChatListEntryByLetter(Mode list, QChar letter); void addChatListEntryByLetter( Mode list, @@ -93,6 +92,10 @@ public: virtual const base::flat_set &chatListNameWords() const = 0; virtual const base::flat_set &chatListFirstLetters() const = 0; + virtual Data::Folder *folder() const { + return nullptr; + } + virtual void loadUserpic() = 0; virtual void paintUserpic( Painter &p, @@ -117,7 +120,7 @@ public: private: virtual TimeId adjustChatListTimeId() const; - virtual void changedInChatListHook(Dialogs::Mode list, bool added); + virtual void changedInChatListHook(Mode list, bool added); virtual void changedChatListPinHook(); void setChatListExistence(bool exists); @@ -125,6 +128,8 @@ private: const RowsByLetter &chatListLinks(Mode list) const; Row *mainChatListLink(Mode list) const; + not_null myChatsList(Mode list) const; + not_null _owner; Dialogs::Key _key; RowsByLetter _chatListLinks[2]; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 522450b3b..81d4583f5 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -249,11 +249,11 @@ int DialogsInner::searchInChatSkip() const { } bool DialogsInner::cancelFolder() { - if (!_folderChatsList) { + if (!_openedFolder) { return false; } clearSelection(); - _folderChatsList = nullptr; + _openedFolder = nullptr; refresh(); return true; } @@ -1471,11 +1471,9 @@ void DialogsInner::updateSelectedRow(Dialogs::Key key) { } not_null DialogsInner::shownDialogs() const { - return _folderChatsList - ? _folderChatsList - : (Global::DialogsMode() == Dialogs::Mode::Important) - ? session().data().importantChatsList().get() - : session().data().chatsList().get(); + return _openedFolder + ? _openedFolder->chatsList(Global::DialogsMode()) + : session().data().chatsList(Global::DialogsMode()); } void DialogsInner::leaveEventHook(QEvent *e) { @@ -1609,7 +1607,7 @@ void DialogsInner::applyFilterUpdate(QString newFilter, bool force) { _filterResultsGlobal.clear(); if (!_searchInChat && !words.isEmpty()) { const Dialogs::List *toFilter = nullptr; - if (const auto list = session().data().chatsList(); !list->empty()) { + if (const auto list = session().data().chatsList(Dialogs::Mode::All); !list->empty()) { for (fi = fb; fi != fe; ++fi) { const auto found = list->filtered(fi->at(0)); if (!found || found->empty()) { @@ -2409,7 +2407,7 @@ bool DialogsInner::chooseRow() { : chosen.message.fullId.msg)); } else if (const auto folder = chosen.key.folder()) { clearSelection(); - _folderChatsList = folder->chatsList(); + _openedFolder = folder; refresh(); } if (openSearchResult && !session().supportMode()) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index 1be1ebd7b..03ca7e507 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -282,7 +282,7 @@ private: std::optional _lastMousePosition; Qt::MouseButton _pressButton = Qt::LeftButton; - Dialogs::IndexedList *_folderChatsList = nullptr; + Data::Folder *_openedFolder = nullptr; std::unique_ptr _importantSwitch; bool _importantSwitchSelected = false; bool _importantSwitchPressed = false; diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 6df80b744..4bf29ec37 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -1810,8 +1810,13 @@ Data::Folder *History::folder() const { return _folder; } -void History::setFolder(not_null folder) { +void History::setFolder( + not_null folder, + HistoryItem *folderDialogItem) { setFolderPointer(folder); + if (folderDialogItem && _lastMessage != folderDialogItem) { + setLastMessage(folderDialogItem); + } } void History::clearFolder() { @@ -1819,16 +1824,30 @@ void History::clearFolder() { } void History::setFolderPointer(Data::Folder *folder) { - if (_folder != folder) { - const auto was = _folder; - _folder = folder; - if (was) { - was->unregisterOne(this); - } - if (_folder) { - _folder->registerOne(this); - } - updateChatListSortPosition(); + if (_folder == folder) { + return; + } + using Mode = Dialogs::Mode; + const auto wasAll = inChatList(Mode::All); + const auto wasImportant = inChatList(Mode::Important); + if (wasAll) { + removeFromChatList(Mode::All); + } + if (wasImportant) { + removeFromChatList(Mode::Important); + } + const auto was = std::exchange(_folder, folder); + if (was) { + was->unregisterOne(this); + } + if (wasAll) { + addToChatList(Mode::All); + } + if (wasImportant) { + addToChatList(Mode::Important); + } + if (_folder) { + _folder->registerOne(this); } } diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index d333fb6e8..8b14ec38a 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -323,8 +323,10 @@ public: std::shared_ptr adminLogIdManager(); - Data::Folder *folder() const; - void setFolder(not_null folder); + Data::Folder *folder() const override; + void setFolder( + not_null folder, + HistoryItem *folderDialogItem = nullptr); void clearFolder(); // Still public data.