230 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
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_entry.h"
 | 
						|
 | 
						|
#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 "main/main_session.h"
 | 
						|
#include "history/history_item.h"
 | 
						|
#include "history/history.h"
 | 
						|
#include "app.h"
 | 
						|
#include "styles/style_dialogs.h" // st::dialogsTextWidthMin
 | 
						|
 | 
						|
namespace Dialogs {
 | 
						|
namespace {
 | 
						|
 | 
						|
auto DialogsPosToTopShift = 0;
 | 
						|
 | 
						|
uint64 DialogPosFromDate(TimeId date) {
 | 
						|
	if (!date) {
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	return (uint64(date) << 32) | (++DialogsPosToTopShift);
 | 
						|
}
 | 
						|
 | 
						|
uint64 FixedOnTopDialogPos(int index) {
 | 
						|
	return 0xFFFFFFFFFFFF000FULL - index;
 | 
						|
}
 | 
						|
 | 
						|
uint64 PinnedDialogPos(int pinnedIndex) {
 | 
						|
	return 0xFFFFFFFF000000FFULL - pinnedIndex;
 | 
						|
}
 | 
						|
 | 
						|
} // namespace
 | 
						|
 | 
						|
Entry::Entry(not_null<Data::Session*> owner, const Key &key)
 | 
						|
: lastItemTextCache(st::dialogsTextWidthMin)
 | 
						|
, _owner(owner)
 | 
						|
, _key(key) {
 | 
						|
}
 | 
						|
 | 
						|
Data::Session &Entry::owner() const {
 | 
						|
	return *_owner;
 | 
						|
}
 | 
						|
 | 
						|
Main::Session &Entry::session() const {
 | 
						|
	return _owner->session();
 | 
						|
}
 | 
						|
 | 
						|
void Entry::cachePinnedIndex(int index) {
 | 
						|
	if (_pinnedIndex != index) {
 | 
						|
		const auto wasPinned = isPinnedDialog();
 | 
						|
		_pinnedIndex = index;
 | 
						|
		if (session().supportMode()) {
 | 
						|
			// Force reorder in support mode.
 | 
						|
			_sortKeyInChatList = 0;
 | 
						|
		}
 | 
						|
		updateChatListSortPosition();
 | 
						|
		updateChatListEntry();
 | 
						|
		if (wasPinned != isPinnedDialog()) {
 | 
						|
			changedChatListPinHook();
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Entry::cacheProxyPromoted(bool promoted) {
 | 
						|
	if (_isProxyPromoted != promoted) {
 | 
						|
		_isProxyPromoted = promoted;
 | 
						|
		updateChatListSortPosition();
 | 
						|
		updateChatListEntry();
 | 
						|
		if (!_isProxyPromoted) {
 | 
						|
			updateChatListExistence();
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
bool Entry::needUpdateInChatList() const {
 | 
						|
	return inChatList() || shouldBeInChatList();
 | 
						|
}
 | 
						|
 | 
						|
void Entry::updateChatListSortPosition() {
 | 
						|
	if (session().supportMode()
 | 
						|
		&& _sortKeyInChatList != 0
 | 
						|
		&& session().settings().supportFixChatsOrder()) {
 | 
						|
		updateChatListEntry();
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	const auto fixedIndex = fixedOnTopIndex();
 | 
						|
	_sortKeyInChatList = fixedIndex
 | 
						|
		? FixedOnTopDialogPos(fixedIndex)
 | 
						|
		: isPinnedDialog()
 | 
						|
		? PinnedDialogPos(_pinnedIndex)
 | 
						|
		: DialogPosFromDate(adjustedChatListTimeId());
 | 
						|
	if (needUpdateInChatList()) {
 | 
						|
		setChatListExistence(true);
 | 
						|
	} else {
 | 
						|
		_sortKeyInChatList = 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Entry::updateChatListExistence() {
 | 
						|
	setChatListExistence(shouldBeInChatList());
 | 
						|
}
 | 
						|
 | 
						|
void Entry::notifyUnreadStateChange(const UnreadState &wasState) {
 | 
						|
	owner().unreadStateChanged(_key, wasState);
 | 
						|
}
 | 
						|
 | 
						|
void Entry::setChatListExistence(bool exists) {
 | 
						|
	if (const auto main = App::main()) {
 | 
						|
		if (exists && _sortKeyInChatList) {
 | 
						|
			main->refreshDialog(_key);
 | 
						|
			updateChatListEntry();
 | 
						|
		} else {
 | 
						|
			main->removeDialog(_key);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
TimeId Entry::adjustedChatListTimeId() const {
 | 
						|
	return chatListTimeId();
 | 
						|
}
 | 
						|
 | 
						|
void Entry::changedChatListPinHook() {
 | 
						|
}
 | 
						|
 | 
						|
RowsByLetter &Entry::chatListLinks(Mode list) {
 | 
						|
	return _chatListLinks[static_cast<int>(list)];
 | 
						|
}
 | 
						|
 | 
						|
const RowsByLetter &Entry::chatListLinks(Mode list) const {
 | 
						|
	return _chatListLinks[static_cast<int>(list)];
 | 
						|
}
 | 
						|
 | 
						|
Row *Entry::mainChatListLink(Mode list) const {
 | 
						|
	auto it = chatListLinks(list).find(0);
 | 
						|
	Assert(it != chatListLinks(list).cend());
 | 
						|
	return it->second;
 | 
						|
}
 | 
						|
 | 
						|
PositionChange Entry::adjustByPosInChatList(Mode list) {
 | 
						|
	const auto lnk = mainChatListLink(list);
 | 
						|
	const auto from = lnk->pos();
 | 
						|
	myChatsList(list)->adjustByDate(chatListLinks(list));
 | 
						|
	const auto to = lnk->pos();
 | 
						|
	return { from, to };
 | 
						|
}
 | 
						|
 | 
						|
void Entry::setChatListTimeId(TimeId date) {
 | 
						|
	_timeId = date;
 | 
						|
	updateChatListSortPosition();
 | 
						|
	if (const auto folder = this->folder()) {
 | 
						|
		folder->updateChatListSortPosition();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
int Entry::posInChatList(Dialogs::Mode list) const {
 | 
						|
	return mainChatListLink(list)->pos();
 | 
						|
}
 | 
						|
 | 
						|
not_null<Row*> Entry::addToChatList(Mode list) {
 | 
						|
	if (!inChatList(list)) {
 | 
						|
		chatListLinks(list) = myChatsList(list)->addToEnd(_key);
 | 
						|
		if (list == Mode::All) {
 | 
						|
			owner().unreadEntryChanged(_key, true);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return mainChatListLink(list);
 | 
						|
}
 | 
						|
 | 
						|
void Entry::removeFromChatList(Dialogs::Mode list) {
 | 
						|
	if (inChatList(list)) {
 | 
						|
		myChatsList(list)->del(_key);
 | 
						|
		chatListLinks(list).clear();
 | 
						|
		if (list == Mode::All) {
 | 
						|
			owner().unreadEntryChanged(_key, false);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Entry::removeChatListEntryByLetter(Mode list, QChar letter) {
 | 
						|
	Expects(letter != 0);
 | 
						|
 | 
						|
	if (inChatList(list)) {
 | 
						|
		chatListLinks(list).remove(letter);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Entry::addChatListEntryByLetter(
 | 
						|
		Mode list,
 | 
						|
		QChar letter,
 | 
						|
		not_null<Row*> row) {
 | 
						|
	Expects(letter != 0);
 | 
						|
 | 
						|
	if (inChatList(list)) {
 | 
						|
		chatListLinks(list).emplace(letter, row);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Entry::updateChatListEntry() const {
 | 
						|
	if (const auto main = App::main()) {
 | 
						|
		if (inChatList()) {
 | 
						|
			main->repaintDialogRow(
 | 
						|
				Mode::All,
 | 
						|
				mainChatListLink(Mode::All));
 | 
						|
			if (inChatList(Mode::Important)) {
 | 
						|
				main->repaintDialogRow(
 | 
						|
					Mode::Important,
 | 
						|
					mainChatListLink(Mode::Important));
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if (session().supportMode()
 | 
						|
			&& !session().settings().supportAllSearchResults()) {
 | 
						|
			main->repaintDialogRow({ _key, FullMsgId() });
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
not_null<IndexedList*> Entry::myChatsList(Mode list) const {
 | 
						|
	return owner().chatsList(folder())->indexed(list);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace Dialogs
 |