mirror of https://github.com/procxx/kepka.git
				
				
				
			History::dialogs and Histories::unread are private now, counting only chats from dialogs list to the badge
This commit is contained in:
		
							parent
							
								
									7338c3e21e
								
							
						
					
					
						commit
						798f800913
					
				|  | @ -273,7 +273,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt | ||||||
| 						if (!h->isEmpty()) { | 						if (!h->isEmpty()) { | ||||||
| 							h->clear(true); | 							h->clear(true); | ||||||
| 						} | 						} | ||||||
| 						if (!hto->dialogs.isEmpty() && !h->dialogs.isEmpty()) { | 						if (hto->inChatList() && h->inChatList()) { | ||||||
| 							App::removeDialog(h); | 							App::removeDialog(h); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
|  | @ -522,7 +522,7 @@ namespace App { | ||||||
| 								if (!h->isEmpty()) { | 								if (!h->isEmpty()) { | ||||||
| 									h->clear(true); | 									h->clear(true); | ||||||
| 								} | 								} | ||||||
| 								if (!hto->dialogs.isEmpty() && !h->dialogs.isEmpty()) { | 								if (hto->inChatList() && h->inChatList()) { | ||||||
| 									App::removeDialog(h); | 									App::removeDialog(h); | ||||||
| 								} | 								} | ||||||
| 							} | 							} | ||||||
|  |  | ||||||
|  | @ -443,16 +443,12 @@ void DialogsInner::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DialogsInner::createDialog(History *history) { | void DialogsInner::createDialog(History *history) { | ||||||
| 	bool creating = history->dialogs.isEmpty(); | 	bool creating = !history->inChatList(); | ||||||
| 	if (creating) { | 	if (creating) { | ||||||
| 		history->dialogs = dialogs.addToEnd(history); | 		DialogRow *mainRow = history->addToChatList(dialogs); | ||||||
| 		contactsNoDialogs.del(history->peer, history->dialogs[0]); | 		contactsNoDialogs.del(history->peer, mainRow); | ||||||
| 	} | 	} | ||||||
| 
 | 	RefPair(int32, movedFrom, int32, movedTo) = history->adjustByPosInChatsList(dialogs); | ||||||
| 	History::DialogLinks links = history->dialogs; |  | ||||||
| 	int32 movedFrom = links[0]->pos * st::dlgHeight; |  | ||||||
| 	dialogs.adjustByPos(links); |  | ||||||
| 	int32 movedTo = links[0]->pos * st::dlgHeight; |  | ||||||
| 
 | 
 | ||||||
| 	emit dialogMoved(movedFrom, movedTo); | 	emit dialogMoved(movedFrom, movedTo); | ||||||
| 
 | 
 | ||||||
|  | @ -471,8 +467,7 @@ void DialogsInner::removeDialog(History *history) { | ||||||
| 	if (sel && sel->history == history) { | 	if (sel && sel->history == history) { | ||||||
| 		sel = 0; | 		sel = 0; | ||||||
| 	} | 	} | ||||||
| 	dialogs.del(history->peer); | 	history->removeFromChatList(dialogs); | ||||||
| 	history->dialogs = History::DialogLinks(); |  | ||||||
| 	history->clearNotifications(); | 	history->clearNotifications(); | ||||||
| 	if (App::wnd()) App::wnd()->notifyClear(history); | 	if (App::wnd()) App::wnd()->notifyClear(history); | ||||||
| 	if (contacts.list.rowByPeer.constFind(history->peer->id) != contacts.list.rowByPeer.cend()) { | 	if (contacts.list.rowByPeer.constFind(history->peer->id) != contacts.list.rowByPeer.cend()) { | ||||||
|  | @ -550,8 +545,8 @@ void DialogsInner::updateSelectedRow(PeerData *peer) { | ||||||
| 	if (_state == DefaultState) { | 	if (_state == DefaultState) { | ||||||
| 		if (peer) { | 		if (peer) { | ||||||
| 			if (History *h = App::historyLoaded(peer->id)) { | 			if (History *h = App::historyLoaded(peer->id)) { | ||||||
| 				if (h->dialogs.contains(0)) { | 				if (h->inChatList()) { | ||||||
| 					update(0, h->dialogs.value(0)->pos * st::dlgHeight, fullWidth(), st::dlgHeight); | 					update(0, h->posInChatList() * st::dlgHeight, fullWidth(), st::dlgHeight); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} else if (sel) { | 		} else if (sel) { | ||||||
|  | @ -1019,7 +1014,7 @@ void DialogsInner::addSavedPeersAfter(const QDateTime &date) { | ||||||
| 	SavedPeersByTime &saved(cRefSavedPeersByTime()); | 	SavedPeersByTime &saved(cRefSavedPeersByTime()); | ||||||
| 	while (!saved.isEmpty() && (date.isNull() || date < saved.lastKey())) { | 	while (!saved.isEmpty() && (date.isNull() || date < saved.lastKey())) { | ||||||
| 		History *history = App::history(saved.last()->id); | 		History *history = App::history(saved.last()->id); | ||||||
| 		history->setPosInDialogsDate(saved.lastKey()); | 		history->setChatsListDate(saved.lastKey()); | ||||||
| 		contactsNoDialogs.del(history->peer); | 		contactsNoDialogs.del(history->peer); | ||||||
| 		saved.remove(saved.lastKey(), saved.last()); | 		saved.remove(saved.lastKey(), saved.last()); | ||||||
| 	} | 	} | ||||||
|  | @ -1074,8 +1069,11 @@ void DialogsInner::peopleReceived(const QString &query, const QVector<MTPPeer> & | ||||||
| 	_peopleResults.reserve(people.size()); | 	_peopleResults.reserve(people.size()); | ||||||
| 	for (QVector<MTPPeer>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) { | 	for (QVector<MTPPeer>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) { | ||||||
| 		PeerId peerId = peerFromMTP(*i); | 		PeerId peerId = peerFromMTP(*i); | ||||||
| 		History *h = App::historyLoaded(peerId); | 		if (History *h = App::historyLoaded(peerId)) { | ||||||
| 		if (h && !h->dialogs.isEmpty()) continue; // skip dialogs
 | 			if (h->inChatList()) { | ||||||
|  | 				continue; // skip existing chats
 | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		_peopleResults.push_back(App::peer(peerId)); | 		_peopleResults.push_back(App::peer(peerId)); | ||||||
| 	} | 	} | ||||||
|  | @ -1786,11 +1784,11 @@ void DialogsWidget::activate() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DialogsWidget::createDialog(History *history) { | void DialogsWidget::createDialog(History *history) { | ||||||
| 	bool creating = history->dialogs.isEmpty(); | 	bool creating = !history->inChatList(); | ||||||
| 	_inner.createDialog(history); | 	_inner.createDialog(history); | ||||||
| 	if (creating && history->peer->migrateFrom()) { | 	if (creating && history->peer->migrateFrom()) { | ||||||
| 		if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) { | 		if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) { | ||||||
| 			if (!h->dialogs.isEmpty()) { | 			if (h->inChatList()) { | ||||||
| 				removeDialog(h); | 				removeDialog(h); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -67,7 +67,6 @@ public: | ||||||
| 	void selectSkipPage(int32 pixels, int32 direction); | 	void selectSkipPage(int32 pixels, int32 direction); | ||||||
| 
 | 
 | ||||||
| 	void createDialog(History *history); | 	void createDialog(History *history); | ||||||
| 	void moveDialogToTop(const History::DialogLinks &links); |  | ||||||
| 	void dlgUpdated(DialogRow *row); | 	void dlgUpdated(DialogRow *row); | ||||||
| 	void dlgUpdated(History *row, MsgId msgId); | 	void dlgUpdated(History *row, MsgId msgId); | ||||||
| 	void removeDialog(History *history); | 	void removeDialog(History *history); | ||||||
|  |  | ||||||
|  | @ -294,7 +294,7 @@ History::History(const PeerId &peerId) : width(0), height(0) | ||||||
| , sendRequestId(0) | , sendRequestId(0) | ||||||
| , textCachedFor(0) | , textCachedFor(0) | ||||||
| , lastItemTextCache(st::dlgRichMinWidth) | , lastItemTextCache(st::dlgRichMinWidth) | ||||||
| , posInDialogs(0) | , _sortKeyInChatList(0) | ||||||
| , typingText(st::dlgRichMinWidth) { | , typingText(st::dlgRichMinWidth) { | ||||||
| 	if (peer->isChannel() || (peer->isUser() && peer->asUser()->botInfo)) { | 	if (peer->isChannel() || (peer->isUser() && peer->asUser()->botInfo)) { | ||||||
| 		outboxReadBefore = INT_MAX; | 		outboxReadBefore = INT_MAX; | ||||||
|  | @ -367,7 +367,7 @@ bool History::updateTyping(uint64 ms, bool force) { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (changed && App::main()) { | 	if (changed && App::main()) { | ||||||
| 		if (!dialogs.isEmpty()) App::main()->dlgUpdated(dialogs[0]); | 		updateChatListEntry(); | ||||||
| 		if (App::main()->historyPeer() == peer) { | 		if (App::main()->historyPeer() == peer) { | ||||||
| 			App::main()->topBar()->update(); | 			App::main()->topBar()->update(); | ||||||
| 		} | 		} | ||||||
|  | @ -1180,7 +1180,7 @@ void DialogsIndexed::peerNameChanged(PeerData *peer, const PeerData::Names &oldN | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		for (PeerData::NameFirstChars::const_iterator i = toRemove.cbegin(), e = toRemove.cend(); i != e; ++i) { | 		for (PeerData::NameFirstChars::const_iterator i = toRemove.cbegin(), e = toRemove.cend(); i != e; ++i) { | ||||||
| 			if (sortMode == DialogsSortByDate) history->dialogs.remove(*i); | 			if (sortMode == DialogsSortByDate) history->removeChatListEntryByLetter(*i); | ||||||
| 			DialogsIndex::iterator j = index.find(*i); | 			DialogsIndex::iterator j = index.find(*i); | ||||||
| 			if (j != index.cend()) { | 			if (j != index.cend()) { | ||||||
| 				j.value()->del(peer->id, mainRow); | 				j.value()->del(peer->id, mainRow); | ||||||
|  | @ -1191,11 +1191,8 @@ void DialogsIndexed::peerNameChanged(PeerData *peer, const PeerData::Names &oldN | ||||||
| 			if (j == index.cend()) { | 			if (j == index.cend()) { | ||||||
| 				j = index.insert(*i, new DialogsList(sortMode)); | 				j = index.insert(*i, new DialogsList(sortMode)); | ||||||
| 			} | 			} | ||||||
| 			if (sortMode == DialogsSortByDate) { | 			DialogRow *row = j.value()->addToEnd(history); | ||||||
| 				history->dialogs.insert(*i, j.value()->addToEnd(history)); | 			if (sortMode == DialogsSortByDate) history->addChatListEntryByLetter(*i, row); | ||||||
| 			} else { |  | ||||||
| 				j.value()->addToEnd(history); |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -2175,16 +2172,10 @@ MsgId History::inboxRead(MsgId upTo) { | ||||||
| 	if (!upTo) upTo = msgIdForRead(); | 	if (!upTo) upTo = msgIdForRead(); | ||||||
| 	inboxReadBefore = qMax(inboxReadBefore, upTo + 1); | 	inboxReadBefore = qMax(inboxReadBefore, upTo + 1); | ||||||
| 
 | 
 | ||||||
| 	if (App::main()) { | 	updateChatListEntry(); | ||||||
| 		if (!dialogs.isEmpty()) { | 	if (peer->migrateTo()) { | ||||||
| 			App::main()->dlgUpdated(dialogs[0]); | 		if (History *h = App::historyLoaded(peer->migrateTo()->id)) { | ||||||
| 		} | 			h->updateChatListEntry(); | ||||||
| 		if (peer->migrateTo()) { |  | ||||||
| 			if (History *h = App::historyLoaded(peer->migrateTo()->id)) { |  | ||||||
| 				if (!h->dialogs.isEmpty()) { |  | ||||||
| 					App::main()->dlgUpdated(h->dialogs[0]); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -2235,10 +2226,13 @@ void History::setUnreadCount(int32 newUnreadCount, bool psUpdate) { | ||||||
| 			showFrom = 0; | 			showFrom = 0; | ||||||
| 			inboxReadBefore = qMax(inboxReadBefore, msgIdForRead() + 1); | 			inboxReadBefore = qMax(inboxReadBefore, msgIdForRead() + 1); | ||||||
| 		} | 		} | ||||||
| 		App::histories().unreadFull += newUnreadCount - unreadCount; | 		if (inChatList()) { | ||||||
| 		if (mute) App::histories().unreadMuted += newUnreadCount - unreadCount; | 			App::histories().unreadIncrement(newUnreadCount - unreadCount, mute); | ||||||
|  | 			if (psUpdate && (!mute || cIncludeMuted()) && App::wnd()) { | ||||||
|  | 				App::wnd()->updateCounter(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		unreadCount = newUnreadCount; | 		unreadCount = newUnreadCount; | ||||||
| 		if (psUpdate && (!mute || cIncludeMuted()) && App::wnd()) App::wnd()->updateCounter(); |  | ||||||
| 		if (unreadBar) { | 		if (unreadBar) { | ||||||
| 			int32 count = unreadCount; | 			int32 count = unreadCount; | ||||||
| 			if (peer->migrateTo()) { | 			if (peer->migrateTo()) { | ||||||
|  | @ -2253,10 +2247,12 @@ void History::setUnreadCount(int32 newUnreadCount, bool psUpdate) { | ||||||
| 
 | 
 | ||||||
|  void History::setMute(bool newMute) { |  void History::setMute(bool newMute) { | ||||||
| 	if (mute != newMute) { | 	if (mute != newMute) { | ||||||
| 		App::histories().unreadMuted += newMute ? unreadCount : (-unreadCount); |  | ||||||
| 		mute = newMute; | 		mute = newMute; | ||||||
| 		if (App::wnd()) App::wnd()->updateCounter(); | 		if (inChatList() && unreadCount) { | ||||||
| 		if (!dialogs.isEmpty() && App::main()) App::main()->dlgUpdated(dialogs[0]); | 			App::histories().unreadMuteChanged(unreadCount, newMute); | ||||||
|  | 			if (App::wnd()) App::wnd()->updateCounter(); | ||||||
|  | 		} | ||||||
|  | 		updateChatListEntry(); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2420,25 +2416,25 @@ void History::setLastMessage(HistoryItem *msg) { | ||||||
| 	if (msg) { | 	if (msg) { | ||||||
| 		if (!lastMsg) Local::removeSavedPeer(peer); | 		if (!lastMsg) Local::removeSavedPeer(peer); | ||||||
| 		lastMsg = msg; | 		lastMsg = msg; | ||||||
| 		setPosInDialogsDate(msg->date); | 		setChatsListDate(msg->date); | ||||||
| 	} else { | 	} else { | ||||||
| 		lastMsg = 0; | 		lastMsg = 0; | ||||||
| 	} | 	} | ||||||
| 	if (!dialogs.isEmpty() && App::main()) App::main()->dlgUpdated(dialogs[0]); | 	updateChatListEntry(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void History::setPosInDialogsDate(const QDateTime &date) { | void History::setChatsListDate(const QDateTime &date) { | ||||||
| 	bool updateDialog = (App::main() && (!peer->isChannel() || peer->asChannel()->amIn() || !dialogs.isEmpty())); | 	bool updateDialog = (App::main() && (!peer->isChannel() || peer->asChannel()->amIn() || !_chatListLinks.isEmpty())); | ||||||
| 	if (peer->migrateTo() && dialogs.isEmpty()) { | 	if (peer->migrateTo() && _chatListLinks.isEmpty()) { | ||||||
| 		updateDialog = false; | 		updateDialog = false; | ||||||
| 	} | 	} | ||||||
| 	if (!lastMsgDate.isNull() && lastMsgDate >= date) { | 	if (!lastMsgDate.isNull() && lastMsgDate >= date) { | ||||||
| 		if (!updateDialog || !dialogs.isEmpty()) { | 		if (!updateDialog || !_chatListLinks.isEmpty()) { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	lastMsgDate = date; | 	lastMsgDate = date; | ||||||
| 	posInDialogs = dialogPosFromDate(lastMsgDate); | 	_sortKeyInChatList = dialogPosFromDate(lastMsgDate); | ||||||
| 	if (updateDialog) { | 	if (updateDialog) { | ||||||
| 		App::main()->createDialog(this); | 		App::main()->createDialog(this); | ||||||
| 	} | 	} | ||||||
|  | @ -2560,6 +2556,58 @@ void History::clear(bool leaveItems) { | ||||||
| 	if (leaveItems && App::main()) App::main()->historyCleared(this); | 	if (leaveItems && App::main()) App::main()->historyCleared(this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | QPair<int32, int32> History::adjustByPosInChatsList(DialogsIndexed &indexed) { | ||||||
|  | 	int32 movedFrom = _chatListLinks[0]->pos * st::dlgHeight; | ||||||
|  | 	indexed.adjustByPos(_chatListLinks); | ||||||
|  | 	int32 movedTo = _chatListLinks[0]->pos * st::dlgHeight; | ||||||
|  | 	return qMakePair(movedFrom, movedTo); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DialogRow *History::addToChatList(DialogsIndexed &indexed) { | ||||||
|  | 	if (!inChatList()) { | ||||||
|  | 		_chatListLinks = indexed.addToEnd(this); | ||||||
|  | 		if (unreadCount) { | ||||||
|  | 			App::histories().unreadIncrement(unreadCount, mute); | ||||||
|  | 			if (App::wnd()) App::wnd()->updateCounter(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	t_assert(!_chatListLinks.isEmpty()); | ||||||
|  | 	return _chatListLinks[0]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void History::removeFromChatList(DialogsIndexed &indexed) { | ||||||
|  | 	if (inChatList()) { | ||||||
|  | 		indexed.del(peer); | ||||||
|  | 		_chatListLinks.clear(); | ||||||
|  | 		if (unreadCount) { | ||||||
|  | 			App::histories().unreadIncrement(-unreadCount, mute); | ||||||
|  | 			if (App::wnd()) App::wnd()->updateCounter(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void History::removeChatListEntryByLetter(QChar letter) { | ||||||
|  | 	t_assert(letter != 0); | ||||||
|  | 	if (inChatList()) { | ||||||
|  | 		_chatListLinks.remove(letter); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void History::addChatListEntryByLetter(QChar letter, DialogRow *row) { | ||||||
|  | 	t_assert(letter != 0); | ||||||
|  | 	if (inChatList()) { | ||||||
|  | 		_chatListLinks.insert(letter, row); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void History::updateChatListEntry() const { | ||||||
|  | 	if (MainWidget *m = App::main()) { | ||||||
|  | 		if (inChatList()) { | ||||||
|  | 			m->dlgUpdated(_chatListLinks[0]); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void History::overviewSliceDone(int32 overviewIndex, const MTPmessages_Messages &result, bool onlyCounts) { | void History::overviewSliceDone(int32 overviewIndex, const MTPmessages_Messages &result, bool onlyCounts) { | ||||||
| 	const QVector<MTPMessage> *v = 0; | 	const QVector<MTPMessage> *v = 0; | ||||||
| 	switch (result.type()) { | 	switch (result.type()) { | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ public: | ||||||
| 	typedef QHash<PeerId, History*> Map; | 	typedef QHash<PeerId, History*> Map; | ||||||
| 	Map map; | 	Map map; | ||||||
| 
 | 
 | ||||||
| 	Histories() : _a_typings(animation(this, &Histories::step_typings)), unreadFull(0), unreadMuted(0) { | 	Histories() : _a_typings(animation(this, &Histories::step_typings)), _unreadFull(0), _unreadMuted(0) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void regSendAction(History *history, UserData *user, const MTPSendMessageAction &action); | 	void regSendAction(History *history, UserData *user, const MTPSendMessageAction &action); | ||||||
|  | @ -52,7 +52,7 @@ public: | ||||||
| 	void clear(); | 	void clear(); | ||||||
| 	void remove(const PeerId &peer); | 	void remove(const PeerId &peer); | ||||||
| 	~Histories() { | 	~Histories() { | ||||||
| 		unreadFull = unreadMuted = 0; | 		_unreadFull = _unreadMuted = 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	HistoryItem *addNewMessage(const MTPMessage &msg, NewMessageType type); | 	HistoryItem *addNewMessage(const MTPMessage &msg, NewMessageType type); | ||||||
|  | @ -62,7 +62,29 @@ public: | ||||||
| 	TypingHistories typing; | 	TypingHistories typing; | ||||||
| 	Animation _a_typings; | 	Animation _a_typings; | ||||||
| 
 | 
 | ||||||
| 	int32 unreadFull, unreadMuted; | 	int32 unreadBadge() const { | ||||||
|  | 		return _unreadFull - (cIncludeMuted() ? 0 : _unreadMuted); | ||||||
|  | 	} | ||||||
|  | 	bool unreadOnlyMuted() const { | ||||||
|  | 		return cIncludeMuted() ? (_unreadMuted >= _unreadFull) : false; | ||||||
|  | 	} | ||||||
|  | 	void unreadIncrement(int32 count, bool muted) { | ||||||
|  | 		_unreadFull += count; | ||||||
|  | 		if (muted) { | ||||||
|  | 			_unreadMuted += count; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	void unreadMuteChanged(int32 count, bool muted) { | ||||||
|  | 		if (muted) { | ||||||
|  | 			_unreadMuted += count; | ||||||
|  | 		} else { | ||||||
|  | 			_unreadMuted -= count; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	int32 _unreadFull, _unreadMuted; | ||||||
|  | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class HistoryBlock; | class HistoryBlock; | ||||||
|  | @ -195,6 +217,7 @@ enum AddToOverviewMethod { | ||||||
| 	AddToOverviewBack, // when new messages slice was received and it is the last one, we index all media
 | 	AddToOverviewBack, // when new messages slice was received and it is the last one, we index all media
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct DialogsIndexed; | ||||||
| class ChannelHistory; | class ChannelHistory; | ||||||
| class History { | class History { | ||||||
| public: | public: | ||||||
|  | @ -264,9 +287,27 @@ public: | ||||||
| 	void getReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScrollMsgTop); | 	void getReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScrollMsgTop); | ||||||
| 
 | 
 | ||||||
| 	void setLastMessage(HistoryItem *msg); | 	void setLastMessage(HistoryItem *msg); | ||||||
| 	void setPosInDialogsDate(const QDateTime &date); |  | ||||||
| 	void fixLastMessage(bool wasAtBottom); | 	void fixLastMessage(bool wasAtBottom); | ||||||
| 
 | 
 | ||||||
|  | 	typedef QMap<QChar, DialogRow*> ChatListLinksMap; | ||||||
|  | 	void setChatsListDate(const QDateTime &date); | ||||||
|  | 	QPair<int32, int32> adjustByPosInChatsList(DialogsIndexed &indexed); | ||||||
|  | 	uint64 sortKeyInChatList() const { | ||||||
|  | 		return _sortKeyInChatList; | ||||||
|  | 	} | ||||||
|  | 	bool inChatList() const { | ||||||
|  | 		return !_chatListLinks.isEmpty(); | ||||||
|  | 	} | ||||||
|  | 	int32 posInChatList() const { | ||||||
|  | 		t_assert(inChatList()); | ||||||
|  | 		return _chatListLinks[0]->pos; | ||||||
|  | 	} | ||||||
|  | 	DialogRow *addToChatList(DialogsIndexed &indexed); | ||||||
|  | 	void removeFromChatList(DialogsIndexed &indexed); | ||||||
|  | 	void removeChatListEntryByLetter(QChar letter); | ||||||
|  | 	void addChatListEntryByLetter(QChar letter, DialogRow *row); | ||||||
|  | 	void updateChatListEntry() const; | ||||||
|  | 
 | ||||||
| 	MsgId minMsgId() const; | 	MsgId minMsgId() const; | ||||||
| 	MsgId maxMsgId() const; | 	MsgId maxMsgId() const; | ||||||
| 	MsgId msgIdForRead() const; | 	MsgId msgIdForRead() const; | ||||||
|  | @ -345,10 +386,6 @@ public: | ||||||
| 	mutable const HistoryItem *textCachedFor; // cache
 | 	mutable const HistoryItem *textCachedFor; // cache
 | ||||||
| 	mutable Text lastItemTextCache; | 	mutable Text lastItemTextCache; | ||||||
| 
 | 
 | ||||||
| 	typedef QMap<QChar, DialogRow*> DialogLinks; |  | ||||||
| 	DialogLinks dialogs; |  | ||||||
| 	uint64 posInDialogs; // like ((unixtime) << 32) | (incremented counter)
 |  | ||||||
| 
 |  | ||||||
| 	typedef QMap<UserData*, uint64> TypingUsers; | 	typedef QMap<UserData*, uint64> TypingUsers; | ||||||
| 	TypingUsers typing; | 	TypingUsers typing; | ||||||
| 	typedef QMap<UserData*, SendAction> SendActionUsers; | 	typedef QMap<UserData*, SendAction> SendActionUsers; | ||||||
|  | @ -395,6 +432,9 @@ public: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| 
 | 
 | ||||||
|  | 	ChatListLinksMap _chatListLinks; | ||||||
|  | 	uint64 _sortKeyInChatList; // like ((unixtime) << 32) | (incremented counter)
 | ||||||
|  | 
 | ||||||
| 	typedef QMap<MsgId, NullType> MediaOverviewIds; | 	typedef QMap<MsgId, NullType> MediaOverviewIds; | ||||||
| 	MediaOverviewIds overviewIds[OverviewCount]; | 	MediaOverviewIds overviewIds[OverviewCount]; | ||||||
| 	int32 overviewCountData[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded
 | 	int32 overviewCountData[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded
 | ||||||
|  | @ -632,15 +672,15 @@ struct DialogsList { | ||||||
| 		if (sortMode != DialogsSortByDate) return; | 		if (sortMode != DialogsSortByDate) return; | ||||||
| 
 | 
 | ||||||
| 		DialogRow *change = row; | 		DialogRow *change = row; | ||||||
| 		if (change != begin && begin->history->posInDialogs < row->history->posInDialogs) { | 		if (change != begin && begin->history->sortKeyInChatList() < row->history->sortKeyInChatList()) { | ||||||
| 			change = begin; | 			change = begin; | ||||||
| 		} else while (change->prev && change->prev->history->posInDialogs < row->history->posInDialogs) { | 		} else while (change->prev && change->prev->history->sortKeyInChatList() < row->history->sortKeyInChatList()) { | ||||||
| 			change = change->prev; | 			change = change->prev; | ||||||
| 		} | 		} | ||||||
| 		if (!insertBefore(row, change)) { | 		if (!insertBefore(row, change)) { | ||||||
| 			if (change->next != end && end->prev->history->posInDialogs > row->history->posInDialogs) { | 			if (change->next != end && end->prev->history->sortKeyInChatList() > row->history->sortKeyInChatList()) { | ||||||
| 				change = end->prev; | 				change = end->prev; | ||||||
| 			} else while (change->next != end && change->next->history->posInDialogs > row->history->posInDialogs) { | 			} else while (change->next != end && change->next->history->sortKeyInChatList() > row->history->sortKeyInChatList()) { | ||||||
| 				change = change->next; | 				change = change->next; | ||||||
| 			} | 			} | ||||||
| 			insertAfter(row, change); | 			insertAfter(row, change); | ||||||
|  | @ -688,22 +728,19 @@ struct DialogsIndexed { | ||||||
| 	DialogsIndexed(DialogsSortMode sortMode) : sortMode(sortMode), list(sortMode) { | 	DialogsIndexed(DialogsSortMode sortMode) : sortMode(sortMode), list(sortMode) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	History::DialogLinks addToEnd(History *history) { | 	History::ChatListLinksMap addToEnd(History *history) { | ||||||
| 		History::DialogLinks result; | 		History::ChatListLinksMap result; | ||||||
| 		DialogsList::RowByPeer::const_iterator i = list.rowByPeer.find(history->peer->id); | 		DialogsList::RowByPeer::const_iterator i = list.rowByPeer.find(history->peer->id); | ||||||
| 		if (i != list.rowByPeer.cend()) { | 		if (i == list.rowByPeer.cend()) { | ||||||
| 			return i.value()->history->dialogs; | 			result.insert(0, list.addToEnd(history)); | ||||||
| 		} | 			for (PeerData::NameFirstChars::const_iterator i = history->peer->chars.cbegin(), e = history->peer->chars.cend(); i != e; ++i) { | ||||||
| 
 | 				DialogsIndex::iterator j = index.find(*i); | ||||||
| 		result.insert(0, list.addToEnd(history)); | 				if (j == index.cend()) { | ||||||
| 		for (PeerData::NameFirstChars::const_iterator i = history->peer->chars.cbegin(), e = history->peer->chars.cend(); i != e; ++i) { | 					j = index.insert(*i, new DialogsList(sortMode)); | ||||||
| 			DialogsIndex::iterator j = index.find(*i); | 				} | ||||||
| 			if (j == index.cend()) { | 				result.insert(*i, j.value()->addToEnd(history)); | ||||||
| 				j = index.insert(*i, new DialogsList(sortMode)); |  | ||||||
| 			} | 			} | ||||||
| 			result.insert(*i, j.value()->addToEnd(history)); |  | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -724,8 +761,8 @@ struct DialogsIndexed { | ||||||
| 		return res; | 		return res; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void adjustByPos(const History::DialogLinks &links) { | 	void adjustByPos(const History::ChatListLinksMap &links) { | ||||||
| 		for (History::DialogLinks::const_iterator i = links.cbegin(), e = links.cend(); i != e; ++i) { | 		for (History::ChatListLinksMap::const_iterator i = links.cbegin(), e = links.cend(); i != e; ++i) { | ||||||
| 			if (i.key() == QChar(0)) { | 			if (i.key() == QChar(0)) { | ||||||
| 				list.adjustByPos(i.value()); | 				list.adjustByPos(i.value()); | ||||||
| 			} else { | 			} else { | ||||||
|  |  | ||||||
|  | @ -785,8 +785,8 @@ void MainWidget::notify_clipStopperHidden(ClipStopperType type) { | ||||||
| 
 | 
 | ||||||
| void MainWidget::ui_repaintHistoryItem(const HistoryItem *item) { | void MainWidget::ui_repaintHistoryItem(const HistoryItem *item) { | ||||||
| 	history.ui_repaintHistoryItem(item); | 	history.ui_repaintHistoryItem(item); | ||||||
| 	if (!item->history()->dialogs.isEmpty() && item->history()->lastMsg == item) { | 	if (item->history()->lastMsg == item) { | ||||||
| 		dialogs.dlgUpdated(item->history()->dialogs[0]); | 		item->history()->updateChatListEntry(); | ||||||
| 	} | 	} | ||||||
| 	if (overview) overview->ui_repaintHistoryItem(item); | 	if (overview) overview->ui_repaintHistoryItem(item); | ||||||
| } | } | ||||||
|  | @ -4246,9 +4246,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { | ||||||
| 			if (h->lastMsg && h->lastMsg->out() && h->lastMsg->id <= d.vmax_id.v) { | 			if (h->lastMsg && h->lastMsg->out() && h->lastMsg->id <= d.vmax_id.v) { | ||||||
| 				dlgUpdated(h, h->lastMsg->id); | 				dlgUpdated(h, h->lastMsg->id); | ||||||
| 			} | 			} | ||||||
| 			if (!h->dialogs.isEmpty()) { | 			h->updateChatListEntry(); | ||||||
| 				dlgUpdated(h->dialogs[0]); |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ptsApplySkippedUpdates(); | 		ptsApplySkippedUpdates(); | ||||||
|  |  | ||||||
|  | @ -250,8 +250,8 @@ namespace { | ||||||
| #define GTK_ALPHA 3 | #define GTK_ALPHA 3 | ||||||
| 
 | 
 | ||||||
|     QImage _trayIconImageGen() { |     QImage _trayIconImageGen() { | ||||||
| 		int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; | 		int32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; | ||||||
| 		bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; | 		bool muted = App::histories().unreadOnlyMuted(); | ||||||
|         if (_trayIconImage.isNull() || _trayIconImage.width() != _trayIconSize || muted != _trayIconMuted || counterSlice != _trayIconCount) { |         if (_trayIconImage.isNull() || _trayIconImage.width() != _trayIconSize || muted != _trayIconMuted || counterSlice != _trayIconCount) { | ||||||
|             if (_trayIconImageBack.isNull() || _trayIconImageBack.width() != _trayIconSize) { |             if (_trayIconImageBack.isNull() || _trayIconImageBack.width() != _trayIconSize) { | ||||||
|                 _trayIconImageBack = App::wnd()->iconLarge().scaled(_trayIconSize, _trayIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); |                 _trayIconImageBack = App::wnd()->iconLarge().scaled(_trayIconSize, _trayIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); | ||||||
|  | @ -286,8 +286,8 @@ namespace { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     QString _trayIconImageFile() { |     QString _trayIconImageFile() { | ||||||
| 		int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; | 		int32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; | ||||||
| 		bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; | 		bool muted = App::histories().unreadOnlyMuted(); | ||||||
| 
 | 
 | ||||||
|         QString name = cWorkingDir() + qsl("tdata/ticons/ico%1_%2_%3.png").arg(muted ? "mute" : "").arg(_trayIconSize).arg(counterSlice); |         QString name = cWorkingDir() + qsl("tdata/ticons/ico%1_%2_%3.png").arg(muted ? "mute" : "").arg(_trayIconSize).arg(counterSlice); | ||||||
|         QFileInfo info(name); |         QFileInfo info(name); | ||||||
|  | @ -621,7 +621,7 @@ void PsMainWindow::psUpdateIndicator() { | ||||||
| void PsMainWindow::psUpdateCounter() { | void PsMainWindow::psUpdateCounter() { | ||||||
|     setWindowIcon(wndIcon); |     setWindowIcon(wndIcon); | ||||||
| 
 | 
 | ||||||
| 	int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); | 	int32 counter = App::histories().unreadBadge(); | ||||||
| 
 | 
 | ||||||
|     setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram")); |     setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram")); | ||||||
|     if (_psUnityLauncherEntry) { |     if (_psUnityLauncherEntry) { | ||||||
|  | @ -645,8 +645,8 @@ void PsMainWindow::psUpdateCounter() { | ||||||
|             ps_gtk_status_icon_set_from_pixbuf(_trayIcon, _trayPixbuf); |             ps_gtk_status_icon_set_from_pixbuf(_trayIcon, _trayPixbuf); | ||||||
|         } |         } | ||||||
|     } else if (trayIcon) { |     } else if (trayIcon) { | ||||||
| 		int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); | 		int32 counter = App::histories().unreadBadge(); | ||||||
| 		bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; | 		bool muted = App::histories().unreadOnlyMuted(); | ||||||
| 
 | 
 | ||||||
| 		style::color bg = muted ? st::counterMuteBG : st::counterBG; | 		style::color bg = muted ? st::counterMuteBG : st::counterBG; | ||||||
|         QIcon iconSmall; |         QIcon iconSmall; | ||||||
|  |  | ||||||
|  | @ -176,7 +176,7 @@ void _placeCounter(QImage &img, int size, int count, style::color bg, style::col | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PsMainWindow::psUpdateCounter() { | void PsMainWindow::psUpdateCounter() { | ||||||
| 	int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); | 	int32 counter = App::histories().unreadBadge(); | ||||||
| 
 | 
 | ||||||
|     setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram")); |     setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram")); | ||||||
| 	setWindowIcon(wndIcon); | 	setWindowIcon(wndIcon); | ||||||
|  | @ -185,7 +185,7 @@ void PsMainWindow::psUpdateCounter() { | ||||||
|     _private.setWindowBadge(counter ? cnt : QString()); |     _private.setWindowBadge(counter ? cnt : QString()); | ||||||
| 
 | 
 | ||||||
| 	if (trayIcon) { | 	if (trayIcon) { | ||||||
| 		bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; | 		bool muted = App::histories().unreadOnlyMuted(); | ||||||
| 		bool dm = objc_darkMode(); | 		bool dm = objc_darkMode(); | ||||||
| 
 | 
 | ||||||
| 		style::color bg = muted ? st::counterMuteBG : st::counterBG; | 		style::color bg = muted ? st::counterMuteBG : st::counterBG; | ||||||
|  |  | ||||||
|  | @ -1133,8 +1133,8 @@ static HICON _qt_createHIcon(const QIcon &icon, int xSize, int ySize) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PsMainWindow::psUpdateCounter() { | void PsMainWindow::psUpdateCounter() { | ||||||
| 	int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); | 	int32 counter = App::histories().unreadBadge(); | ||||||
| 	bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; | 	bool muted = App::histories().unreadOnlyMuted(); | ||||||
| 
 | 
 | ||||||
| 	style::color bg = muted ? st::counterMuteBG : st::counterBG; | 	style::color bg = muted ? st::counterMuteBG : st::counterBG; | ||||||
| 	QIcon iconSmall, iconBig; | 	QIcon iconSmall, iconBig; | ||||||
|  |  | ||||||
|  | @ -266,8 +266,8 @@ void TitleWidget::updateAdaptiveLayout() { | ||||||
| void TitleWidget::updateCounter() { | void TitleWidget::updateCounter() { | ||||||
| 	if (!Adaptive::OneColumn() || !MTP::authedId()) return; | 	if (!Adaptive::OneColumn() || !MTP::authedId()) return; | ||||||
| 
 | 
 | ||||||
| 	int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); | 	int32 counter = App::histories().unreadBadge(); | ||||||
| 	bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; | 	bool muted = App::histories().unreadOnlyMuted(); | ||||||
| 
 | 
 | ||||||
| 	style::color bg = muted ? st::counterMuteBG : st::counterBG; | 	style::color bg = muted ? st::counterMuteBG : st::counterBG; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -554,6 +554,42 @@ static int32 QuarterArcLength = (FullArcLength / 4); | ||||||
| static int32 MinArcLength = (FullArcLength / 360); | static int32 MinArcLength = (FullArcLength / 360); | ||||||
| static int32 AlmostFullArcLength = (FullArcLength - MinArcLength); | static int32 AlmostFullArcLength = (FullArcLength - MinArcLength); | ||||||
| 
 | 
 | ||||||
|  | template <typename T1, typename T2> | ||||||
|  | class RefPairImplementation { | ||||||
|  | public: | ||||||
|  | 	template <typename T3, typename T4> | ||||||
|  | 	const RefPairImplementation &operator=(const RefPairImplementation<T3, T4> &other) const { | ||||||
|  | 		_first = other._first; | ||||||
|  | 		_second = other._second; | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	template <typename T3, typename T4> | ||||||
|  | 	const RefPairImplementation &operator=(const QPair<T3, T4> &other) const { | ||||||
|  | 		_first = other.first; | ||||||
|  | 		_second = other.second; | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	RefPairImplementation(T1 &first, T2 &second) : _first(first), _second(second) { | ||||||
|  | 	} | ||||||
|  | 	RefPairImplementation(const RefPairImplementation &other); | ||||||
|  | 
 | ||||||
|  | 	template <typename T3, typename T4> | ||||||
|  | 	friend RefPairImplementation<T3, T4> RefPairCreator(T3 &first, T4 &second); | ||||||
|  | 
 | ||||||
|  | 	T1 &_first; | ||||||
|  | 	T2 &_second; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | template <typename T1, typename T2> | ||||||
|  | inline RefPairImplementation<T1, T2> RefPairCreator(T1 &first, T2 &second) { | ||||||
|  | 	return RefPairImplementation<T1, T2>(first, second); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define RefPair(Type1, Name1, Type2, Name2) Type1 Name1; Type2 Name2; RefPairCreator(Name1, Name2) | ||||||
|  | 
 | ||||||
| template <typename I> | template <typename I> | ||||||
| inline void destroyImplementation(I *&ptr) { | inline void destroyImplementation(I *&ptr) { | ||||||
| 	if (ptr) { | 	if (ptr) { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue