Correctly move histories between chat lists.

This commit is contained in:
John Preston 2019-04-17 17:22:37 +04:00
parent 0367319934
commit c58f097535
14 changed files with 115 additions and 193 deletions

View File

@ -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;

View File

@ -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<const Row&>(a).history();
const auto history = static_cast<const Row&>(a).history();
return history->inChatList(Dialogs::Mode::All);
});
if (respectSavedMessagesChat()) {

View File

@ -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());

View File

@ -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));

View File

@ -41,6 +41,7 @@ Folder::Folder(not_null<Data::Session*> 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*> 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*> 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*> 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*> history) {
}
if (_chatsList.empty()) {
updateChatListExistence();
//for (const auto history : _histories) { // #TODO archive
// history->updateChatListExistence();
//}
} else {
history->updateChatListExistence();
}
owner().notifyFolderUpdated(this, FolderUpdateFlag::List);
}
not_null<Dialogs::IndexedList*> Folder::chatsList() {
return &_chatsList;
}
void Folder::updateChatListMessage(not_null<HistoryItem*> item) {
if (justUpdateChatListMessage(item)) {
if (_chatListMessage && *_chatListMessage) {
setChatListTimeId((*_chatListMessage)->date());
}
}
not_null<Dialogs::IndexedList*> 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<HistoryItem*> item) {
if (!_chatListMessage) {
return false;
} else if (*_chatListMessage
&& item->position() <= (*_chatListMessage)->position()) {
return false;
}
_chatListMessage = item;
return true;
}
void Folder::messageRemoved(not_null<HistoryItem*> item) {
if (chatListMessage() == item) {
recountChatListMessage();
}
}
void Folder::historyCleared(not_null<History*> 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 {

View File

@ -42,11 +42,7 @@ public:
void registerOne(not_null<History*> history);
void unregisterOne(not_null<History*> history);
not_null<Dialogs::IndexedList*> chatsList();
void updateChatListMessage(not_null<HistoryItem*> item);
void messageRemoved(not_null<HistoryItem*> item);
void historyCleared(not_null<History*> history);
not_null<Dialogs::IndexedList*> 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<not_null<PeerData*>> chats); // #feed
private:
void indexNameParts();
void recountChatListMessage();
void setChatListMessageFromChannels();
bool justUpdateChatListMessage(not_null<HistoryItem*> item);
void updateChatListDate();
//void changeChatsList(
// const std::vector<not_null<PeerData*>> &add,
// const std::vector<not_null<PeerData*>> &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<QString> _nameWords;
base::flat_set<QChar> _nameFirstLetters;
std::optional<HistoryItem*> _chatListMessage;
rpl::variable<MessagePosition> _unreadPosition;
//rpl::variable<MessagePosition> _unreadPosition;
std::optional<int> _unreadCount;
rpl::event_stream<int> _unreadCountChanges;
int _unreadMutedCount = 0;

View File

@ -2949,12 +2949,10 @@ not_null<Folder*> Session::processFolder(const MTPDfolder &data) {
// return _defaultFeedId.value();
//}
not_null<Dialogs::IndexedList*> Session::chatsList() {
return &_chatsList;
}
not_null<Dialogs::IndexedList*> Session::importantChatsList() {
return &_importantChatsList;
not_null<Dialogs::IndexedList*> Session::chatsList(Dialogs::Mode list) {
return (list == Dialogs::Mode::All)
? &_chatsList
: &_importantChatsList;
}
not_null<Dialogs::IndexedList*> 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)) {

View File

@ -516,8 +516,7 @@ public:
//FeedId defaultFeedId() const;
//rpl::producer<FeedId> defaultFeedIdValue() const;
not_null<Dialogs::IndexedList*> chatsList();
not_null<Dialogs::IndexedList*> importantChatsList();
not_null<Dialogs::IndexedList*> chatsList(Dialogs::Mode list);
not_null<Dialogs::IndexedList*> contactsList();
not_null<Dialogs::IndexedList*> contactsNoChatsList();

View File

@ -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<IndexedList*> 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<Row*> Entry::addToChatList(
Mode list,
not_null<IndexedList*> indexed) {
not_null<Row*> 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<Dialogs::IndexedList*> 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<IndexedList*> Entry::myChatsList(Mode list) const {
if (const auto current = folder()) {
return current->chatsList(list);
}
return owner().chatsList(list);
}
} // namespace Dialogs

View File

@ -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<IndexedList*> indexed);
PositionChange adjustByPosInChatList(Mode list);
bool inChatList(Mode list) const {
return !chatListLinks(list).empty();
}
int posInChatList(Mode list) const;
not_null<Row*> addToChatList(Mode list, not_null<IndexedList*> indexed);
void removeFromChatList(Mode list, not_null<IndexedList*> indexed);
not_null<Row*> 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<QString> &chatListNameWords() const = 0;
virtual const base::flat_set<QChar> &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<IndexedList*> myChatsList(Mode list) const;
not_null<Data::Session*> _owner;
Dialogs::Key _key;
RowsByLetter _chatListLinks[2];

View File

@ -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<Dialogs::IndexedList*> 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()) {

View File

@ -282,7 +282,7 @@ private:
std::optional<QPoint> _lastMousePosition;
Qt::MouseButton _pressButton = Qt::LeftButton;
Dialogs::IndexedList *_folderChatsList = nullptr;
Data::Folder *_openedFolder = nullptr;
std::unique_ptr<ImportantSwitch> _importantSwitch;
bool _importantSwitchSelected = false;
bool _importantSwitchPressed = false;

View File

@ -1810,8 +1810,13 @@ Data::Folder *History::folder() const {
return _folder;
}
void History::setFolder(not_null<Data::Folder*> folder) {
void History::setFolder(
not_null<Data::Folder*> 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);
}
}

View File

@ -323,8 +323,10 @@ public:
std::shared_ptr<AdminLog::LocalIdManager> adminLogIdManager();
Data::Folder *folder() const;
void setFolder(not_null<Data::Folder*> folder);
Data::Folder *folder() const override;
void setFolder(
not_null<Data::Folder*> folder,
HistoryItem *folderDialogItem = nullptr);
void clearFolder();
// Still public data.