Highlight timestamps in replies to media.
This commit is contained in:
		
							parent
							
								
									90c54b1f2a
								
							
						
					
					
						commit
						1ba052cc13
					
				
					 8 changed files with 88 additions and 21 deletions
				
			
		|  | @ -358,6 +358,13 @@ void HistoryMessageReply::paint( | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | DocumentData *HistoryMessageReply::replyToDocument() const { | ||||||
|  | 	if (const auto media = replyToMsg ? replyToMsg->media() : nullptr) { | ||||||
|  | 		return media->document(); | ||||||
|  | 	} | ||||||
|  | 	return nullptr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ReplyMarkupClickHandler::ReplyMarkupClickHandler( | ReplyMarkupClickHandler::ReplyMarkupClickHandler( | ||||||
| 	int row, | 	int row, | ||||||
| 	int column, | 	int column, | ||||||
|  |  | ||||||
|  | @ -130,18 +130,20 @@ struct HistoryMessageReply : public RuntimeComponent<HistoryMessageReply, Histor | ||||||
| 		int w, | 		int w, | ||||||
| 		PaintFlags flags) const; | 		PaintFlags flags) const; | ||||||
| 
 | 
 | ||||||
| 	MsgId replyToId() const { | 	[[nodiscard]] MsgId replyToId() const { | ||||||
| 		return replyToMsgId; | 		return replyToMsgId; | ||||||
| 	} | 	} | ||||||
| 	int replyToWidth() const { | 	[[nodiscard]] int replyToWidth() const { | ||||||
| 		return maxReplyWidth; | 		return maxReplyWidth; | ||||||
| 	} | 	} | ||||||
| 	ClickHandlerPtr replyToLink() const { | 	[[nodiscard]] ClickHandlerPtr replyToLink() const { | ||||||
| 		return replyToLnk; | 		return replyToLnk; | ||||||
| 	} | 	} | ||||||
| 	void setReplyToLinkFrom( | 	void setReplyToLinkFrom( | ||||||
| 		not_null<HistoryMessage*> holder); | 		not_null<HistoryMessage*> holder); | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] DocumentData *replyToDocument() const; | ||||||
|  | 
 | ||||||
| 	MsgId replyToMsgId = 0; | 	MsgId replyToMsgId = 0; | ||||||
| 	HistoryItem *replyToMsg = nullptr; | 	HistoryItem *replyToMsg = nullptr; | ||||||
| 	ClickHandlerPtr replyToLnk; | 	ClickHandlerPtr replyToLnk; | ||||||
|  |  | ||||||
|  | @ -17,7 +17,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | ||||||
| #include "history/history_location_manager.h" | #include "history/history_location_manager.h" | ||||||
| #include "history/history_service.h" | #include "history/history_service.h" | ||||||
| #include "history/view/history_view_service_message.h" | #include "history/view/history_view_service_message.h" | ||||||
| #include "history/view/history_view_context_menu.h" // For CopyPostLink().
 | #include "history/view/history_view_context_menu.h" // CopyPostLink.
 | ||||||
|  | #include "history/view/media/history_view_media.h" // AddTimestampLinks.
 | ||||||
| #include "chat_helpers/stickers_emoji_pack.h" | #include "chat_helpers/stickers_emoji_pack.h" | ||||||
| #include "main/main_session.h" | #include "main/main_session.h" | ||||||
| #include "boxes/share_box.h" | #include "boxes/share_box.h" | ||||||
|  | @ -698,7 +699,13 @@ int HistoryMessage::viewsCount() const { | ||||||
| 
 | 
 | ||||||
| bool HistoryMessage::updateDependencyItem() { | bool HistoryMessage::updateDependencyItem() { | ||||||
| 	if (const auto reply = Get<HistoryMessageReply>()) { | 	if (const auto reply = Get<HistoryMessageReply>()) { | ||||||
| 		return reply->updateData(this, true); | 		const auto document = reply->replyToDocument(); | ||||||
|  | 		const auto result = reply->updateData(this, true); | ||||||
|  | 		if (document != reply->replyToDocument() | ||||||
|  | 			&& generateLocalEntitiesByReply()) { | ||||||
|  | 			reapplyText(); | ||||||
|  | 		} | ||||||
|  | 		return result; | ||||||
| 	} | 	} | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  | @ -1150,6 +1157,37 @@ Storage::SharedMediaTypesMask HistoryMessage::sharedMediaTypes() const { | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool HistoryMessage::generateLocalEntitiesByReply() const { | ||||||
|  | 	return !_media || _media->webpage(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TextWithEntities HistoryMessage::withLocalEntities( | ||||||
|  | 		const TextWithEntities &textWithEntities) const { | ||||||
|  | 	if (!generateLocalEntitiesByReply()) { | ||||||
|  | 		return textWithEntities; | ||||||
|  | 	} | ||||||
|  | 	if (const auto reply = Get<HistoryMessageReply>()) { | ||||||
|  | 		if (const auto document = reply->replyToDocument()) { | ||||||
|  | 			if (document->isVideoFile() || document->isSong()) { | ||||||
|  | 				using namespace HistoryView; | ||||||
|  | 				const auto duration = document->getDuration(); | ||||||
|  | 				const auto base = (duration > 0) | ||||||
|  | 					? DocumentTimestampLinkBase( | ||||||
|  | 						document, | ||||||
|  | 						reply->replyToMsg->fullId()) | ||||||
|  | 					: QString(); | ||||||
|  | 				if (!base.isEmpty()) { | ||||||
|  | 					return AddTimestampLinks( | ||||||
|  | 						textWithEntities, | ||||||
|  | 						duration, | ||||||
|  | 						base); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return textWithEntities; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void HistoryMessage::setText(const TextWithEntities &textWithEntities) { | void HistoryMessage::setText(const TextWithEntities &textWithEntities) { | ||||||
| 	for_const (auto &entity, textWithEntities.entities) { | 	for_const (auto &entity, textWithEntities.entities) { | ||||||
| 		auto type = entity.type(); | 		auto type = entity.type(); | ||||||
|  | @ -1168,7 +1206,7 @@ void HistoryMessage::setText(const TextWithEntities &textWithEntities) { | ||||||
| 	clearIsolatedEmoji(); | 	clearIsolatedEmoji(); | ||||||
| 	_text.setMarkedText( | 	_text.setMarkedText( | ||||||
| 		st::messageTextStyle, | 		st::messageTextStyle, | ||||||
| 		textWithEntities, | 		withLocalEntities(textWithEntities), | ||||||
| 		Ui::ItemTextOptions(this)); | 		Ui::ItemTextOptions(this)); | ||||||
| 	if (!textWithEntities.text.isEmpty() && _text.isEmpty()) { | 	if (!textWithEntities.text.isEmpty() && _text.isEmpty()) { | ||||||
| 		// If server has allowed some text that we've trim-ed entirely,
 | 		// If server has allowed some text that we've trim-ed entirely,
 | ||||||
|  | @ -1184,6 +1222,11 @@ void HistoryMessage::setText(const TextWithEntities &textWithEntities) { | ||||||
| 	_textHeight = 0; | 	_textHeight = 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void HistoryMessage::reapplyText() { | ||||||
|  | 	setText(originalText()); | ||||||
|  | 	history()->owner().requestItemResize(this); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void HistoryMessage::setEmptyText() { | void HistoryMessage::setEmptyText() { | ||||||
| 	clearIsolatedEmoji(); | 	clearIsolatedEmoji(); | ||||||
| 	_text.setMarkedText( | 	_text.setMarkedText( | ||||||
|  | @ -1309,8 +1352,13 @@ void HistoryMessage::setRealId(MsgId newId) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void HistoryMessage::dependencyItemRemoved(HistoryItem *dependency) { | void HistoryMessage::dependencyItemRemoved(HistoryItem *dependency) { | ||||||
| 	if (auto reply = Get<HistoryMessageReply>()) { | 	if (const auto reply = Get<HistoryMessageReply>()) { | ||||||
|  | 		const auto document = reply->replyToDocument(); | ||||||
| 		reply->itemRemoved(this, dependency); | 		reply->itemRemoved(this, dependency); | ||||||
|  | 		if (document != reply->replyToDocument() | ||||||
|  | 			&& generateLocalEntitiesByReply()) { | ||||||
|  | 			reapplyText(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -198,6 +198,10 @@ private: | ||||||
| 		const MTPDmessageFwdHeader &data); | 		const MTPDmessageFwdHeader &data); | ||||||
| 
 | 
 | ||||||
| 	void refreshMessageBadge(); | 	void refreshMessageBadge(); | ||||||
|  | 	[[nodiscard]] bool generateLocalEntitiesByReply() const; | ||||||
|  | 	[[nodiscard]] TextWithEntities withLocalEntities( | ||||||
|  | 		const TextWithEntities &textWithEntities) const; | ||||||
|  | 	void reapplyText(); | ||||||
| 
 | 
 | ||||||
| 	Ui::Text::String _messageBadge; | 	Ui::Text::String _messageBadge; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -423,7 +423,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms | ||||||
| 	if (radial | 	if (radial | ||||||
| 		|| (!streamingMode | 		|| (!streamingMode | ||||||
| 			&& ((!_data->loaded() && !_data->loading()) || !autoplay))) { | 			&& ((!_data->loaded() && !_data->loading()) || !autoplay))) { | ||||||
| 		const auto radialOpacity = item->isSending() | 		const auto radialOpacity = (item->isSending() || _data->uploading()) | ||||||
| 			? 1. | 			? 1. | ||||||
| 			: streamed | 			: streamed | ||||||
| 			? streamed->waitingOpacity() | 			? streamed->waitingOpacity() | ||||||
|  | @ -873,6 +873,7 @@ void Gif::drawGrouped( | ||||||
| 	if (displayLoading | 	if (displayLoading | ||||||
| 		&& (!streamed | 		&& (!streamed | ||||||
| 			|| item->isSending() | 			|| item->isSending() | ||||||
|  | 			|| _data->uploading() | ||||||
| 			|| (cornerDownload && _data->loading()))) { | 			|| (cornerDownload && _data->loading()))) { | ||||||
| 		ensureAnimation(); | 		ensureAnimation(); | ||||||
| 		if (!_animation->radial.animating()) { | 		if (!_animation->radial.animating()) { | ||||||
|  | @ -930,7 +931,7 @@ void Gif::drawGrouped( | ||||||
| 	if (radial | 	if (radial | ||||||
| 		|| (!streamingMode | 		|| (!streamingMode | ||||||
| 			&& ((!_data->loaded() && !_data->loading()) || !autoplay))) { | 			&& ((!_data->loaded() && !_data->loading()) || !autoplay))) { | ||||||
| 		const auto radialOpacity = item->isSending() | 		const auto radialOpacity = (item->isSending() || _data->uploading()) | ||||||
| 			? 1. | 			? 1. | ||||||
| 			: streamed | 			: streamed | ||||||
| 			? streamed->waitingOpacity() | 			? streamed->waitingOpacity() | ||||||
|  | @ -1423,6 +1424,7 @@ bool Gif::dataLoaded() const { | ||||||
| bool Gif::needInfoDisplay() const { | bool Gif::needInfoDisplay() const { | ||||||
| 	return _data->isVideoFile() | 	return _data->isVideoFile() | ||||||
| 		|| _parent->data()->isSending() | 		|| _parent->data()->isSending() | ||||||
|  | 		|| _data->uploading() | ||||||
| 		|| _parent->isUnderCursor(); | 		|| _parent->isUnderCursor(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -32,7 +32,17 @@ namespace { | ||||||
| 	return (ok1 && ok2 && ok3) ? result : -1; | 	return (ok1 && ok2 && ok3) ? result : -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [[nodiscard]] TextWithEntities AddTimestampLinks( | } // namespace
 | ||||||
|  | 
 | ||||||
|  | QString DocumentTimestampLinkBase( | ||||||
|  | 		not_null<DocumentData*> document, | ||||||
|  | 		FullMsgId context) { | ||||||
|  | 	return QString( | ||||||
|  | 		"doc%1_%2_%3" | ||||||
|  | 	).arg(document->id).arg(context.channel).arg(context.msg); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TextWithEntities AddTimestampLinks( | ||||||
| 		TextWithEntities text, | 		TextWithEntities text, | ||||||
| 		TimeId duration, | 		TimeId duration, | ||||||
| 		const QString &base) { | 		const QString &base) { | ||||||
|  | @ -92,16 +102,6 @@ namespace { | ||||||
| 	return text; | 	return text; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 |  | ||||||
| 
 |  | ||||||
| QString DocumentTimestampLinkBase( |  | ||||||
| 		not_null<DocumentData*> document, |  | ||||||
| 		FullMsgId context) { |  | ||||||
| 	return QString( |  | ||||||
| 		"doc%1_%2_%3" |  | ||||||
| 	).arg(document->id).arg(context.channel).arg(context.msg); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Storage::SharedMediaTypesMask Media::sharedMediaTypes() const { | Storage::SharedMediaTypesMask Media::sharedMediaTypes() const { | ||||||
| 	return {}; | 	return {}; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -43,6 +43,10 @@ enum class MediaInBubbleState { | ||||||
| [[nodiscard]] QString DocumentTimestampLinkBase( | [[nodiscard]] QString DocumentTimestampLinkBase( | ||||||
| 	not_null<DocumentData*> document, | 	not_null<DocumentData*> document, | ||||||
| 	FullMsgId context); | 	FullMsgId context); | ||||||
|  | [[nodiscard]] TextWithEntities AddTimestampLinks( | ||||||
|  | 	TextWithEntities text, | ||||||
|  | 	TimeId duration, | ||||||
|  | 	const QString &base); | ||||||
| 
 | 
 | ||||||
| class Media : public Object { | class Media : public Object { | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| Subproject commit 65eb03a6a78ffe09cd8f644edfe14560854b89eb | Subproject commit 6b673d9154cd596b9c648b130f334c166af36875 | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 John Preston
						John Preston