diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index fdd35ffdd..9a0a660b4 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -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}"; diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index 5a13cf2d5..cd9d863dc 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -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 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 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( - message, - realParent, - photo, - spoiler); - } else { - return std::make_unique( - message, - realParent, - story->document(), - spoiler); + if (!maybeStory) { + if (maybeStory.error() == Data::NoStory::Deleted) { + _expired = true; + return nullptr; } + _expired = false; + return std::make_unique( + message, + realParent, + realParent->history()->owner().photo(kLoadingStoryPhotoId), + spoiler); + } + _expired = false; + const auto story = *maybeStory; + if (const auto photo = story->photo()) { + return std::make_unique( + message, + realParent, + photo, + spoiler); + } else { + return std::make_unique( + message, + realParent, + story->document(), + spoiler); } - return std::make_unique( - message, - realParent, - realParent->history()->owner().photo(kLoadingStoryPhotoId), - spoiler); } } // namespace Data diff --git a/Telegram/SourceFiles/data/data_media_types.h b/Telegram/SourceFiles/data/data_media_types.h index 614d0333a..0ba84e928 100644 --- a/Telegram/SourceFiles/data/data_media_types.h +++ b/Telegram/SourceFiles/data/data_media_types.h @@ -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 clone(not_null 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; }; diff --git a/Telegram/SourceFiles/data/data_stories.cpp b/Telegram/SourceFiles/data/data_stories.cpp index 0d2e64bfa..3952f9712 100644 --- a/Telegram/SourceFiles/data/data_stories.cpp +++ b/Telegram/SourceFiles/data/data_stories.cpp @@ -742,11 +742,12 @@ void Stories::sendResolveRequests() { auto leftToSend = kMaxResolveTogether; auto byPeer = base::flat_map>(); 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 = { diff --git a/Telegram/SourceFiles/history/history_item_components.cpp b/Telegram/SourceFiles/history/history_item_components.cpp index ce9a8edf2..05289283e 100644 --- a/Telegram/SourceFiles/history/history_item_components.cpp +++ b/Telegram/SourceFiles/history/history_item_components.cpp @@ -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, diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 4d734bfcb..763978823 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -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 &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( diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index a2b9cb049..3faaa355b 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -536,6 +536,9 @@ private: virtual QSize performCountCurrentSize(int newWidth) = 0; void refreshMedia(Element *replacing); + void setTextWithLinks( + const TextWithEntities &text, + const std::vector &links = {}); struct TextWithLinks { TextWithEntities text; diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index e2892d105..ad06f53c4 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -1777,9 +1777,8 @@ void Message::unloadHeavyPart() { bool Message::showForwardsFromSender( not_null 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()) { - 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()) { return false; diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index efa945cc4..960a4cd16 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -72,7 +72,7 @@ Photo::Photo( , _spoiler(spoiler ? std::make_unique() : nullptr) { if (const auto media = realParent->media()) { if (media->storyId()) { - _story = true; + _story = 1; } } _caption = createCaption(realParent);