Support story link previews.
This commit is contained in:
parent
22b6f27f7b
commit
1b581a1597
|
@ -3702,6 +3702,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_view_button_background" = "View background";
|
"lng_view_button_background" = "View background";
|
||||||
"lng_view_button_theme" = "View theme";
|
"lng_view_button_theme" = "View theme";
|
||||||
"lng_view_button_message" = "View message";
|
"lng_view_button_message" = "View message";
|
||||||
|
"lng_view_button_story" = "View story";
|
||||||
"lng_view_button_voice_chat" = "Voice chat";
|
"lng_view_button_voice_chat" = "Voice chat";
|
||||||
"lng_view_button_voice_chat_channel" = "Live stream";
|
"lng_view_button_voice_chat_channel" = "Live stream";
|
||||||
"lng_view_button_request_join" = "Request to Join";
|
"lng_view_button_request_join" = "Request to Join";
|
||||||
|
|
|
@ -779,7 +779,7 @@ QString ApiWrap::exportDirectStoryLink(not_null<Data::Story*> story) {
|
||||||
const auto fallback = [&] {
|
const auto fallback = [&] {
|
||||||
const auto base = user->username();
|
const auto base = user->username();
|
||||||
const auto story = QString::number(storyId.story);
|
const auto story = QString::number(storyId.story);
|
||||||
const auto query = base + "/s" + story;
|
const auto query = base + "/s/" + story;
|
||||||
return session().createInternalLinkFull(query);
|
return session().createInternalLinkFull(query);
|
||||||
};
|
};
|
||||||
const auto i = _unlikelyStoryLinks.find(storyId);
|
const auto i = _unlikelyStoryLinks.find(storyId);
|
||||||
|
|
|
@ -1982,11 +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();
|
||||||
const auto maybeStory = stories->lookup(storyId);
|
if (const auto maybeStory = stories->lookup(storyId)) {
|
||||||
if (!maybeStory) {
|
parent->setText((*maybeStory)->caption());
|
||||||
|
} else {
|
||||||
if (maybeStory.error() == NoStory::Unknown) {
|
if (maybeStory.error() == NoStory::Unknown) {
|
||||||
stories->resolve(storyId, crl::guard(this, [=] {
|
stories->resolve(storyId, crl::guard(this, [=] {
|
||||||
_expired = !stories->lookup(storyId);
|
if (const auto maybeStory = stories->lookup(storyId)) {
|
||||||
|
parent->setText((*maybeStory)->caption());
|
||||||
|
} else {
|
||||||
|
_expired = true;
|
||||||
|
}
|
||||||
parent->history()->owner().requestItemViewRefresh(parent);
|
parent->history()->owner().requestItemViewRefresh(parent);
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
|
@ -2052,6 +2057,7 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
|
||||||
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 (!maybeStory) {
|
if (!maybeStory) {
|
||||||
|
realParent->setText(TextWithEntities());
|
||||||
if (maybeStory.error() == Data::NoStory::Deleted) {
|
if (maybeStory.error() == Data::NoStory::Deleted) {
|
||||||
_expired = true;
|
_expired = true;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -2065,6 +2071,7 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
|
||||||
}
|
}
|
||||||
_expired = false;
|
_expired = false;
|
||||||
const auto story = *maybeStory;
|
const auto story = *maybeStory;
|
||||||
|
realParent->setText(story->caption());
|
||||||
if (const auto photo = story->photo()) {
|
if (const auto photo = story->photo()) {
|
||||||
return std::make_unique<HistoryView::Photo>(
|
return std::make_unique<HistoryView::Photo>(
|
||||||
message,
|
message,
|
||||||
|
|
|
@ -3215,6 +3215,7 @@ not_null<WebPageData*> Session::processWebpage(const MTPDwebPagePending &data) {
|
||||||
QString(),
|
QString(),
|
||||||
QString(),
|
QString(),
|
||||||
TextWithEntities(),
|
TextWithEntities(),
|
||||||
|
FullStoryId(),
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
WebPageCollage(),
|
WebPageCollage(),
|
||||||
|
@ -3269,6 +3270,7 @@ not_null<WebPageData*> Session::webpage(
|
||||||
siteName,
|
siteName,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
|
FullStoryId(),
|
||||||
photo,
|
photo,
|
||||||
document,
|
document,
|
||||||
std::move(collage),
|
std::move(collage),
|
||||||
|
@ -3321,16 +3323,55 @@ void Session::webpageApplyFields(
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
auto story = (Data::Story*)nullptr;
|
||||||
|
auto storyId = FullStoryId();
|
||||||
|
if (const auto attributes = data.vattributes()) {
|
||||||
|
for (const auto &attribute : attributes->v) {
|
||||||
|
attribute.match([&](const MTPDwebPageAttributeStory &data) {
|
||||||
|
storyId = FullStoryId{
|
||||||
|
peerFromUser(data.vuser_id()),
|
||||||
|
data.vid().v,
|
||||||
|
};
|
||||||
|
if (const auto embed = data.vstory()) {
|
||||||
|
story = stories().applyFromWebpage(
|
||||||
|
peerFromUser(data.vuser_id()),
|
||||||
|
*embed);
|
||||||
|
} else if (const auto maybe = stories().lookup(storyId)) {
|
||||||
|
story = *maybe;
|
||||||
|
} else if (maybe.error() == Data::NoStory::Unknown) {
|
||||||
|
stories().resolve(storyId, [=] {
|
||||||
|
if (const auto maybe = stories().lookup(storyId)) {
|
||||||
|
const auto story = *maybe;
|
||||||
|
page->document = story->document();
|
||||||
|
page->photo = story->photo();
|
||||||
|
page->description = story->caption();
|
||||||
|
page->type = WebPageType::Story;
|
||||||
|
notifyWebPageUpdateDelayed(page);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [](const auto &) {});
|
||||||
|
}
|
||||||
|
}
|
||||||
webpageApplyFields(
|
webpageApplyFields(
|
||||||
page,
|
page,
|
||||||
ParseWebPageType(data),
|
(story ? WebPageType::Story : ParseWebPageType(data)),
|
||||||
qs(data.vurl()),
|
qs(data.vurl()),
|
||||||
qs(data.vdisplay_url()),
|
qs(data.vdisplay_url()),
|
||||||
siteName,
|
siteName,
|
||||||
qs(data.vtitle().value_or_empty()),
|
qs(data.vtitle().value_or_empty()),
|
||||||
description,
|
(story ? story->caption() : description),
|
||||||
photo ? processPhoto(*photo).get() : nullptr,
|
storyId,
|
||||||
document ? processDocument(*document).get() : lookupThemeDocument(),
|
(story
|
||||||
|
? story->photo()
|
||||||
|
: photo
|
||||||
|
? processPhoto(*photo).get()
|
||||||
|
: nullptr),
|
||||||
|
(story
|
||||||
|
? story->document()
|
||||||
|
: document
|
||||||
|
? processDocument(*document).get()
|
||||||
|
: lookupThemeDocument()),
|
||||||
WebPageCollage(this, data),
|
WebPageCollage(this, data),
|
||||||
data.vduration().value_or_empty(),
|
data.vduration().value_or_empty(),
|
||||||
qs(data.vauthor().value_or_empty()),
|
qs(data.vauthor().value_or_empty()),
|
||||||
|
@ -3345,6 +3386,7 @@ void Session::webpageApplyFields(
|
||||||
const QString &siteName,
|
const QString &siteName,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const TextWithEntities &description,
|
const TextWithEntities &description,
|
||||||
|
FullStoryId storyId,
|
||||||
PhotoData *photo,
|
PhotoData *photo,
|
||||||
DocumentData *document,
|
DocumentData *document,
|
||||||
WebPageCollage &&collage,
|
WebPageCollage &&collage,
|
||||||
|
@ -3359,6 +3401,7 @@ void Session::webpageApplyFields(
|
||||||
siteName,
|
siteName,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
|
storyId,
|
||||||
photo,
|
photo,
|
||||||
document,
|
document,
|
||||||
std::move(collage),
|
std::move(collage),
|
||||||
|
|
|
@ -811,6 +811,7 @@ private:
|
||||||
const QString &siteName,
|
const QString &siteName,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const TextWithEntities &description,
|
const TextWithEntities &description,
|
||||||
|
FullStoryId storyId,
|
||||||
PhotoData *photo,
|
PhotoData *photo,
|
||||||
DocumentData *document,
|
DocumentData *document,
|
||||||
WebPageCollage &&collage,
|
WebPageCollage &&collage,
|
||||||
|
|
|
@ -455,6 +455,17 @@ void Stories::apply(not_null<PeerData*> peer, const MTPUserStories *data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Story *Stories::applyFromWebpage(PeerId peerId, const MTPstoryItem &story) {
|
||||||
|
const auto idDates = parseAndApply(
|
||||||
|
_owner->peer(peerId),
|
||||||
|
story,
|
||||||
|
base::unixtime::now());
|
||||||
|
const auto value = idDates
|
||||||
|
? lookup({ peerId, idDates.id })
|
||||||
|
: base::make_unexpected(NoStory::Deleted);
|
||||||
|
return value ? value->get() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void Stories::requestUserStories(not_null<UserData*> user) {
|
void Stories::requestUserStories(not_null<UserData*> user) {
|
||||||
if (!_requestingUserStories.emplace(user).second) {
|
if (!_requestingUserStories.emplace(user).second) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -244,6 +244,7 @@ public:
|
||||||
void loadMore(StorySourcesList list);
|
void loadMore(StorySourcesList list);
|
||||||
void apply(const MTPDupdateStory &data);
|
void apply(const MTPDupdateStory &data);
|
||||||
void apply(not_null<PeerData*> peer, const MTPUserStories *data);
|
void apply(not_null<PeerData*> peer, const MTPUserStories *data);
|
||||||
|
Story *applyFromWebpage(PeerId peerId, const MTPstoryItem &story);
|
||||||
void loadAround(FullStoryId id, StoriesContext context);
|
void loadAround(FullStoryId id, StoriesContext context);
|
||||||
|
|
||||||
const StoriesSource *source(PeerId id) const;
|
const StoriesSource *source(PeerId id) const;
|
||||||
|
|
|
@ -152,6 +152,8 @@ WebPageType ParseWebPageType(
|
||||||
return WebPageType::WallPaper;
|
return WebPageType::WallPaper;
|
||||||
} else if (type == u"telegram_theme"_q) {
|
} else if (type == u"telegram_theme"_q) {
|
||||||
return WebPageType::Theme;
|
return WebPageType::Theme;
|
||||||
|
} else if (type == u"telegram_story"_q) {
|
||||||
|
return WebPageType::Story;
|
||||||
} else if (type == u"telegram_channel"_q) {
|
} else if (type == u"telegram_channel"_q) {
|
||||||
return WebPageType::Channel;
|
return WebPageType::Channel;
|
||||||
} else if (type == u"telegram_channel_request"_q) {
|
} else if (type == u"telegram_channel_request"_q) {
|
||||||
|
@ -214,6 +216,7 @@ bool WebPageData::applyChanges(
|
||||||
const QString &newSiteName,
|
const QString &newSiteName,
|
||||||
const QString &newTitle,
|
const QString &newTitle,
|
||||||
const TextWithEntities &newDescription,
|
const TextWithEntities &newDescription,
|
||||||
|
FullStoryId newStoryId,
|
||||||
PhotoData *newPhoto,
|
PhotoData *newPhoto,
|
||||||
DocumentData *newDocument,
|
DocumentData *newDocument,
|
||||||
WebPageCollage &&newCollage,
|
WebPageCollage &&newCollage,
|
||||||
|
@ -254,6 +257,7 @@ bool WebPageData::applyChanges(
|
||||||
&& siteName == resultSiteName
|
&& siteName == resultSiteName
|
||||||
&& title == resultTitle
|
&& title == resultTitle
|
||||||
&& description.text == newDescription.text
|
&& description.text == newDescription.text
|
||||||
|
&& storyId == newStoryId
|
||||||
&& photo == newPhoto
|
&& photo == newPhoto
|
||||||
&& document == newDocument
|
&& document == newDocument
|
||||||
&& collage.items == newCollage.items
|
&& collage.items == newCollage.items
|
||||||
|
@ -271,6 +275,7 @@ bool WebPageData::applyChanges(
|
||||||
siteName = resultSiteName;
|
siteName = resultSiteName;
|
||||||
title = resultTitle;
|
title = resultTitle;
|
||||||
description = newDescription;
|
description = newDescription;
|
||||||
|
storyId = newStoryId;
|
||||||
photo = newPhoto;
|
photo = newPhoto;
|
||||||
document = newDocument;
|
document = newDocument;
|
||||||
collage = std::move(newCollage);
|
collage = std::move(newCollage);
|
||||||
|
|
|
@ -35,6 +35,7 @@ enum class WebPageType {
|
||||||
|
|
||||||
WallPaper,
|
WallPaper,
|
||||||
Theme,
|
Theme,
|
||||||
|
Story,
|
||||||
|
|
||||||
Article,
|
Article,
|
||||||
ArticleWithIV,
|
ArticleWithIV,
|
||||||
|
@ -70,6 +71,7 @@ struct WebPageData {
|
||||||
const QString &newSiteName,
|
const QString &newSiteName,
|
||||||
const QString &newTitle,
|
const QString &newTitle,
|
||||||
const TextWithEntities &newDescription,
|
const TextWithEntities &newDescription,
|
||||||
|
FullStoryId newStoryId,
|
||||||
PhotoData *newPhoto,
|
PhotoData *newPhoto,
|
||||||
DocumentData *newDocument,
|
DocumentData *newDocument,
|
||||||
WebPageCollage &&newCollage,
|
WebPageCollage &&newCollage,
|
||||||
|
@ -89,6 +91,7 @@ struct WebPageData {
|
||||||
QString siteName;
|
QString siteName;
|
||||||
QString title;
|
QString title;
|
||||||
TextWithEntities description;
|
TextWithEntities description;
|
||||||
|
FullStoryId storyId;
|
||||||
int duration = 0;
|
int duration = 0;
|
||||||
QString author;
|
QString author;
|
||||||
PhotoData *photo = nullptr;
|
PhotoData *photo = nullptr;
|
||||||
|
|
|
@ -52,6 +52,8 @@ inline auto WebPageToPhrase(not_null<WebPageData*> webpage) {
|
||||||
const auto type = webpage->type;
|
const auto type = webpage->type;
|
||||||
return Ui::Text::Upper((type == WebPageType::Theme)
|
return Ui::Text::Upper((type == WebPageType::Theme)
|
||||||
? tr::lng_view_button_theme(tr::now)
|
? tr::lng_view_button_theme(tr::now)
|
||||||
|
: (type == WebPageType::Story)
|
||||||
|
? tr::lng_view_button_story(tr::now)
|
||||||
: (type == WebPageType::Message)
|
: (type == WebPageType::Message)
|
||||||
? tr::lng_view_button_message(tr::now)
|
? tr::lng_view_button_message(tr::now)
|
||||||
: (type == WebPageType::Group)
|
: (type == WebPageType::Group)
|
||||||
|
@ -139,6 +141,8 @@ bool ViewButton::MediaHasViewButton(
|
||||||
|| ((type == WebPageType::Theme)
|
|| ((type == WebPageType::Theme)
|
||||||
&& webpage->document
|
&& webpage->document
|
||||||
&& webpage->document->isTheme())
|
&& webpage->document->isTheme())
|
||||||
|
|| ((type == WebPageType::Story)
|
||||||
|
&& (webpage->photo || webpage->document))
|
||||||
|| ((type == WebPageType::WallPaper)
|
|| ((type == WebPageType::WallPaper)
|
||||||
&& webpage->document
|
&& webpage->document
|
||||||
&& webpage->document->isWallPaper());
|
&& webpage->document->isWallPaper());
|
||||||
|
|
|
@ -168,6 +168,7 @@ QSize WebPage::countOptimalSize() {
|
||||||
&& _data->photo
|
&& _data->photo
|
||||||
&& _data->type != WebPageType::Photo
|
&& _data->type != WebPageType::Photo
|
||||||
&& _data->type != WebPageType::Document
|
&& _data->type != WebPageType::Document
|
||||||
|
&& _data->type != WebPageType::Story
|
||||||
&& _data->type != WebPageType::Video) {
|
&& _data->type != WebPageType::Video) {
|
||||||
if (_data->type == WebPageType::Profile) {
|
if (_data->type == WebPageType::Profile) {
|
||||||
_asArticle = true;
|
_asArticle = true;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user