/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "editor/editor_message_source.h" #include "base/unixtime.h" #include "data/data_groups.h" #include "data/data_media_types.h" #include "data/data_peer.h" #include "data/data_session.h" #include "data/data_web_page.h" #include "editor/editor_message_video.h" #include "history/history.h" #include "history/history_item.h" #include "history/view/history_view_fake_items.h" #include "main/main_session.h" namespace Editor { namespace { [[nodiscard]] TextWithEntities LinkText(const LinkPreview &link) { auto result = TextWithEntities{ link.name.isEmpty() ? link.url : link.name, }; result.entities.push_back(link.name.isEmpty() ? EntityInText(EntityType::Url, 0, result.text.size()) : EntityInText( EntityType::CustomUrl, 0, result.text.size(), link.url)); return result; } [[nodiscard]] MTPMessageMedia LinkMedia( const LinkPreview &link, WebPageData *webpage) { if (!webpage) { return MTP_messageMediaEmpty(); } using Flag = MTPDmessageMediaWebPage::Flag; return MTP_messageMediaWebPage( MTP_flags(link.largePhoto ? Flag::f_force_large_media : Flag::f_force_small_media), MTP_webPagePending( MTP_flags(0), MTP_long(webpage->id), MTPstring(), MTP_int(0))); } [[nodiscard]] not_null LinkHistory( not_null session) { const auto peerId = HistoryView::GenerateUser( session->data().history(PeerData::kServiceNotificationsId), u"Link"_q); const auto result = session->data().history(peerId); result->peer->setBarSettings(PeerBarSettings()); return result; } [[nodiscard]] not_null MakeLinkItem( not_null session, const LinkPreview &link, WebPageData *webpage) { const auto history = LinkHistory(session); return history->makeMessage( { .id = history->nextNonHistoryEntryId(), .flags = (MessageFlag::FakeHistoryItem | MessageFlag::HasFromId | (link.captionAbove ? MessageFlag() : MessageFlag::InvertMedia)), .from = session->userPeerId(), .date = base::unixtime::now(), }, LinkText(link), LinkMedia(link, webpage)); } } // namespace bool MessageForbidsRender(not_null item) { return item->isSponsored() || item->forbidsSaving() || !item->history()->peer->allowsForwarding(); } bool CanRenderMessage(not_null item) { const auto media = item->media(); return !MessageForbidsRender(item) && !item->isEphemeral() && !item->showSimilarChannels() && !item->isLegacyMessage() && !dynamic_cast(media); } not_null MessageToRender(not_null item) { const auto group = item->history()->owner().groups().find(item); return group ? group->items.front() : item; } MessageSource::MessageSource(not_null item) : _session(&item->history()->session()) , _item(item) { if (MessageVideo::Find(item)) { _video = std::make_unique(item); } watchRemoval(); } MessageSource::MessageSource( not_null session, LinkPreview link, WebPageData *webpage) : _session(session) , _link(std::move(link)) , _webpage(webpage) , _item(MakeLinkItem(session, *_link, webpage)) , _owned(true) { watchRemoval(); } MessageSource::~MessageSource() { if (_owned) { if (const auto item = base::take(_item)) { item->destroy(); } } } void MessageSource::watchRemoval() { _session->data().itemRemoved( ) | rpl::filter([=](not_null item) { return (item == _item); }) | rpl::on_next([=] { _item = nullptr; _removed.fire({}); }, _lifetime); } Main::Session &MessageSource::session() const { return *_session; } HistoryItem *MessageSource::item() const { return _item; } const std::optional &MessageSource::link() const { return _link; } WebPageData *MessageSource::webpage() const { return _webpage; } MessageVideo *MessageSource::video() const { return _video.get(); } rpl::producer<> MessageSource::removed() const { return _removed.events(); } } // namespace Editor