Hashtag search results as dialogs (support).
This commit is contained in:
		
							parent
							
								
									81a9554caa
								
							
						
					
					
						commit
						631e51a493
					
				
					 6 changed files with 264 additions and 89 deletions
				
			
		|  | @ -641,6 +641,43 @@ void ApiWrap::requestDialogEntry( | ||||||
| 	}).send(); | 	}).send(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ApiWrap::requestDialogEntries( | ||||||
|  | 		std::vector<not_null<History*>> histories) { | ||||||
|  | 	const auto already = [&](not_null<History*> history) { | ||||||
|  | 		const auto [i, ok] = _dialogRequests.try_emplace(history); | ||||||
|  | 		return !ok; | ||||||
|  | 	}; | ||||||
|  | 	histories.erase(ranges::remove_if(histories, already), end(histories)); | ||||||
|  | 	if (histories.empty()) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	auto peers = QVector<MTPInputDialogPeer>(); | ||||||
|  | 	peers.reserve(histories.size()); | ||||||
|  | 	for (const auto history : histories) { | ||||||
|  | 		peers.push_back(MTP_inputDialogPeer(history->peer->input)); | ||||||
|  | 	} | ||||||
|  | 	const auto finalize = [=](std::vector<not_null<History*>> histories) { | ||||||
|  | 		for (const auto history : histories) { | ||||||
|  | 			if (const auto callbacks = _dialogRequests.take(history)) { | ||||||
|  | 				for (const auto callback : *callbacks) { | ||||||
|  | 					callback(); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 	request(MTPmessages_GetPeerDialogs( | ||||||
|  | 		MTP_vector(std::move(peers)) | ||||||
|  | 	)).done([=](const MTPmessages_PeerDialogs &result) { | ||||||
|  | 		applyPeerDialogs(result); | ||||||
|  | 		for (const auto history : histories) { | ||||||
|  | 			historyDialogEntryApplied(history); | ||||||
|  | 		} | ||||||
|  | 		finalize(histories); | ||||||
|  | 	}).fail([=](const RPCError &error) { | ||||||
|  | 		finalize(histories); | ||||||
|  | 	}).send(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void ApiWrap::applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs) { | void ApiWrap::applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs) { | ||||||
| 	Expects(dialogs.type() == mtpc_messages_peerDialogs); | 	Expects(dialogs.type() == mtpc_messages_peerDialogs); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -87,6 +87,7 @@ public: | ||||||
| 	void requestDialogEntry( | 	void requestDialogEntry( | ||||||
| 		not_null<History*> history, | 		not_null<History*> history, | ||||||
| 		Fn<void()> callback = nullptr); | 		Fn<void()> callback = nullptr); | ||||||
|  | 	void requestDialogEntries(std::vector<not_null<History*>> histories); | ||||||
| 	//void applyFeedSources(const MTPDchannels_feedSources &data); // #feed
 | 	//void applyFeedSources(const MTPDchannels_feedSources &data); // #feed
 | ||||||
| 	//void setFeedChannels(
 | 	//void setFeedChannels(
 | ||||||
| 	//	not_null<Data::Feed*> feed,
 | 	//	not_null<Data::Feed*> feed,
 | ||||||
|  |  | ||||||
|  | @ -451,9 +451,12 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		const auto showUnreadInSearchResults = uniqueSearchResults(); | ||||||
| 		if (!_waitingForSearch || !_searchResults.empty()) { | 		if (!_waitingForSearch || !_searchResults.empty()) { | ||||||
| 			const auto text = _searchResults.empty() | 			const auto text = _searchResults.empty() | ||||||
| 				? lang(lng_search_no_results) | 				? lang(lng_search_no_results) | ||||||
|  | 				: showUnreadInSearchResults | ||||||
|  | 				? qsl("Search results") | ||||||
| 				: lng_search_found_results( | 				: lng_search_found_results( | ||||||
| 					lt_count, | 					lt_count, | ||||||
| 					_searchedMigratedCount + _searchedCount); | 					_searchedMigratedCount + _searchedCount); | ||||||
|  | @ -489,7 +492,8 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO | ||||||
| 						active, | 						active, | ||||||
| 						selected, | 						selected, | ||||||
| 						paintingOther, | 						paintingOther, | ||||||
| 						ms); | 						ms, | ||||||
|  | 						showUnreadInSearchResults); | ||||||
| 					p.translate(0, st::dialogsRowHeight); | 					p.translate(0, st::dialogsRowHeight); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | @ -674,7 +678,6 @@ void DialogsInner::paintSearchInFeed( | ||||||
| 	paintSearchInFilter(p, paintUserpic, top, fullWidth, icon, text); | 	paintSearchInFilter(p, paintUserpic, top, fullWidth, icon, text); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| void DialogsInner::activate() { | void DialogsInner::activate() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1840,28 +1843,53 @@ void DialogsInner::addAllSavedPeers() { | ||||||
| 	addSavedPeersAfter(QDateTime()); | 	addSavedPeersAfter(QDateTime()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool DialogsInner::uniqueSearchResults() const { | ||||||
|  | 	return Auth().supportMode() | ||||||
|  | 		&& _filter.startsWith('#') | ||||||
|  | 		&& !_searchInChat; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool DialogsInner::hasHistoryInSearchResults(not_null<History*> history) const { | ||||||
|  | 	using Result = std::unique_ptr<Dialogs::FakeRow>; | ||||||
|  | 	return ranges::find( | ||||||
|  | 		_searchResults, | ||||||
|  | 		history, | ||||||
|  | 		[](const Result &result) { return result->item()->history(); } | ||||||
|  | 	) != end(_searchResults); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool DialogsInner::searchReceived( | bool DialogsInner::searchReceived( | ||||||
| 		const QVector<MTPMessage> &messages, | 		const QVector<MTPMessage> &messages, | ||||||
| 		DialogsSearchRequestType type, | 		DialogsSearchRequestType type, | ||||||
| 		int fullCount) { | 		int fullCount) { | ||||||
|  | 	const auto uniquePeers = uniqueSearchResults(); | ||||||
| 	if (type == DialogsSearchFromStart || type == DialogsSearchPeerFromStart) { | 	if (type == DialogsSearchFromStart || type == DialogsSearchPeerFromStart) { | ||||||
| 		clearSearchResults(false); | 		clearSearchResults(false); | ||||||
| 	} | 	} | ||||||
| 	auto isGlobalSearch = (type == DialogsSearchFromStart || type == DialogsSearchFromOffset); | 	auto isGlobalSearch = (type == DialogsSearchFromStart || type == DialogsSearchFromOffset); | ||||||
| 	auto isMigratedSearch = (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset); | 	auto isMigratedSearch = (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset); | ||||||
| 
 | 
 | ||||||
|  | 	auto unknownUnreadCounts = std::vector<not_null<History*>>(); | ||||||
| 	TimeId lastDateFound = 0; | 	TimeId lastDateFound = 0; | ||||||
| 	for_const (auto message, messages) { | 	for_const (auto message, messages) { | ||||||
| 		auto msgId = idFromMessage(message); | 		auto msgId = idFromMessage(message); | ||||||
| 		auto peerId = peerFromMessage(message); | 		auto peerId = peerFromMessage(message); | ||||||
| 		auto lastDate = dateFromMessage(message); | 		auto lastDate = dateFromMessage(message); | ||||||
| 		if (auto peer = App::peerLoaded(peerId)) { | 		if (const auto peer = App::peerLoaded(peerId)) { | ||||||
| 			if (lastDate) { | 			if (lastDate) { | ||||||
| 				auto item = App::histories().addNewMessage(message, NewMessageExisting); | 				const auto item = App::histories().addNewMessage( | ||||||
|  | 					message, | ||||||
|  | 					NewMessageExisting); | ||||||
|  | 				const auto history = item->history(); | ||||||
|  | 				if (!uniquePeers || !hasHistoryInSearchResults(history)) { | ||||||
| 					_searchResults.push_back( | 					_searchResults.push_back( | ||||||
| 						std::make_unique<Dialogs::FakeRow>( | 						std::make_unique<Dialogs::FakeRow>( | ||||||
| 							_searchInChat, | 							_searchInChat, | ||||||
| 							item)); | 							item)); | ||||||
|  | 					if (uniquePeers && !history->unreadCountKnown()) { | ||||||
|  | 						unknownUnreadCounts.push_back(history); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
| 				lastDateFound = lastDate; | 				lastDateFound = lastDate; | ||||||
| 				if (isGlobalSearch) { | 				if (isGlobalSearch) { | ||||||
| 					_lastSearchDate = lastDateFound; | 					_lastSearchDate = lastDateFound; | ||||||
|  | @ -1891,7 +1919,12 @@ bool DialogsInner::searchReceived( | ||||||
| 			|| type == DialogsSearchMigratedFromOffset)) { | 			|| type == DialogsSearchMigratedFromOffset)) { | ||||||
| 		_waitingForSearch = false; | 		_waitingForSearch = false; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	refresh(); | 	refresh(); | ||||||
|  | 
 | ||||||
|  | 	if (!unknownUnreadCounts.empty()) { | ||||||
|  | 		Auth().api().requestDialogEntries(std::move(unknownUnreadCounts)); | ||||||
|  | 	} | ||||||
| 	return lastDateFound != 0; | 	return lastDateFound != 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2476,7 +2509,9 @@ bool DialogsInner::chooseRow() { | ||||||
| 		if (const auto history = chosen.key.history()) { | 		if (const auto history = chosen.key.history()) { | ||||||
| 			App::main()->choosePeer( | 			App::main()->choosePeer( | ||||||
| 				history->peer->id, | 				history->peer->id, | ||||||
| 				chosen.message.fullId.msg); | 				(uniqueSearchResults() | ||||||
|  | 					? ShowAtUnreadMsgId | ||||||
|  | 					: chosen.message.fullId.msg)); | ||||||
| 		} else if (const auto feed = chosen.key.feed()) { | 		} else if (const auto feed = chosen.key.feed()) { | ||||||
| 			_controller->showSection( | 			_controller->showSection( | ||||||
| 				HistoryFeed::Memento(feed, chosen.message), | 				HistoryFeed::Memento(feed, chosen.message), | ||||||
|  |  | ||||||
|  | @ -189,6 +189,8 @@ private: | ||||||
| 	void handlePeerNameChange( | 	void handlePeerNameChange( | ||||||
| 		not_null<PeerData*> peer, | 		not_null<PeerData*> peer, | ||||||
| 		const base::flat_set<QChar> &oldLetters); | 		const base::flat_set<QChar> &oldLetters); | ||||||
|  | 	bool uniqueSearchResults() const; | ||||||
|  | 	bool hasHistoryInSearchResults(not_null<History*> history) const; | ||||||
| 
 | 
 | ||||||
| 	void applyDialog(const MTPDdialog &dialog); | 	void applyDialog(const MTPDdialog &dialog); | ||||||
| //	void applyFeedDialog(const MTPDdialogFeed &dialog); // #feed
 | //	void applyFeedDialog(const MTPDdialogFeed &dialog); // #feed
 | ||||||
|  |  | ||||||
|  | @ -52,6 +52,102 @@ void paintRowDate(Painter &p, QDateTime date, QRect &rectForName, bool active, b | ||||||
| 	paintRowTopRight(p, dt, rectForName, active, selected); | 	paintRowTopRight(p, dt, rectForName, active, selected); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void PaintNarrowCounter( | ||||||
|  | 		Painter &p, | ||||||
|  | 		bool displayUnreadCounter, | ||||||
|  | 		bool displayUnreadMark, | ||||||
|  | 		bool displayMentionBadge, | ||||||
|  | 		int unreadCount, | ||||||
|  | 		bool active, | ||||||
|  | 		bool unreadMuted) { | ||||||
|  | 	auto skipBeforeMention = 0; | ||||||
|  | 	if (displayUnreadCounter || displayUnreadMark) { | ||||||
|  | 		auto counter = (unreadCount > 0) | ||||||
|  | 			? QString::number(unreadCount) | ||||||
|  | 			: QString(); | ||||||
|  | 		const auto allowDigits = displayMentionBadge ? 1 : 3; | ||||||
|  | 		if (counter.size() > allowDigits + 1) { | ||||||
|  | 			counter = qsl("..") + counter.mid(counter.size() - allowDigits); | ||||||
|  | 		} | ||||||
|  | 		auto unreadRight = st::dialogsPadding.x() + st::dialogsPhotoSize; | ||||||
|  | 		auto unreadTop = st::dialogsPadding.y() + st::dialogsPhotoSize - st::dialogsUnreadHeight; | ||||||
|  | 		auto unreadWidth = 0; | ||||||
|  | 
 | ||||||
|  | 		UnreadBadgeStyle st; | ||||||
|  | 		st.active = active; | ||||||
|  | 		st.muted = unreadMuted; | ||||||
|  | 		paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth); | ||||||
|  | 		skipBeforeMention += unreadWidth + st.padding; | ||||||
|  | 	} | ||||||
|  | 	if (displayMentionBadge) { | ||||||
|  | 		auto counter = qsl("@"); | ||||||
|  | 		auto unreadRight = st::dialogsPadding.x() + st::dialogsPhotoSize - skipBeforeMention; | ||||||
|  | 		auto unreadTop = st::dialogsPadding.y() + st::dialogsPhotoSize - st::dialogsUnreadHeight; | ||||||
|  | 		auto unreadWidth = 0; | ||||||
|  | 
 | ||||||
|  | 		UnreadBadgeStyle st; | ||||||
|  | 		st.active = active; | ||||||
|  | 		st.muted = false; | ||||||
|  | 		st.padding = 0; | ||||||
|  | 		st.textTop = 0; | ||||||
|  | 		paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int PaintWideCounter( | ||||||
|  | 		Painter &p, | ||||||
|  | 		int texttop, | ||||||
|  | 		int availableWidth, | ||||||
|  | 		int fullWidth, | ||||||
|  | 		bool displayUnreadCounter, | ||||||
|  | 		bool displayUnreadMark, | ||||||
|  | 		bool displayMentionBadge, | ||||||
|  | 		bool displayPinnedIcon, | ||||||
|  | 		int unreadCount, | ||||||
|  | 		bool active, | ||||||
|  | 		bool selected, | ||||||
|  | 		bool unreadMuted) { | ||||||
|  | 	const auto initial = availableWidth; | ||||||
|  | 	auto hadOneBadge = false; | ||||||
|  | 	if (displayUnreadCounter || displayUnreadMark) { | ||||||
|  | 		auto counter = (unreadCount > 0) | ||||||
|  | 			? QString::number(unreadCount) | ||||||
|  | 			: QString(); | ||||||
|  | 		auto unreadRight = fullWidth - st::dialogsPadding.x(); | ||||||
|  | 		auto unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2; | ||||||
|  | 		auto unreadWidth = 0; | ||||||
|  | 
 | ||||||
|  | 		UnreadBadgeStyle st; | ||||||
|  | 		st.active = active; | ||||||
|  | 		st.muted = unreadMuted; | ||||||
|  | 		paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth); | ||||||
|  | 		availableWidth -= unreadWidth + st.padding; | ||||||
|  | 
 | ||||||
|  | 		hadOneBadge = true; | ||||||
|  | 	} else if (displayPinnedIcon) { | ||||||
|  | 		auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon)); | ||||||
|  | 		icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth); | ||||||
|  | 		availableWidth -= icon.width() + st::dialogsUnreadPadding; | ||||||
|  | 
 | ||||||
|  | 		hadOneBadge = true; | ||||||
|  | 	} | ||||||
|  | 	if (displayMentionBadge) { | ||||||
|  | 		auto counter = qsl("@"); | ||||||
|  | 		auto unreadRight = fullWidth - st::dialogsPadding.x() - (initial - availableWidth); | ||||||
|  | 		auto unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2; | ||||||
|  | 		auto unreadWidth = 0; | ||||||
|  | 
 | ||||||
|  | 		UnreadBadgeStyle st; | ||||||
|  | 		st.active = active; | ||||||
|  | 		st.muted = false; | ||||||
|  | 		st.padding = 0; | ||||||
|  | 		st.textTop = 0; | ||||||
|  | 		paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth); | ||||||
|  | 		availableWidth -= unreadWidth + st.padding + (hadOneBadge ? st::dialogsUnreadPadding : 0); | ||||||
|  | 	} | ||||||
|  | 	return availableWidth; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| enum class Flag { | enum class Flag { | ||||||
| 	Active           = 0x01, | 	Active           = 0x01, | ||||||
| 	Selected         = 0x02, | 	Selected         = 0x02, | ||||||
|  | @ -370,7 +466,13 @@ UnreadBadgeStyle::UnreadBadgeStyle() | ||||||
| , font(st::dialogsUnreadFont) { | , font(st::dialogsUnreadFont) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void paintUnreadCount(Painter &p, const QString &text, int x, int y, const UnreadBadgeStyle &st, int *outUnreadWidth) { | void paintUnreadCount( | ||||||
|  | 		Painter &p, | ||||||
|  | 		const QString &text, | ||||||
|  | 		int x, | ||||||
|  | 		int y, | ||||||
|  | 		const UnreadBadgeStyle &st, | ||||||
|  | 		int *outUnreadWidth) { | ||||||
| 	int unreadWidth = st.font->width(text); | 	int unreadWidth = st.font->width(text); | ||||||
| 	int unreadRectWidth = unreadWidth + 2 * st.padding; | 	int unreadRectWidth = unreadWidth + 2 * st.padding; | ||||||
| 	int unreadRectHeight = st.size; | 	int unreadRectHeight = st.size; | ||||||
|  | @ -464,45 +566,22 @@ void RowPainter::paint( | ||||||
| 		| (onlyBackground ? Flag::OnlyBackground : Flag(0)) | 		| (onlyBackground ? Flag::OnlyBackground : Flag(0)) | ||||||
| 		| (peer && peer->isSelf() ? Flag::SavedMessages : Flag(0)); | 		| (peer && peer->isSelf() ? Flag::SavedMessages : Flag(0)); | ||||||
| 	const auto paintItemCallback = [&](int nameleft, int namewidth) { | 	const auto paintItemCallback = [&](int nameleft, int namewidth) { | ||||||
| 		auto availableWidth = namewidth; | 		const auto texttop = st::dialogsPadding.y() | ||||||
| 		auto texttop = st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip; | 			+ st::msgNameFont->height | ||||||
| 		auto hadOneBadge = false; | 			+ st::dialogsSkip; | ||||||
| 		if (displayUnreadCounter || displayUnreadMark) { | 		const auto availableWidth = PaintWideCounter( | ||||||
| 			auto counter = (unreadCount > 0) | 			p, | ||||||
| 				? QString::number(unreadCount) | 			texttop, | ||||||
| 				: QString(); | 			namewidth, | ||||||
| 			auto unreadRight = fullWidth - st::dialogsPadding.x(); | 			fullWidth, | ||||||
| 			auto unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2; | 			displayUnreadCounter, | ||||||
| 			auto unreadWidth = 0; | 			displayUnreadMark, | ||||||
| 
 | 			displayMentionBadge, | ||||||
| 			UnreadBadgeStyle st; | 			displayPinnedIcon, | ||||||
| 			st.active = active; | 			unreadCount, | ||||||
| 			st.muted = unreadMuted; | 			active, | ||||||
| 			paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth); | 			selected, | ||||||
| 			availableWidth -= unreadWidth + st.padding; | 			unreadMuted); | ||||||
| 
 |  | ||||||
| 			hadOneBadge = true; |  | ||||||
| 		} else if (displayPinnedIcon) { |  | ||||||
| 			auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon)); |  | ||||||
| 			icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth); |  | ||||||
| 			availableWidth -= icon.width() + st::dialogsUnreadPadding; |  | ||||||
| 
 |  | ||||||
| 			hadOneBadge = true; |  | ||||||
| 		} |  | ||||||
| 		if (displayMentionBadge) { |  | ||||||
| 			auto counter = qsl("@"); |  | ||||||
| 			auto unreadRight = fullWidth - st::dialogsPadding.x() - (namewidth - availableWidth); |  | ||||||
| 			auto unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2; |  | ||||||
| 			auto unreadWidth = 0; |  | ||||||
| 
 |  | ||||||
| 			UnreadBadgeStyle st; |  | ||||||
| 			st.active = active; |  | ||||||
| 			st.muted = false; |  | ||||||
| 			st.padding = 0; |  | ||||||
| 			st.textTop = 0; |  | ||||||
| 			paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth); |  | ||||||
| 			availableWidth -= unreadWidth + st.padding + (hadOneBadge ? st::dialogsUnreadPadding : 0); |  | ||||||
| 		} |  | ||||||
| 		const auto &color = active | 		const auto &color = active | ||||||
| 			? st::dialogsTextFgServiceActive | 			? st::dialogsTextFgServiceActive | ||||||
| 			: (selected | 			: (selected | ||||||
|  | @ -517,7 +596,7 @@ void RowPainter::paint( | ||||||
| 			color, | 			color, | ||||||
| 			ms) : false; | 			ms) : false; | ||||||
| 		if (!actionWasPainted) { | 		if (!actionWasPainted) { | ||||||
| 			auto itemRect = QRect( | 			const auto itemRect = QRect( | ||||||
| 				nameleft, | 				nameleft, | ||||||
| 				texttop, | 				texttop, | ||||||
| 				availableWidth, | 				availableWidth, | ||||||
|  | @ -533,39 +612,14 @@ void RowPainter::paint( | ||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
| 	const auto paintCounterCallback = [&] { | 	const auto paintCounterCallback = [&] { | ||||||
| 		auto hadOneBadge = false; | 		PaintNarrowCounter( | ||||||
| 		auto skipBeforeMention = 0; | 			p, | ||||||
| 		if (displayUnreadCounter || displayUnreadMark) { | 			displayUnreadCounter, | ||||||
| 			auto counter = (unreadCount > 0) | 			displayUnreadMark, | ||||||
| 				? QString::number(unreadCount) | 			displayMentionBadge, | ||||||
| 				: QString(); | 			unreadCount, | ||||||
| 			const auto allowDigits = displayMentionBadge ? 1 : 3; | 			active, | ||||||
| 			if (counter.size() > allowDigits + 1) { | 			unreadMuted); | ||||||
| 				counter = qsl("..") + counter.mid(counter.size() - allowDigits); |  | ||||||
| 			} |  | ||||||
| 			auto unreadRight = st::dialogsPadding.x() + st::dialogsPhotoSize; |  | ||||||
| 			auto unreadTop = st::dialogsPadding.y() + st::dialogsPhotoSize - st::dialogsUnreadHeight; |  | ||||||
| 			auto unreadWidth = 0; |  | ||||||
| 
 |  | ||||||
| 			UnreadBadgeStyle st; |  | ||||||
| 			st.active = active; |  | ||||||
| 			st.muted = unreadMuted; |  | ||||||
| 			paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth); |  | ||||||
| 			skipBeforeMention += unreadWidth + st.padding; |  | ||||||
| 		} |  | ||||||
| 		if (displayMentionBadge) { |  | ||||||
| 			auto counter = qsl("@"); |  | ||||||
| 			auto unreadRight = st::dialogsPadding.x() + st::dialogsPhotoSize - skipBeforeMention; |  | ||||||
| 			auto unreadTop = st::dialogsPadding.y() + st::dialogsPhotoSize - st::dialogsUnreadHeight; |  | ||||||
| 			auto unreadWidth = 0; |  | ||||||
| 
 |  | ||||||
| 			UnreadBadgeStyle st; |  | ||||||
| 			st.active = active; |  | ||||||
| 			st.muted = false; |  | ||||||
| 			st.padding = 0; |  | ||||||
| 			st.textTop = 0; |  | ||||||
| 			paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth); |  | ||||||
| 		} |  | ||||||
| 	}; | 	}; | ||||||
| 	paintRow( | 	paintRow( | ||||||
| 		p, | 		p, | ||||||
|  | @ -590,7 +644,8 @@ void RowPainter::paint( | ||||||
| 		bool active, | 		bool active, | ||||||
| 		bool selected, | 		bool selected, | ||||||
| 		bool onlyBackground, | 		bool onlyBackground, | ||||||
| 		TimeMs ms) { | 		TimeMs ms, | ||||||
|  | 		bool displayUnreadInfo) { | ||||||
| 	auto item = row->item(); | 	auto item = row->item(); | ||||||
| 	auto history = item->history(); | 	auto history = item->history(); | ||||||
| 	auto cloudDraft = nullptr; | 	auto cloudDraft = nullptr; | ||||||
|  | @ -618,19 +673,63 @@ void RowPainter::paint( | ||||||
| 		} | 		} | ||||||
| 		return HistoryItem::DrawInDialog::Normal; | 		return HistoryItem::DrawInDialog::Normal; | ||||||
| 	}(); | 	}(); | ||||||
|  | 
 | ||||||
|  | 	const auto unreadCount = displayUnreadInfo | ||||||
|  | 		? history->chatListUnreadCount() | ||||||
|  | 		: 0; | ||||||
|  | 	const auto unreadMark = displayUnreadInfo | ||||||
|  | 		&& history->chatListUnreadMark(); | ||||||
|  | 	const auto unreadMuted = history->chatListMutedBadge(); | ||||||
|  | 	const auto displayMentionBadge = displayUnreadInfo | ||||||
|  | 		&& history->hasUnreadMentions(); | ||||||
|  | 	const auto displayUnreadCounter = (unreadCount > 0); | ||||||
|  | 	const auto displayUnreadMark = !displayUnreadCounter | ||||||
|  | 		&& !displayMentionBadge | ||||||
|  | 		&& unreadMark; | ||||||
|  | 	const auto displayPinnedIcon = false; | ||||||
|  | 
 | ||||||
| 	const auto paintItemCallback = [&](int nameleft, int namewidth) { | 	const auto paintItemCallback = [&](int nameleft, int namewidth) { | ||||||
| 		auto lastWidth = namewidth; | 		const auto texttop = st::dialogsPadding.y() | ||||||
| 		auto texttop = st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip; | 			+ st::msgNameFont->height | ||||||
|  | 			+ st::dialogsSkip; | ||||||
|  | 		const auto availableWidth = PaintWideCounter( | ||||||
|  | 			p, | ||||||
|  | 			texttop, | ||||||
|  | 			namewidth, | ||||||
|  | 			fullWidth, | ||||||
|  | 			displayUnreadCounter, | ||||||
|  | 			displayUnreadMark, | ||||||
|  | 			displayMentionBadge, | ||||||
|  | 			displayPinnedIcon, | ||||||
|  | 			unreadCount, | ||||||
|  | 			active, | ||||||
|  | 			selected, | ||||||
|  | 			unreadMuted); | ||||||
|  | 
 | ||||||
|  | 		const auto itemRect = QRect( | ||||||
|  | 			nameleft, | ||||||
|  | 			texttop, | ||||||
|  | 			availableWidth, | ||||||
|  | 			st::dialogsTextFont->height); | ||||||
| 		item->drawInDialog( | 		item->drawInDialog( | ||||||
| 			p, | 			p, | ||||||
| 			QRect(nameleft, texttop, lastWidth, st::dialogsTextFont->height), | 			itemRect, | ||||||
| 			active, | 			active, | ||||||
| 			selected, | 			selected, | ||||||
| 			drawInDialogWay, | 			drawInDialogWay, | ||||||
| 			row->_cacheFor, | 			row->_cacheFor, | ||||||
| 			row->_cache); | 			row->_cache); | ||||||
| 	}; | 	}; | ||||||
| 	const auto paintCounterCallback = [] {}; | 	const auto paintCounterCallback = [&] { | ||||||
|  | 		PaintNarrowCounter( | ||||||
|  | 			p, | ||||||
|  | 			displayUnreadCounter, | ||||||
|  | 			displayUnreadMark, | ||||||
|  | 			displayMentionBadge, | ||||||
|  | 			unreadCount, | ||||||
|  | 			active, | ||||||
|  | 			unreadMuted); | ||||||
|  | 	}; | ||||||
| 	const auto showSavedMessages = history->peer->isSelf() | 	const auto showSavedMessages = history->peer->isSelf() | ||||||
| 		&& !row->searchInChat(); | 		&& !row->searchInChat(); | ||||||
| 	const auto flags = (active ? Flag::Active : Flag(0)) | 	const auto flags = (active ? Flag::Active : Flag(0)) | ||||||
|  |  | ||||||
|  | @ -44,7 +44,8 @@ public: | ||||||
| 		bool active, | 		bool active, | ||||||
| 		bool selected, | 		bool selected, | ||||||
| 		bool onlyBackground, | 		bool onlyBackground, | ||||||
| 		TimeMs ms); | 		TimeMs ms, | ||||||
|  | 		bool displayUnreadInfo); | ||||||
| 	static QRect sendActionAnimationRect( | 	static QRect sendActionAnimationRect( | ||||||
| 		int animationWidth, | 		int animationWidth, | ||||||
| 		int animationHeight, | 		int animationHeight, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 John Preston
						John Preston