Improved shared story layout.
This commit is contained in:
		
							parent
							
								
									c133f4de69
								
							
						
					
					
						commit
						1c41df364c
					
				
					 9 changed files with 107 additions and 56 deletions
				
			
		| 
						 | 
				
			
			@ -1699,6 +1699,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
			
		|||
"lng_context_about_private_link" = "This link will only work for members of this chat.";
 | 
			
		||||
 | 
			
		||||
"lng_forwarded" = "Forwarded from {user}";
 | 
			
		||||
"lng_forwarded_story" = "Story from {user}";
 | 
			
		||||
"lng_forwarded_date" = "Original: {date}";
 | 
			
		||||
"lng_forwarded_channel" = "Forwarded from {channel}";
 | 
			
		||||
"lng_forwarded_psa_default" = "Forwarded from {channel}";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -410,6 +410,10 @@ FullStoryId Media::storyId() const {
 | 
			
		|||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Media::storyExpired() const {
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Media::uploading() const {
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1978,12 +1982,16 @@ MediaStory::MediaStory(not_null<HistoryItem*> parent, FullStoryId storyId)
 | 
			
		|||
: Media(parent)
 | 
			
		||||
, _storyId(storyId) {
 | 
			
		||||
	const auto stories = &parent->history()->owner().stories();
 | 
			
		||||
	if (!stories->lookup(storyId)) {
 | 
			
		||||
		stories->resolve(storyId, crl::guard(this, [=] {
 | 
			
		||||
			if (stories->lookup(storyId)) {
 | 
			
		||||
	const auto maybeStory = stories->lookup(storyId);
 | 
			
		||||
	if (!maybeStory) {
 | 
			
		||||
		if (maybeStory.error() == NoStory::Unknown) {
 | 
			
		||||
			stories->resolve(storyId, crl::guard(this, [=] {
 | 
			
		||||
				_expired = !stories->lookup(storyId);
 | 
			
		||||
				parent->history()->owner().requestItemViewRefresh(parent);
 | 
			
		||||
			}
 | 
			
		||||
		}));
 | 
			
		||||
			}));
 | 
			
		||||
		} else {
 | 
			
		||||
			_expired = true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1995,6 +2003,10 @@ FullStoryId MediaStory::storyId() const {
 | 
			
		|||
	return _storyId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MediaStory::storyExpired() const {
 | 
			
		||||
	return _expired;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextWithEntities MediaStory::notificationText() const {
 | 
			
		||||
	const auto stories = &parent()->history()->owner().stories();
 | 
			
		||||
	const auto maybeStory = stories->lookup(_storyId);
 | 
			
		||||
| 
						 | 
				
			
			@ -2015,6 +2027,10 @@ TextForMimeData MediaStory::clipboardText() const {
 | 
			
		|||
		parent()->clipboardText());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MediaStory::dropForwardedInfo() const {
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MediaStory::updateInlineResultMedia(const MTPMessageMedia &media) {
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2030,26 +2046,33 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
 | 
			
		|||
	const auto spoiler = false;
 | 
			
		||||
	const auto stories = &parent()->history()->owner().stories();
 | 
			
		||||
	const auto maybeStory = stories->lookup(_storyId);
 | 
			
		||||
	if (const auto story = maybeStory ? maybeStory->get() : nullptr) {
 | 
			
		||||
		if (const auto photo = story->photo()) {
 | 
			
		||||
			return std::make_unique<HistoryView::Photo>(
 | 
			
		||||
				message,
 | 
			
		||||
				realParent,
 | 
			
		||||
				photo,
 | 
			
		||||
				spoiler);
 | 
			
		||||
		} else {
 | 
			
		||||
			return std::make_unique<HistoryView::Gif>(
 | 
			
		||||
				message,
 | 
			
		||||
				realParent,
 | 
			
		||||
				story->document(),
 | 
			
		||||
				spoiler);
 | 
			
		||||
	if (!maybeStory) {
 | 
			
		||||
		if (maybeStory.error() == Data::NoStory::Deleted) {
 | 
			
		||||
			_expired = true;
 | 
			
		||||
			return nullptr;
 | 
			
		||||
		}
 | 
			
		||||
		_expired = false;
 | 
			
		||||
		return std::make_unique<HistoryView::Photo>(
 | 
			
		||||
			message,
 | 
			
		||||
			realParent,
 | 
			
		||||
			realParent->history()->owner().photo(kLoadingStoryPhotoId),
 | 
			
		||||
			spoiler);
 | 
			
		||||
	}
 | 
			
		||||
	_expired = false;
 | 
			
		||||
	const auto story = *maybeStory;
 | 
			
		||||
	if (const auto photo = story->photo()) {
 | 
			
		||||
		return std::make_unique<HistoryView::Photo>(
 | 
			
		||||
			message,
 | 
			
		||||
			realParent,
 | 
			
		||||
			photo,
 | 
			
		||||
			spoiler);
 | 
			
		||||
	} else {
 | 
			
		||||
		return std::make_unique<HistoryView::Gif>(
 | 
			
		||||
			message,
 | 
			
		||||
			realParent,
 | 
			
		||||
			story->document(),
 | 
			
		||||
			spoiler);
 | 
			
		||||
	}
 | 
			
		||||
	return std::make_unique<HistoryView::Photo>(
 | 
			
		||||
		message,
 | 
			
		||||
		realParent,
 | 
			
		||||
		realParent->history()->owner().photo(kLoadingStoryPhotoId),
 | 
			
		||||
		spoiler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Data
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,6 +112,7 @@ public:
 | 
			
		|||
	virtual PollData *poll() const;
 | 
			
		||||
	virtual const WallPaper *paper() const;
 | 
			
		||||
	virtual FullStoryId storyId() const;
 | 
			
		||||
	virtual bool storyExpired() const;
 | 
			
		||||
 | 
			
		||||
	virtual bool uploading() const;
 | 
			
		||||
	virtual Storage::SharedMediaTypesMask sharedMediaTypes() const;
 | 
			
		||||
| 
						 | 
				
			
			@ -571,11 +572,13 @@ public:
 | 
			
		|||
 | 
			
		||||
	std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] FullStoryId storyId() const override;
 | 
			
		||||
	FullStoryId storyId() const override;
 | 
			
		||||
	bool storyExpired() const override;
 | 
			
		||||
 | 
			
		||||
	TextWithEntities notificationText() const override;
 | 
			
		||||
	QString pinnedTextSubstring() const override;
 | 
			
		||||
	TextForMimeData clipboardText() const override;
 | 
			
		||||
	bool dropForwardedInfo() const override;
 | 
			
		||||
 | 
			
		||||
	bool updateInlineResultMedia(const MTPMessageMedia &media) override;
 | 
			
		||||
	bool updateSentMedia(const MTPMessageMedia &media) override;
 | 
			
		||||
| 
						 | 
				
			
			@ -586,6 +589,7 @@ public:
 | 
			
		|||
 | 
			
		||||
private:
 | 
			
		||||
	const FullStoryId _storyId;
 | 
			
		||||
	bool _expired = false;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -742,11 +742,12 @@ void Stories::sendResolveRequests() {
 | 
			
		|||
	auto leftToSend = kMaxResolveTogether;
 | 
			
		||||
	auto byPeer = base::flat_map<PeerId, QVector<MTPint>>();
 | 
			
		||||
	for (auto i = begin(_resolvePending); i != end(_resolvePending);) {
 | 
			
		||||
		auto &[peerId, ids] = *i;
 | 
			
		||||
		const auto peerId = i->first;
 | 
			
		||||
		auto &ids = i->second;
 | 
			
		||||
		auto &sent = _resolveSent[peerId];
 | 
			
		||||
		if (ids.size() <= leftToSend) {
 | 
			
		||||
			sent = base::take(ids);
 | 
			
		||||
			i = _resolvePending.erase(i);
 | 
			
		||||
			i = _resolvePending.erase(i); // Invalidates `ids`.
 | 
			
		||||
			leftToSend -= int(sent.size());
 | 
			
		||||
		} else {
 | 
			
		||||
			sent = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -192,7 +192,13 @@ void HistoryMessageForwarded::create(const HistoryMessageVia *via) const {
 | 
			
		|||
	} else {
 | 
			
		||||
		phrase = name;
 | 
			
		||||
	}
 | 
			
		||||
	if (via && psaType.isEmpty()) {
 | 
			
		||||
	if (story) {
 | 
			
		||||
		phrase = tr::lng_forwarded_story(
 | 
			
		||||
			tr::now,
 | 
			
		||||
			lt_user,
 | 
			
		||||
			Ui::Text::Link(phrase.text, QString()), // Link 1.
 | 
			
		||||
			Ui::Text::WithEntities);
 | 
			
		||||
	} else if (via && psaType.isEmpty()) {
 | 
			
		||||
		if (fromChannel) {
 | 
			
		||||
			phrase = tr::lng_forwarded_channel_via(
 | 
			
		||||
				tr::now,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -839,14 +839,15 @@ auto Element::contextDependentServiceText() -> TextWithLinks {
 | 
			
		|||
void Element::validateText() {
 | 
			
		||||
	const auto item = data();
 | 
			
		||||
	const auto &text = item->_text;
 | 
			
		||||
	if (_text.isEmpty() == text.empty()) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	const auto context = Core::MarkedTextContext{
 | 
			
		||||
		.session = &history()->session(),
 | 
			
		||||
		.customEmojiRepaint = [=] { customEmojiRepaint(); },
 | 
			
		||||
	};
 | 
			
		||||
	if (_flags & Flag::ServiceMessage) {
 | 
			
		||||
	const auto media = item->media();
 | 
			
		||||
	if (media && media->storyExpired()) {
 | 
			
		||||
		_media = nullptr;
 | 
			
		||||
		if (_text.isEmpty()) {
 | 
			
		||||
			setTextWithLinks(
 | 
			
		||||
				Ui::Text::Italic(u"This story has expired"_q));
 | 
			
		||||
		}
 | 
			
		||||
	} else if (_text.isEmpty() == text.empty()) {
 | 
			
		||||
	} else if (_flags & Flag::ServiceMessage) {
 | 
			
		||||
		const auto contextDependentText = contextDependentServiceText();
 | 
			
		||||
		const auto &markedText = contextDependentText.text.empty()
 | 
			
		||||
			? text
 | 
			
		||||
| 
						 | 
				
			
			@ -854,28 +855,33 @@ void Element::validateText() {
 | 
			
		|||
		const auto &customLinks = contextDependentText.text.empty()
 | 
			
		||||
			? item->customTextLinks()
 | 
			
		||||
			: contextDependentText.links;
 | 
			
		||||
		_text.setMarkedText(
 | 
			
		||||
			st::serviceTextStyle,
 | 
			
		||||
			markedText,
 | 
			
		||||
			Ui::ItemTextServiceOptions(),
 | 
			
		||||
			context);
 | 
			
		||||
		setTextWithLinks(markedText, customLinks);
 | 
			
		||||
	} else {
 | 
			
		||||
		setTextWithLinks(item->translatedTextWithLocalEntities());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Element::setTextWithLinks(
 | 
			
		||||
		const TextWithEntities &text,
 | 
			
		||||
		const std::vector<ClickHandlerPtr> &links) {
 | 
			
		||||
	const auto context = Core::MarkedTextContext{
 | 
			
		||||
		.session = &history()->session(),
 | 
			
		||||
		.customEmojiRepaint = [=] { customEmojiRepaint(); },
 | 
			
		||||
	};
 | 
			
		||||
	if (_flags & Flag::ServiceMessage) {
 | 
			
		||||
		const auto &options = Ui::ItemTextServiceOptions();
 | 
			
		||||
		_text.setMarkedText(st::serviceTextStyle, text, options, context);
 | 
			
		||||
		auto linkIndex = 0;
 | 
			
		||||
		for (const auto &link : customLinks) {
 | 
			
		||||
		for (const auto &link : links) {
 | 
			
		||||
			// Link indices start with 1.
 | 
			
		||||
			_text.setLink(++linkIndex, link);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		const auto item = data();
 | 
			
		||||
		const auto &options = Ui::ItemTextOptions(item);
 | 
			
		||||
		clearSpecialOnlyEmoji();
 | 
			
		||||
		const auto context = Core::MarkedTextContext{
 | 
			
		||||
			.session = &history()->session(),
 | 
			
		||||
			.customEmojiRepaint = [=] { customEmojiRepaint(); },
 | 
			
		||||
		};
 | 
			
		||||
		_text.setMarkedText(
 | 
			
		||||
			st::messageTextStyle,
 | 
			
		||||
			item->translatedTextWithLocalEntities(),
 | 
			
		||||
			Ui::ItemTextOptions(item),
 | 
			
		||||
			context);
 | 
			
		||||
		if (!text.empty() && _text.isEmpty()) {
 | 
			
		||||
		_text.setMarkedText(st::messageTextStyle, text, options, context);
 | 
			
		||||
		if (!item->_text.empty() && _text.isEmpty()){
 | 
			
		||||
			// If server has allowed some text that we've trim-ed entirely,
 | 
			
		||||
			// just replace it with something so that UI won't look buggy.
 | 
			
		||||
			_text.setMarkedText(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -536,6 +536,9 @@ private:
 | 
			
		|||
	virtual QSize performCountCurrentSize(int newWidth) = 0;
 | 
			
		||||
 | 
			
		||||
	void refreshMedia(Element *replacing);
 | 
			
		||||
	void setTextWithLinks(
 | 
			
		||||
		const TextWithEntities &text,
 | 
			
		||||
		const std::vector<ClickHandlerPtr> &links = {});
 | 
			
		||||
 | 
			
		||||
	struct TextWithLinks {
 | 
			
		||||
		TextWithEntities text;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1777,9 +1777,8 @@ void Message::unloadHeavyPart() {
 | 
			
		|||
bool Message::showForwardsFromSender(
 | 
			
		||||
		not_null<HistoryMessageForwarded*> forwarded) const {
 | 
			
		||||
	const auto peer = data()->history()->peer;
 | 
			
		||||
	return peer->isSelf()
 | 
			
		||||
		|| peer->isRepliesChat()
 | 
			
		||||
		|| forwarded->imported;
 | 
			
		||||
	return !forwarded->story
 | 
			
		||||
		&& (peer->isSelf() || peer->isRepliesChat() || forwarded->imported);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Message::hasFromPhoto() const {
 | 
			
		||||
| 
						 | 
				
			
			@ -2877,7 +2876,9 @@ bool Message::displayFromName() const {
 | 
			
		|||
bool Message::displayForwardedFrom() const {
 | 
			
		||||
	const auto item = data();
 | 
			
		||||
	if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
 | 
			
		||||
		if (showForwardsFromSender(forwarded)) {
 | 
			
		||||
		if (forwarded->story) {
 | 
			
		||||
			return true;
 | 
			
		||||
		} else if (showForwardsFromSender(forwarded)) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		if (const auto sender = item->discussionPostOriginalSender()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3685,6 +3686,9 @@ bool Message::needInfoDisplay() const {
 | 
			
		|||
 | 
			
		||||
bool Message::hasVisibleText() const {
 | 
			
		||||
	if (data()->emptyText()) {
 | 
			
		||||
		if (const auto media = data()->media()) {
 | 
			
		||||
			return media->storyExpired();
 | 
			
		||||
		}
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	const auto media = this->media();
 | 
			
		||||
| 
						 | 
				
			
			@ -3713,6 +3717,9 @@ void Message::refreshInfoSkipBlock() {
 | 
			
		|||
	const auto media = this->media();
 | 
			
		||||
	const auto hasTextSkipBlock = [&] {
 | 
			
		||||
		if (item->_text.empty()) {
 | 
			
		||||
			if (const auto media = data()->media()) {
 | 
			
		||||
				return media->storyExpired();
 | 
			
		||||
			}
 | 
			
		||||
			return false;
 | 
			
		||||
		} else if (item->Has<HistoryMessageLogEntryOriginal>()) {
 | 
			
		||||
			return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,7 +72,7 @@ Photo::Photo(
 | 
			
		|||
, _spoiler(spoiler ? std::make_unique<MediaSpoiler>() : nullptr) {
 | 
			
		||||
	if (const auto media = realParent->media()) {
 | 
			
		||||
		if (media->storyId()) {
 | 
			
		||||
			_story = true;
 | 
			
		||||
			_story = 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	_caption = createCaption(realParent);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue