Improved shared story layout.

This commit is contained in:
John Preston 2023-06-13 13:36:17 +04:00
parent c133f4de69
commit 1c41df364c
9 changed files with 107 additions and 56 deletions

View file

@ -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_context_about_private_link" = "This link will only work for members of this chat.";
"lng_forwarded" = "Forwarded from {user}"; "lng_forwarded" = "Forwarded from {user}";
"lng_forwarded_story" = "Story from {user}";
"lng_forwarded_date" = "Original: {date}"; "lng_forwarded_date" = "Original: {date}";
"lng_forwarded_channel" = "Forwarded from {channel}"; "lng_forwarded_channel" = "Forwarded from {channel}";
"lng_forwarded_psa_default" = "Forwarded from {channel}"; "lng_forwarded_psa_default" = "Forwarded from {channel}";

View file

@ -410,6 +410,10 @@ FullStoryId Media::storyId() const {
return {}; return {};
} }
bool Media::storyExpired() const {
return false;
}
bool Media::uploading() const { bool Media::uploading() const {
return false; return false;
} }
@ -1978,12 +1982,16 @@ MediaStory::MediaStory(not_null<HistoryItem*> parent, FullStoryId storyId)
: Media(parent) : Media(parent)
, _storyId(storyId) { , _storyId(storyId) {
const auto stories = &parent->history()->owner().stories(); const auto stories = &parent->history()->owner().stories();
if (!stories->lookup(storyId)) { const auto maybeStory = stories->lookup(storyId);
stories->resolve(storyId, crl::guard(this, [=] { if (!maybeStory) {
if (stories->lookup(storyId)) { if (maybeStory.error() == NoStory::Unknown) {
stories->resolve(storyId, crl::guard(this, [=] {
_expired = !stories->lookup(storyId);
parent->history()->owner().requestItemViewRefresh(parent); parent->history()->owner().requestItemViewRefresh(parent);
} }));
})); } else {
_expired = true;
}
} }
} }
@ -1995,6 +2003,10 @@ FullStoryId MediaStory::storyId() const {
return _storyId; return _storyId;
} }
bool MediaStory::storyExpired() const {
return _expired;
}
TextWithEntities MediaStory::notificationText() const { TextWithEntities MediaStory::notificationText() const {
const auto stories = &parent()->history()->owner().stories(); const auto stories = &parent()->history()->owner().stories();
const auto maybeStory = stories->lookup(_storyId); const auto maybeStory = stories->lookup(_storyId);
@ -2015,6 +2027,10 @@ TextForMimeData MediaStory::clipboardText() const {
parent()->clipboardText()); parent()->clipboardText());
} }
bool MediaStory::dropForwardedInfo() const {
return true;
}
bool MediaStory::updateInlineResultMedia(const MTPMessageMedia &media) { bool MediaStory::updateInlineResultMedia(const MTPMessageMedia &media) {
return false; return false;
} }
@ -2030,26 +2046,33 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
const auto spoiler = false; const auto spoiler = false;
const auto stories = &parent()->history()->owner().stories(); const auto stories = &parent()->history()->owner().stories();
const auto maybeStory = stories->lookup(_storyId); const auto maybeStory = stories->lookup(_storyId);
if (const auto story = maybeStory ? maybeStory->get() : nullptr) { if (!maybeStory) {
if (const auto photo = story->photo()) { if (maybeStory.error() == Data::NoStory::Deleted) {
return std::make_unique<HistoryView::Photo>( _expired = true;
message, return nullptr;
realParent,
photo,
spoiler);
} else {
return std::make_unique<HistoryView::Gif>(
message,
realParent,
story->document(),
spoiler);
} }
_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 } // namespace Data

View file

@ -112,6 +112,7 @@ public:
virtual PollData *poll() const; virtual PollData *poll() const;
virtual const WallPaper *paper() const; virtual const WallPaper *paper() const;
virtual FullStoryId storyId() const; virtual FullStoryId storyId() const;
virtual bool storyExpired() const;
virtual bool uploading() const; virtual bool uploading() const;
virtual Storage::SharedMediaTypesMask sharedMediaTypes() const; virtual Storage::SharedMediaTypesMask sharedMediaTypes() const;
@ -571,11 +572,13 @@ public:
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override; 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; TextWithEntities notificationText() const override;
QString pinnedTextSubstring() const override; QString pinnedTextSubstring() const override;
TextForMimeData clipboardText() const override; TextForMimeData clipboardText() const override;
bool dropForwardedInfo() const override;
bool updateInlineResultMedia(const MTPMessageMedia &media) override; bool updateInlineResultMedia(const MTPMessageMedia &media) override;
bool updateSentMedia(const MTPMessageMedia &media) override; bool updateSentMedia(const MTPMessageMedia &media) override;
@ -586,6 +589,7 @@ public:
private: private:
const FullStoryId _storyId; const FullStoryId _storyId;
bool _expired = false;
}; };

View file

@ -742,11 +742,12 @@ void Stories::sendResolveRequests() {
auto leftToSend = kMaxResolveTogether; auto leftToSend = kMaxResolveTogether;
auto byPeer = base::flat_map<PeerId, QVector<MTPint>>(); auto byPeer = base::flat_map<PeerId, QVector<MTPint>>();
for (auto i = begin(_resolvePending); i != end(_resolvePending);) { 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]; auto &sent = _resolveSent[peerId];
if (ids.size() <= leftToSend) { if (ids.size() <= leftToSend) {
sent = base::take(ids); sent = base::take(ids);
i = _resolvePending.erase(i); i = _resolvePending.erase(i); // Invalidates `ids`.
leftToSend -= int(sent.size()); leftToSend -= int(sent.size());
} else { } else {
sent = { sent = {

View file

@ -192,7 +192,13 @@ void HistoryMessageForwarded::create(const HistoryMessageVia *via) const {
} else { } else {
phrase = name; 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) { if (fromChannel) {
phrase = tr::lng_forwarded_channel_via( phrase = tr::lng_forwarded_channel_via(
tr::now, tr::now,

View file

@ -839,14 +839,15 @@ auto Element::contextDependentServiceText() -> TextWithLinks {
void Element::validateText() { void Element::validateText() {
const auto item = data(); const auto item = data();
const auto &text = item->_text; const auto &text = item->_text;
if (_text.isEmpty() == text.empty()) { const auto media = item->media();
return; if (media && media->storyExpired()) {
} _media = nullptr;
const auto context = Core::MarkedTextContext{ if (_text.isEmpty()) {
.session = &history()->session(), setTextWithLinks(
.customEmojiRepaint = [=] { customEmojiRepaint(); }, Ui::Text::Italic(u"This story has expired"_q));
}; }
if (_flags & Flag::ServiceMessage) { } else if (_text.isEmpty() == text.empty()) {
} else if (_flags & Flag::ServiceMessage) {
const auto contextDependentText = contextDependentServiceText(); const auto contextDependentText = contextDependentServiceText();
const auto &markedText = contextDependentText.text.empty() const auto &markedText = contextDependentText.text.empty()
? text ? text
@ -854,28 +855,33 @@ void Element::validateText() {
const auto &customLinks = contextDependentText.text.empty() const auto &customLinks = contextDependentText.text.empty()
? item->customTextLinks() ? item->customTextLinks()
: contextDependentText.links; : contextDependentText.links;
_text.setMarkedText( setTextWithLinks(markedText, customLinks);
st::serviceTextStyle, } else {
markedText, setTextWithLinks(item->translatedTextWithLocalEntities());
Ui::ItemTextServiceOptions(), }
context); }
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; auto linkIndex = 0;
for (const auto &link : customLinks) { for (const auto &link : links) {
// Link indices start with 1. // Link indices start with 1.
_text.setLink(++linkIndex, link); _text.setLink(++linkIndex, link);
} }
} else { } else {
const auto item = data();
const auto &options = Ui::ItemTextOptions(item);
clearSpecialOnlyEmoji(); clearSpecialOnlyEmoji();
const auto context = Core::MarkedTextContext{ _text.setMarkedText(st::messageTextStyle, text, options, context);
.session = &history()->session(), if (!item->_text.empty() && _text.isEmpty()){
.customEmojiRepaint = [=] { customEmojiRepaint(); },
};
_text.setMarkedText(
st::messageTextStyle,
item->translatedTextWithLocalEntities(),
Ui::ItemTextOptions(item),
context);
if (!text.empty() && _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,
// just replace it with something so that UI won't look buggy. // just replace it with something so that UI won't look buggy.
_text.setMarkedText( _text.setMarkedText(

View file

@ -536,6 +536,9 @@ private:
virtual QSize performCountCurrentSize(int newWidth) = 0; virtual QSize performCountCurrentSize(int newWidth) = 0;
void refreshMedia(Element *replacing); void refreshMedia(Element *replacing);
void setTextWithLinks(
const TextWithEntities &text,
const std::vector<ClickHandlerPtr> &links = {});
struct TextWithLinks { struct TextWithLinks {
TextWithEntities text; TextWithEntities text;

View file

@ -1777,9 +1777,8 @@ void Message::unloadHeavyPart() {
bool Message::showForwardsFromSender( bool Message::showForwardsFromSender(
not_null<HistoryMessageForwarded*> forwarded) const { not_null<HistoryMessageForwarded*> forwarded) const {
const auto peer = data()->history()->peer; const auto peer = data()->history()->peer;
return peer->isSelf() return !forwarded->story
|| peer->isRepliesChat() && (peer->isSelf() || peer->isRepliesChat() || forwarded->imported);
|| forwarded->imported;
} }
bool Message::hasFromPhoto() const { bool Message::hasFromPhoto() const {
@ -2877,7 +2876,9 @@ bool Message::displayFromName() const {
bool Message::displayForwardedFrom() const { bool Message::displayForwardedFrom() const {
const auto item = data(); const auto item = data();
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) { if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
if (showForwardsFromSender(forwarded)) { if (forwarded->story) {
return true;
} else if (showForwardsFromSender(forwarded)) {
return false; return false;
} }
if (const auto sender = item->discussionPostOriginalSender()) { if (const auto sender = item->discussionPostOriginalSender()) {
@ -3685,6 +3686,9 @@ bool Message::needInfoDisplay() const {
bool Message::hasVisibleText() const { bool Message::hasVisibleText() const {
if (data()->emptyText()) { if (data()->emptyText()) {
if (const auto media = data()->media()) {
return media->storyExpired();
}
return false; return false;
} }
const auto media = this->media(); const auto media = this->media();
@ -3713,6 +3717,9 @@ void Message::refreshInfoSkipBlock() {
const auto media = this->media(); const auto media = this->media();
const auto hasTextSkipBlock = [&] { const auto hasTextSkipBlock = [&] {
if (item->_text.empty()) { if (item->_text.empty()) {
if (const auto media = data()->media()) {
return media->storyExpired();
}
return false; return false;
} else if (item->Has<HistoryMessageLogEntryOriginal>()) { } else if (item->Has<HistoryMessageLogEntryOriginal>()) {
return false; return false;

View file

@ -72,7 +72,7 @@ Photo::Photo(
, _spoiler(spoiler ? std::make_unique<MediaSpoiler>() : nullptr) { , _spoiler(spoiler ? std::make_unique<MediaSpoiler>() : nullptr) {
if (const auto media = realParent->media()) { if (const auto media = realParent->media()) {
if (media->storyId()) { if (media->storyId()) {
_story = true; _story = 1;
} }
} }
_caption = createCaption(realParent); _caption = createCaption(realParent);