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_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}";

View File

@ -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

View File

@ -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;
};

View File

@ -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 = {

View File

@ -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,

View File

@ -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(

View File

@ -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;

View File

@ -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;

View File

@ -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);