mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Start customizable webpages.
This commit is contained in:
parent
486d5b63d3
commit
b2e8e0431e
16 changed files with 172 additions and 73 deletions
|
@ -1434,9 +1434,11 @@ QString MediaCall::Text(
|
||||||
|
|
||||||
MediaWebPage::MediaWebPage(
|
MediaWebPage::MediaWebPage(
|
||||||
not_null<HistoryItem*> parent,
|
not_null<HistoryItem*> parent,
|
||||||
not_null<WebPageData*> page)
|
not_null<WebPageData*> page,
|
||||||
|
MediaWebPageFlags flags)
|
||||||
: Media(parent)
|
: Media(parent)
|
||||||
, _page(page) {
|
, _page(page)
|
||||||
|
, _flags(flags) {
|
||||||
parent->history()->owner().registerWebPageItem(_page, parent);
|
parent->history()->owner().registerWebPageItem(_page, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1445,7 +1447,7 @@ MediaWebPage::~MediaWebPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Media> MediaWebPage::clone(not_null<HistoryItem*> parent) {
|
std::unique_ptr<Media> MediaWebPage::clone(not_null<HistoryItem*> parent) {
|
||||||
return std::make_unique<MediaWebPage>(parent, _page);
|
return std::make_unique<MediaWebPage>(parent, _page, _flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentData *MediaWebPage::document() const {
|
DocumentData *MediaWebPage::document() const {
|
||||||
|
@ -1524,7 +1526,7 @@ std::unique_ptr<HistoryView::Media> MediaWebPage::createView(
|
||||||
not_null<HistoryView::Element*> message,
|
not_null<HistoryView::Element*> message,
|
||||||
not_null<HistoryItem*> realParent,
|
not_null<HistoryItem*> realParent,
|
||||||
HistoryView::Element *replacing) {
|
HistoryView::Element *replacing) {
|
||||||
return std::make_unique<HistoryView::WebPage>(message, _page);
|
return std::make_unique<HistoryView::WebPage>(message, _page, _flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaGame::MediaGame(
|
MediaGame::MediaGame(
|
||||||
|
|
|
@ -372,7 +372,8 @@ class MediaWebPage final : public Media {
|
||||||
public:
|
public:
|
||||||
MediaWebPage(
|
MediaWebPage(
|
||||||
not_null<HistoryItem*> parent,
|
not_null<HistoryItem*> parent,
|
||||||
not_null<WebPageData*> page);
|
not_null<WebPageData*> page,
|
||||||
|
MediaWebPageFlags flags);
|
||||||
~MediaWebPage();
|
~MediaWebPage();
|
||||||
|
|
||||||
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
|
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
|
||||||
|
@ -398,7 +399,8 @@ public:
|
||||||
HistoryView::Element *replacing = nullptr) override;
|
HistoryView::Element *replacing = nullptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
not_null<WebPageData*> _page;
|
const not_null<WebPageData*> _page;
|
||||||
|
const MediaWebPageFlags _flags;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3288,6 +3288,7 @@ not_null<WebPageData*> Session::processWebpage(const MTPDwebPagePending &data) {
|
||||||
webpageApplyFields(
|
webpageApplyFields(
|
||||||
result,
|
result,
|
||||||
WebPageType::Article,
|
WebPageType::Article,
|
||||||
|
false,
|
||||||
QString(),
|
QString(),
|
||||||
QString(),
|
QString(),
|
||||||
QString(),
|
QString(),
|
||||||
|
@ -3312,6 +3313,7 @@ not_null<WebPageData*> Session::webpage(
|
||||||
return webpage(
|
return webpage(
|
||||||
id,
|
id,
|
||||||
WebPageType::Article,
|
WebPageType::Article,
|
||||||
|
false,
|
||||||
QString(),
|
QString(),
|
||||||
QString(),
|
QString(),
|
||||||
siteName,
|
siteName,
|
||||||
|
@ -3328,6 +3330,7 @@ not_null<WebPageData*> Session::webpage(
|
||||||
not_null<WebPageData*> Session::webpage(
|
not_null<WebPageData*> Session::webpage(
|
||||||
WebPageId id,
|
WebPageId id,
|
||||||
WebPageType type,
|
WebPageType type,
|
||||||
|
bool hasLargeMedia,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &displayUrl,
|
const QString &displayUrl,
|
||||||
const QString &siteName,
|
const QString &siteName,
|
||||||
|
@ -3343,6 +3346,7 @@ not_null<WebPageData*> Session::webpage(
|
||||||
webpageApplyFields(
|
webpageApplyFields(
|
||||||
result,
|
result,
|
||||||
type,
|
type,
|
||||||
|
hasLargeMedia,
|
||||||
url,
|
url,
|
||||||
displayUrl,
|
displayUrl,
|
||||||
siteName,
|
siteName,
|
||||||
|
@ -3434,6 +3438,7 @@ void Session::webpageApplyFields(
|
||||||
webpageApplyFields(
|
webpageApplyFields(
|
||||||
page,
|
page,
|
||||||
(story ? WebPageType::Story : ParseWebPageType(data)),
|
(story ? WebPageType::Story : ParseWebPageType(data)),
|
||||||
|
data.is_has_large_media(),
|
||||||
qs(data.vurl()),
|
qs(data.vurl()),
|
||||||
qs(data.vdisplay_url()),
|
qs(data.vdisplay_url()),
|
||||||
siteName,
|
siteName,
|
||||||
|
@ -3459,6 +3464,7 @@ void Session::webpageApplyFields(
|
||||||
void Session::webpageApplyFields(
|
void Session::webpageApplyFields(
|
||||||
not_null<WebPageData*> page,
|
not_null<WebPageData*> page,
|
||||||
WebPageType type,
|
WebPageType type,
|
||||||
|
bool hasLargeMedia,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &displayUrl,
|
const QString &displayUrl,
|
||||||
const QString &siteName,
|
const QString &siteName,
|
||||||
|
@ -3474,6 +3480,7 @@ void Session::webpageApplyFields(
|
||||||
const auto requestPending = (!page->pendingTill && pendingTill > 0);
|
const auto requestPending = (!page->pendingTill && pendingTill > 0);
|
||||||
const auto changed = page->applyChanges(
|
const auto changed = page->applyChanges(
|
||||||
type,
|
type,
|
||||||
|
hasLargeMedia,
|
||||||
url,
|
url,
|
||||||
displayUrl,
|
displayUrl,
|
||||||
siteName,
|
siteName,
|
||||||
|
|
|
@ -20,7 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
class Image;
|
class Image;
|
||||||
class HistoryItem;
|
class HistoryItem;
|
||||||
struct WebPageCollage;
|
struct WebPageCollage;
|
||||||
enum class WebPageType;
|
enum class WebPageType : uint8;
|
||||||
enum class NewMessageType;
|
enum class NewMessageType;
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
|
@ -552,6 +552,7 @@ public:
|
||||||
[[nodiscard]] not_null<WebPageData*> webpage(
|
[[nodiscard]] not_null<WebPageData*> webpage(
|
||||||
WebPageId id,
|
WebPageId id,
|
||||||
WebPageType type,
|
WebPageType type,
|
||||||
|
bool hasLargeMedia,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &displayUrl,
|
const QString &displayUrl,
|
||||||
const QString &siteName,
|
const QString &siteName,
|
||||||
|
@ -813,6 +814,7 @@ private:
|
||||||
void webpageApplyFields(
|
void webpageApplyFields(
|
||||||
not_null<WebPageData*> page,
|
not_null<WebPageData*> page,
|
||||||
WebPageType type,
|
WebPageType type,
|
||||||
|
bool hasLargeMedia,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &displayUrl,
|
const QString &displayUrl,
|
||||||
const QString &siteName,
|
const QString &siteName,
|
||||||
|
|
|
@ -246,65 +246,75 @@ enum class MessageFlag : uint64 {
|
||||||
MentionsMe = (1ULL << 15),
|
MentionsMe = (1ULL << 15),
|
||||||
IsOrWasScheduled = (1ULL << 16),
|
IsOrWasScheduled = (1ULL << 16),
|
||||||
NoForwards = (1ULL << 17),
|
NoForwards = (1ULL << 17),
|
||||||
|
InvertMedia = (1ULL << 18),
|
||||||
|
|
||||||
// Needs to return back to inline mode.
|
// Needs to return back to inline mode.
|
||||||
HasSwitchInlineButton = (1ULL << 18),
|
HasSwitchInlineButton = (1ULL << 19),
|
||||||
|
|
||||||
// For "shared links" indexing.
|
// For "shared links" indexing.
|
||||||
HasTextLinks = (1ULL << 19),
|
HasTextLinks = (1ULL << 20),
|
||||||
|
|
||||||
// Group / channel create or migrate service message.
|
// Group / channel create or migrate service message.
|
||||||
IsGroupEssential = (1ULL << 20),
|
IsGroupEssential = (1ULL << 21),
|
||||||
|
|
||||||
// Edited media is generated on the client
|
// Edited media is generated on the client
|
||||||
// and should not update media from server.
|
// and should not update media from server.
|
||||||
IsLocalUpdateMedia = (1ULL << 21),
|
IsLocalUpdateMedia = (1ULL << 22),
|
||||||
|
|
||||||
// Sent from inline bot, need to re-set media when sent.
|
// Sent from inline bot, need to re-set media when sent.
|
||||||
FromInlineBot = (1ULL << 22),
|
FromInlineBot = (1ULL << 23),
|
||||||
|
|
||||||
// Generated on the client side and should be unread.
|
// Generated on the client side and should be unread.
|
||||||
ClientSideUnread = (1ULL << 23),
|
ClientSideUnread = (1ULL << 24),
|
||||||
|
|
||||||
// In a supergroup.
|
// In a supergroup.
|
||||||
HasAdminBadge = (1ULL << 24),
|
HasAdminBadge = (1ULL << 25),
|
||||||
|
|
||||||
// Outgoing message that is being sent.
|
// Outgoing message that is being sent.
|
||||||
BeingSent = (1ULL << 25),
|
BeingSent = (1ULL << 26),
|
||||||
|
|
||||||
// Outgoing message and failed to be sent.
|
// Outgoing message and failed to be sent.
|
||||||
SendingFailed = (1ULL << 26),
|
SendingFailed = (1ULL << 27),
|
||||||
|
|
||||||
// No media and only a several emoji or an only custom emoji text.
|
// No media and only a several emoji or an only custom emoji text.
|
||||||
SpecialOnlyEmoji = (1ULL << 27),
|
SpecialOnlyEmoji = (1ULL << 28),
|
||||||
|
|
||||||
// Message existing in the message history.
|
// Message existing in the message history.
|
||||||
HistoryEntry = (1ULL << 28),
|
HistoryEntry = (1ULL << 29),
|
||||||
|
|
||||||
// Local message, not existing on the server.
|
// Local message, not existing on the server.
|
||||||
Local = (1ULL << 29),
|
Local = (1ULL << 30),
|
||||||
|
|
||||||
// Fake message for some UI element.
|
// Fake message for some UI element.
|
||||||
FakeHistoryItem = (1ULL << 30),
|
FakeHistoryItem = (1ULL << 31),
|
||||||
|
|
||||||
// Contact sign-up message, notification should be skipped for Silent.
|
// Contact sign-up message, notification should be skipped for Silent.
|
||||||
IsContactSignUp = (1ULL << 31),
|
IsContactSignUp = (1ULL << 32),
|
||||||
|
|
||||||
// Optimization for item text custom emoji repainting.
|
// Optimization for item text custom emoji repainting.
|
||||||
CustomEmojiRepainting = (1ULL << 32),
|
CustomEmojiRepainting = (1ULL << 33),
|
||||||
|
|
||||||
// Profile photo suggestion, views have special media type.
|
// Profile photo suggestion, views have special media type.
|
||||||
IsUserpicSuggestion = (1ULL << 33),
|
IsUserpicSuggestion = (1ULL << 34),
|
||||||
|
|
||||||
OnlyEmojiAndSpaces = (1ULL << 34),
|
OnlyEmojiAndSpaces = (1ULL << 35),
|
||||||
OnlyEmojiAndSpacesSet = (1ULL << 35),
|
OnlyEmojiAndSpacesSet = (1ULL << 36),
|
||||||
|
|
||||||
// Fake message with bot cover and information.
|
// Fake message with bot cover and information.
|
||||||
FakeBotAbout = (1ULL << 36),
|
FakeBotAbout = (1ULL << 37),
|
||||||
|
|
||||||
StoryItem = (1ULL << 37),
|
StoryItem = (1ULL << 38),
|
||||||
|
|
||||||
InHighlightProcess = (1ULL << 38),
|
InHighlightProcess = (1ULL << 39),
|
||||||
};
|
};
|
||||||
inline constexpr bool is_flag_type(MessageFlag) { return true; }
|
inline constexpr bool is_flag_type(MessageFlag) { return true; }
|
||||||
using MessageFlags = base::flags<MessageFlag>;
|
using MessageFlags = base::flags<MessageFlag>;
|
||||||
|
|
||||||
|
enum class MediaWebPageFlag : uint8 {
|
||||||
|
ForceLargeMedia = (1 << 0),
|
||||||
|
ForceSmallMedia = (1 << 1),
|
||||||
|
Manual = (1 << 2),
|
||||||
|
Safe = (1 << 3),
|
||||||
|
};
|
||||||
|
inline constexpr bool is_flag_type(MediaWebPageFlag) { return true; }
|
||||||
|
using MediaWebPageFlags = base::flags<MediaWebPageFlag>;
|
||||||
|
|
|
@ -213,6 +213,7 @@ Main::Session &WebPageData::session() const {
|
||||||
|
|
||||||
bool WebPageData::applyChanges(
|
bool WebPageData::applyChanges(
|
||||||
WebPageType newType,
|
WebPageType newType,
|
||||||
|
bool newHasLargeMedia,
|
||||||
const QString &newUrl,
|
const QString &newUrl,
|
||||||
const QString &newDisplayUrl,
|
const QString &newDisplayUrl,
|
||||||
const QString &newSiteName,
|
const QString &newSiteName,
|
||||||
|
@ -254,6 +255,7 @@ bool WebPageData::applyChanges(
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if (type == newType
|
if (type == newType
|
||||||
|
&& hasLargeMedia == newHasLargeMedia
|
||||||
&& url == resultUrl
|
&& url == resultUrl
|
||||||
&& displayUrl == resultDisplayUrl
|
&& displayUrl == resultDisplayUrl
|
||||||
&& siteName == resultSiteName
|
&& siteName == resultSiteName
|
||||||
|
@ -272,6 +274,7 @@ bool WebPageData::applyChanges(
|
||||||
_owner->session().api().clearWebPageRequest(this);
|
_owner->session().api().clearWebPageRequest(this);
|
||||||
}
|
}
|
||||||
type = newType;
|
type = newType;
|
||||||
|
hasLargeMedia = newHasLargeMedia;
|
||||||
url = resultUrl;
|
url = resultUrl;
|
||||||
displayUrl = resultDisplayUrl;
|
displayUrl = resultDisplayUrl;
|
||||||
siteName = resultSiteName;
|
siteName = resultSiteName;
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/flags.h"
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ namespace Data {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
enum class WebPageType {
|
enum class WebPageType : uint8 {
|
||||||
Message,
|
Message,
|
||||||
|
|
||||||
Group,
|
Group,
|
||||||
|
@ -44,8 +45,7 @@ enum class WebPageType {
|
||||||
VoiceChat,
|
VoiceChat,
|
||||||
Livestream,
|
Livestream,
|
||||||
};
|
};
|
||||||
|
[[nodiscard]] WebPageType ParseWebPageType(const MTPDwebPage &type);
|
||||||
WebPageType ParseWebPageType(const MTPDwebPage &type);
|
|
||||||
|
|
||||||
struct WebPageCollage {
|
struct WebPageCollage {
|
||||||
using Item = std::variant<PhotoData*, DocumentData*>;
|
using Item = std::variant<PhotoData*, DocumentData*>;
|
||||||
|
@ -67,6 +67,7 @@ struct WebPageData {
|
||||||
|
|
||||||
bool applyChanges(
|
bool applyChanges(
|
||||||
WebPageType newType,
|
WebPageType newType,
|
||||||
|
bool newHasLargeMedia,
|
||||||
const QString &newUrl,
|
const QString &newUrl,
|
||||||
const QString &newDisplayUrl,
|
const QString &newDisplayUrl,
|
||||||
const QString &newSiteName,
|
const QString &newSiteName,
|
||||||
|
@ -87,17 +88,18 @@ struct WebPageData {
|
||||||
|
|
||||||
WebPageId id = 0;
|
WebPageId id = 0;
|
||||||
WebPageType type = WebPageType::Article;
|
WebPageType type = WebPageType::Article;
|
||||||
|
bool hasLargeMedia = false;
|
||||||
QString url;
|
QString url;
|
||||||
QString displayUrl;
|
QString displayUrl;
|
||||||
QString siteName;
|
QString siteName;
|
||||||
QString title;
|
QString title;
|
||||||
TextWithEntities description;
|
TextWithEntities description;
|
||||||
FullStoryId storyId;
|
FullStoryId storyId;
|
||||||
int duration = 0;
|
|
||||||
QString author;
|
QString author;
|
||||||
PhotoData *photo = nullptr;
|
PhotoData *photo = nullptr;
|
||||||
DocumentData *document = nullptr;
|
DocumentData *document = nullptr;
|
||||||
WebPageCollage collage;
|
WebPageCollage collage;
|
||||||
|
int duration = 0;
|
||||||
int pendingTill = 0;
|
int pendingTill = 0;
|
||||||
int version = 0;
|
int version = 0;
|
||||||
|
|
||||||
|
|
|
@ -252,16 +252,28 @@ std::unique_ptr<Data::Media> HistoryItem::CreateMedia(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
});
|
});
|
||||||
}, [&](const MTPDmessageMediaWebPage &media) {
|
}, [&](const MTPDmessageMediaWebPage &media) {
|
||||||
|
using Flag = MediaWebPageFlag;
|
||||||
|
const auto flags = Flag()
|
||||||
|
| (media.is_force_large_media()
|
||||||
|
? Flag::ForceLargeMedia
|
||||||
|
: Flag())
|
||||||
|
| (media.is_force_small_media()
|
||||||
|
? Flag::ForceSmallMedia
|
||||||
|
: Flag())
|
||||||
|
| (media.is_manual() ? Flag::Manual : Flag())
|
||||||
|
| (media.is_safe() ? Flag::Safe : Flag());
|
||||||
return media.vwebpage().match([](const MTPDwebPageEmpty &) -> Result {
|
return media.vwebpage().match([](const MTPDwebPageEmpty &) -> Result {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}, [&](const MTPDwebPagePending &webpage) -> Result {
|
}, [&](const MTPDwebPagePending &webpage) -> Result {
|
||||||
return std::make_unique<Data::MediaWebPage>(
|
return std::make_unique<Data::MediaWebPage>(
|
||||||
item,
|
item,
|
||||||
item->history()->owner().processWebpage(webpage));
|
item->history()->owner().processWebpage(webpage),
|
||||||
|
flags);
|
||||||
}, [&](const MTPDwebPage &webpage) -> Result {
|
}, [&](const MTPDwebPage &webpage) -> Result {
|
||||||
return std::make_unique<Data::MediaWebPage>(
|
return std::make_unique<Data::MediaWebPage>(
|
||||||
item,
|
item,
|
||||||
item->history()->owner().processWebpage(webpage));
|
item->history()->owner().processWebpage(webpage),
|
||||||
|
flags);
|
||||||
}, [](const MTPDwebPageNotModified &) -> Result {
|
}, [](const MTPDwebPageNotModified &) -> Result {
|
||||||
LOG(("API Error: "
|
LOG(("API Error: "
|
||||||
"webPageNotModified is unexpected in message media."));
|
"webPageNotModified is unexpected in message media."));
|
||||||
|
@ -503,6 +515,9 @@ HistoryItem::HistoryItem(
|
||||||
};
|
};
|
||||||
if (mediaOriginal && !ignoreMedia()) {
|
if (mediaOriginal && !ignoreMedia()) {
|
||||||
_media = mediaOriginal->clone(this);
|
_media = mediaOriginal->clone(this);
|
||||||
|
if (original->invertMedia()) {
|
||||||
|
_flags |= MessageFlag::InvertMedia;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto dropCustomEmoji = dropForwardInfo
|
const auto dropCustomEmoji = dropForwardInfo
|
||||||
|
|
|
@ -240,6 +240,9 @@ public:
|
||||||
[[nodiscard]] bool isPinned() const {
|
[[nodiscard]] bool isPinned() const {
|
||||||
return _flags & MessageFlag::Pinned;
|
return _flags & MessageFlag::Pinned;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] bool invertMedia() const {
|
||||||
|
return _flags & MessageFlag::InvertMedia;
|
||||||
|
}
|
||||||
[[nodiscard]] bool unread(not_null<Data::Thread*> thread) const;
|
[[nodiscard]] bool unread(not_null<Data::Thread*> thread) const;
|
||||||
[[nodiscard]] bool showNotification() const;
|
[[nodiscard]] bool showNotification() const;
|
||||||
void markClientSideAsRead();
|
void markClientSideAsRead();
|
||||||
|
|
|
@ -331,9 +331,12 @@ MessageFlags FlagsFromMTP(
|
||||||
| ((flags & MTP::f_from_id) ? Flag::HasFromId : Flag())
|
| ((flags & MTP::f_from_id) ? Flag::HasFromId : Flag())
|
||||||
| ((flags & MTP::f_reply_to) ? Flag::HasReplyInfo : Flag())
|
| ((flags & MTP::f_reply_to) ? Flag::HasReplyInfo : Flag())
|
||||||
| ((flags & MTP::f_reply_markup) ? Flag::HasReplyMarkup : Flag())
|
| ((flags & MTP::f_reply_markup) ? Flag::HasReplyMarkup : Flag())
|
||||||
| ((flags & MTP::f_from_scheduled) ? Flag::IsOrWasScheduled : Flag())
|
| ((flags & MTP::f_from_scheduled)
|
||||||
|
? Flag::IsOrWasScheduled
|
||||||
|
: Flag())
|
||||||
| ((flags & MTP::f_views) ? Flag::HasViews : Flag())
|
| ((flags & MTP::f_views) ? Flag::HasViews : Flag())
|
||||||
| ((flags & MTP::f_noforwards) ? Flag::NoForwards : Flag());
|
| ((flags & MTP::f_noforwards) ? Flag::NoForwards : Flag())
|
||||||
|
| ((flags & MTP::f_invert_media) ? Flag::InvertMedia : Flag());
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageFlags FlagsFromMTP(
|
MessageFlags FlagsFromMTP(
|
||||||
|
|
|
@ -411,6 +411,7 @@ Message::Message(
|
||||||
not_null<HistoryItem*> data,
|
not_null<HistoryItem*> data,
|
||||||
Element *replacing)
|
Element *replacing)
|
||||||
: Element(delegate, data, replacing, Flag(0))
|
: Element(delegate, data, replacing, Flag(0))
|
||||||
|
, _invertMedia(data->invertMedia() && !data->emptyText())
|
||||||
, _bottomInfo(
|
, _bottomInfo(
|
||||||
&data->history()->owner().reactions(),
|
&data->history()->owner().reactions(),
|
||||||
BottomInfoDataFromMessage(this)) {
|
BottomInfoDataFromMessage(this)) {
|
||||||
|
@ -1078,16 +1079,20 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
||||||
trect.setHeight(trect.height()
|
trect.setHeight(trect.height()
|
||||||
- (_bottomInfo.height() - st::msgDateFont->height));
|
- (_bottomInfo.height() - st::msgDateFont->height));
|
||||||
}
|
}
|
||||||
paintText(p, trect, context);
|
auto textSelection = context.selection;
|
||||||
if (mediaDisplayed) {
|
const auto mediaHeight = mediaDisplayed ? media->height() : 0;
|
||||||
auto mediaHeight = media->height();
|
const auto paintMedia = [&](int top) {
|
||||||
auto mediaPosition = QPoint(
|
if (!mediaDisplayed) {
|
||||||
inner.left(),
|
return;
|
||||||
trect.y() + trect.height() - mediaHeight);
|
}
|
||||||
|
const auto mediaSelection = _invertMedia
|
||||||
|
? context.selection
|
||||||
|
: skipTextSelection(context.selection);
|
||||||
|
auto mediaPosition = QPoint(inner.left(), top);
|
||||||
p.translate(mediaPosition);
|
p.translate(mediaPosition);
|
||||||
media->draw(p, context.translated(
|
media->draw(p, context.translated(
|
||||||
-mediaPosition
|
-mediaPosition
|
||||||
).withSelection(skipTextSelection(context.selection)));
|
).withSelection(mediaSelection));
|
||||||
if (context.reactionInfo && !displayInfo && !_reactions) {
|
if (context.reactionInfo && !displayInfo && !_reactions) {
|
||||||
const auto add = QPoint(0, mediaHeight);
|
const auto add = QPoint(0, mediaHeight);
|
||||||
context.reactionInfo->position = mediaPosition + add;
|
context.reactionInfo->position = mediaPosition + add;
|
||||||
|
@ -1096,6 +1101,27 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.translate(-mediaPosition);
|
p.translate(-mediaPosition);
|
||||||
|
};
|
||||||
|
if (mediaDisplayed && _invertMedia) {
|
||||||
|
if (!mediaOnTop) {
|
||||||
|
trect.setY(trect.y() + st::mediaInBubbleSkip);
|
||||||
|
}
|
||||||
|
paintMedia(trect.y());
|
||||||
|
trect.setY(trect.y()
|
||||||
|
+ mediaHeight
|
||||||
|
+ (mediaOnBottom ? 0 : st::mediaInBubbleSkip));
|
||||||
|
textSelection = media->skipSelection(textSelection);
|
||||||
|
}
|
||||||
|
paintText(p, trect, context.withSelection(textSelection));
|
||||||
|
if (mediaDisplayed && !_invertMedia) {
|
||||||
|
paintMedia(trect.y() + trect.height() - mediaHeight);
|
||||||
|
if (context.reactionInfo && !displayInfo && !_reactions) {
|
||||||
|
context.reactionInfo->position
|
||||||
|
= QPoint(inner.left(), trect.y() + trect.height());
|
||||||
|
if (context.reactionInfo->effectPaint) {
|
||||||
|
context.reactionInfo->effectOffset -= QPoint(0, mediaHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (entry) {
|
if (entry) {
|
||||||
auto entryLeft = inner.left();
|
auto entryLeft = inner.left();
|
||||||
|
@ -2106,25 +2132,33 @@ TextState Message::textState(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (!result.symbol && inBubble) {
|
if (!result.symbol && inBubble) {
|
||||||
if (mediaDisplayed) {
|
const auto mediaHeight = mediaDisplayed ? media->height() : 0;
|
||||||
auto mediaHeight = media->height();
|
const auto mediaLeft = trect.x() - st::msgPadding.left();
|
||||||
auto mediaLeft = trect.x() - st::msgPadding.left();
|
const auto mediaTop = (!mediaDisplayed || _invertMedia)
|
||||||
auto mediaTop = (trect.y() + trect.height() - mediaHeight);
|
? (trect.y() + (mediaOnTop ? 0 : st::mediaInBubbleSkip))
|
||||||
|
: (trect.y() + trect.height() - mediaHeight);
|
||||||
if (point.y() >= mediaTop && point.y() < mediaTop + mediaHeight) {
|
if (mediaDisplayed && _invertMedia) {
|
||||||
result = media->textState(point - QPoint(mediaLeft, mediaTop), request);
|
trect.setY(mediaTop
|
||||||
|
+ mediaHeight
|
||||||
|
+ (mediaOnBottom ? 0 : st::mediaInBubbleSkip));
|
||||||
|
}
|
||||||
|
if (point.y() >= mediaTop
|
||||||
|
&& point.y() < mediaTop + mediaHeight) {
|
||||||
|
result = media->textState(
|
||||||
|
point - QPoint(mediaLeft, mediaTop),
|
||||||
|
request);
|
||||||
|
if (!_invertMedia) {
|
||||||
result.symbol += visibleTextLength();
|
result.symbol += visibleTextLength();
|
||||||
} else if (getStateText(point, trect, &result, request)) {
|
|
||||||
checkBottomInfoState();
|
|
||||||
return result;
|
|
||||||
} else if (point.y() >= trect.y() + trect.height()) {
|
|
||||||
result.symbol = visibleTextLength();
|
|
||||||
}
|
}
|
||||||
} else if (getStateText(point, trect, &result, request)) {
|
} else if (getStateText(point, trect, &result, request)) {
|
||||||
|
if (_invertMedia) {
|
||||||
|
result.symbol += visibleMediaTextLength();
|
||||||
|
}
|
||||||
checkBottomInfoState();
|
checkBottomInfoState();
|
||||||
return result;
|
return result;
|
||||||
} else if (point.y() >= trect.y() + trect.height()) {
|
} else if (point.y() >= trect.y() + trect.height()) {
|
||||||
result.symbol = visibleTextLength();
|
result.symbol = visibleTextLength()
|
||||||
|
+ visibleMediaTextLength();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkBottomInfoState();
|
checkBottomInfoState();
|
||||||
|
@ -3031,7 +3065,8 @@ void Message::initLogEntryOriginal() {
|
||||||
if (const auto log = data()->Get<HistoryMessageLogEntryOriginal>()) {
|
if (const auto log = data()->Get<HistoryMessageLogEntryOriginal>()) {
|
||||||
AddComponents(LogEntryOriginal::Bit());
|
AddComponents(LogEntryOriginal::Bit());
|
||||||
const auto entry = Get<LogEntryOriginal>();
|
const auto entry = Get<LogEntryOriginal>();
|
||||||
entry->page = std::make_unique<WebPage>(this, log->page);
|
using Flags = MediaWebPageFlags;
|
||||||
|
entry->page = std::make_unique<WebPage>(this, log->page, Flags());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3491,7 +3526,8 @@ void Message::updateMediaInBubbleState() {
|
||||||
}
|
}
|
||||||
const auto reactionsInBubble = (_reactions && embedReactionsInBubble());
|
const auto reactionsInBubble = (_reactions && embedReactionsInBubble());
|
||||||
auto mediaHasSomethingBelow = (_viewButton != nullptr)
|
auto mediaHasSomethingBelow = (_viewButton != nullptr)
|
||||||
|| reactionsInBubble;
|
|| reactionsInBubble
|
||||||
|
|| (invertMedia() && hasVisibleText());
|
||||||
auto mediaHasSomethingAbove = false;
|
auto mediaHasSomethingAbove = false;
|
||||||
auto getMediaHasSomethingAbove = [&] {
|
auto getMediaHasSomethingAbove = [&] {
|
||||||
return displayFromName()
|
return displayFromName()
|
||||||
|
@ -3529,7 +3565,7 @@ void Message::updateMediaInBubbleState() {
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
mediaHasSomethingAbove = getMediaHasSomethingAbove();
|
mediaHasSomethingAbove = getMediaHasSomethingAbove();
|
||||||
}
|
}
|
||||||
if (hasVisibleText()) {
|
if (!invertMedia() && hasVisibleText()) {
|
||||||
mediaHasSomethingAbove = true;
|
mediaHasSomethingAbove = true;
|
||||||
}
|
}
|
||||||
const auto state = [&] {
|
const auto state = [&] {
|
||||||
|
@ -3661,7 +3697,7 @@ QRect Message::countGeometry() const {
|
||||||
// contentLeft += st::msgPhotoSkip - (hmaxwidth - hwidth);
|
// contentLeft += st::msgPhotoSkip - (hmaxwidth - hwidth);
|
||||||
}
|
}
|
||||||
accumulate_min(contentWidth, maxWidth());
|
accumulate_min(contentWidth, maxWidth());
|
||||||
accumulate_min(contentWidth, _bubbleWidthLimit);
|
accumulate_min(contentWidth, int(_bubbleWidthLimit));
|
||||||
if (mediaWidth < contentWidth) {
|
if (mediaWidth < contentWidth) {
|
||||||
const auto textualWidth = plainMaxWidth();
|
const auto textualWidth = plainMaxWidth();
|
||||||
if (mediaWidth < textualWidth
|
if (mediaWidth < textualWidth
|
||||||
|
@ -3768,7 +3804,7 @@ int Message::resizeContentGetHeight(int newWidth) {
|
||||||
}
|
}
|
||||||
accumulate_min(contentWidth, maxWidth());
|
accumulate_min(contentWidth, maxWidth());
|
||||||
_bubbleWidthLimit = std::max(st::msgMaxWidth, monospaceMaxWidth());
|
_bubbleWidthLimit = std::max(st::msgMaxWidth, monospaceMaxWidth());
|
||||||
accumulate_min(contentWidth, _bubbleWidthLimit);
|
accumulate_min(contentWidth, int(_bubbleWidthLimit));
|
||||||
if (mediaDisplayed) {
|
if (mediaDisplayed) {
|
||||||
media->resizeGetHeight(contentWidth);
|
media->resizeGetHeight(contentWidth);
|
||||||
if (media->width() < contentWidth) {
|
if (media->width() < contentWidth) {
|
||||||
|
@ -3924,11 +3960,15 @@ bool Message::needInfoDisplay() const {
|
||||||
const auto entry = logEntryOriginal();
|
const auto entry = logEntryOriginal();
|
||||||
return entry
|
return entry
|
||||||
? !entry->customInfoLayout()
|
? !entry->customInfoLayout()
|
||||||
: (mediaDisplayed
|
: ((mediaDisplayed && media->isBubbleBottom())
|
||||||
? !media->customInfoLayout()
|
? !media->customInfoLayout()
|
||||||
: true);
|
: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Message::invertMedia() const {
|
||||||
|
return _invertMedia;
|
||||||
|
}
|
||||||
|
|
||||||
bool Message::hasVisibleText() const {
|
bool Message::hasVisibleText() const {
|
||||||
if (data()->emptyText()) {
|
if (data()->emptyText()) {
|
||||||
if (const auto media = data()->media()) {
|
if (const auto media = data()->media()) {
|
||||||
|
|
|
@ -270,6 +270,7 @@ private:
|
||||||
[[nodiscard]] int visibleTextLength() const;
|
[[nodiscard]] int visibleTextLength() const;
|
||||||
[[nodiscard]] int visibleMediaTextLength() const;
|
[[nodiscard]] int visibleMediaTextLength() const;
|
||||||
[[nodiscard]] bool needInfoDisplay() const;
|
[[nodiscard]] bool needInfoDisplay() const;
|
||||||
|
[[nodiscard]] bool invertMedia() const;
|
||||||
|
|
||||||
[[nodiscard]] bool isPinnedContext() const;
|
[[nodiscard]] bool isPinnedContext() const;
|
||||||
|
|
||||||
|
@ -309,7 +310,8 @@ private:
|
||||||
mutable std::unique_ptr<FromNameStatus> _fromNameStatus;
|
mutable std::unique_ptr<FromNameStatus> _fromNameStatus;
|
||||||
Ui::Text::String _rightBadge;
|
Ui::Text::String _rightBadge;
|
||||||
mutable int _fromNameVersion = 0;
|
mutable int _fromNameVersion = 0;
|
||||||
int _bubbleWidthLimit = 0;
|
uint32 _bubbleWidthLimit : 31 = 0;
|
||||||
|
uint32 _invertMedia : 1 = 0;
|
||||||
|
|
||||||
BottomInfo _bottomInfo;
|
BottomInfo _bottomInfo;
|
||||||
|
|
||||||
|
|
|
@ -121,14 +121,16 @@ std::vector<std::unique_ptr<Data::Media>> PrepareCollageMedia(
|
||||||
|
|
||||||
WebPage::WebPage(
|
WebPage::WebPage(
|
||||||
not_null<Element*> parent,
|
not_null<Element*> parent,
|
||||||
not_null<WebPageData*> data)
|
not_null<WebPageData*> data,
|
||||||
|
MediaWebPageFlags flags)
|
||||||
: Media(parent)
|
: Media(parent)
|
||||||
, _st(st::historyPagePreview)
|
, _st(st::historyPagePreview)
|
||||||
, _data(data)
|
, _data(data)
|
||||||
, _colorIndex(parent->data()->computeColorIndex())
|
, _colorIndex(parent->data()->computeColorIndex())
|
||||||
, _siteName(st::msgMinWidth - _st.padding.left() - _st.padding.right())
|
, _siteName(st::msgMinWidth - _st.padding.left() - _st.padding.right())
|
||||||
, _title(st::msgMinWidth - _st.padding.left() - _st.padding.right())
|
, _title(st::msgMinWidth - _st.padding.left() - _st.padding.right())
|
||||||
, _description(st::msgMinWidth - _st.padding.left() - _st.padding.right()) {
|
, _description(st::msgMinWidth - _st.padding.left() - _st.padding.right())
|
||||||
|
, _flags(flags) {
|
||||||
history()->owner().registerWebPageView(_data, _parent);
|
history()->owner().registerWebPageView(_data, _parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +240,12 @@ QSize WebPage::countOptimalSize() {
|
||||||
auto title = TextUtilities::SingleLine(_data->title.isEmpty()
|
auto title = TextUtilities::SingleLine(_data->title.isEmpty()
|
||||||
? _data->author
|
? _data->author
|
||||||
: _data->title);
|
: _data->title);
|
||||||
if (!_collage.empty()) {
|
using Flag = MediaWebPageFlag;
|
||||||
|
if (_data->hasLargeMedia && (_flags & Flag::ForceLargeMedia)) {
|
||||||
|
_asArticle = 0;
|
||||||
|
} else if (_data->photo && (_flags & Flag::ForceSmallMedia)) {
|
||||||
|
_asArticle = 1;
|
||||||
|
} else if (!_collage.empty()) {
|
||||||
_asArticle = 0;
|
_asArticle = 0;
|
||||||
} else if (!_data->document
|
} else if (!_data->document
|
||||||
&& _data->photo
|
&& _data->photo
|
||||||
|
@ -956,11 +963,9 @@ TextForMimeData WebPage::selectedText(TextSelection selection) const {
|
||||||
QMargins WebPage::inBubblePadding() const {
|
QMargins WebPage::inBubblePadding() const {
|
||||||
return {
|
return {
|
||||||
st::msgPadding.left(),
|
st::msgPadding.left(),
|
||||||
isBubbleTop() ? st::msgPadding.left() : st::mediaInBubbleSkip,
|
isBubbleTop() ? st::msgPadding.left() : 0,
|
||||||
st::msgPadding.right(),
|
st::msgPadding.right(),
|
||||||
(isBubbleBottom()
|
isBubbleBottom() ? (st::msgPadding.left() + bottomInfoPadding()) : 0
|
||||||
? (st::msgPadding.left() + bottomInfoPadding())
|
|
||||||
: st::mediaInBubbleSkip),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,8 @@ class WebPage : public Media {
|
||||||
public:
|
public:
|
||||||
WebPage(
|
WebPage(
|
||||||
not_null<Element*> parent,
|
not_null<Element*> parent,
|
||||||
not_null<WebPageData*> data);
|
not_null<WebPageData*> data,
|
||||||
|
MediaWebPageFlags flags);
|
||||||
|
|
||||||
[[nodiscard]] static bool HasButton(not_null<WebPageData*> data);
|
[[nodiscard]] static bool HasButton(not_null<WebPageData*> data);
|
||||||
|
|
||||||
|
@ -151,6 +152,8 @@ private:
|
||||||
int _pixw = 0;
|
int _pixw = 0;
|
||||||
int _pixh = 0;
|
int _pixh = 0;
|
||||||
|
|
||||||
|
const MediaWebPageFlags _flags;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
@ -2168,5 +2168,5 @@ stories.togglePeerStoriesHidden#bd0415c4 peer:InputPeer hidden:Bool = Bool;
|
||||||
|
|
||||||
premium.getBoostsList#60f67660 flags:# gifts:flags.0?true peer:InputPeer offset:string limit:int = premium.BoostsList;
|
premium.getBoostsList#60f67660 flags:# gifts:flags.0?true peer:InputPeer offset:string limit:int = premium.BoostsList;
|
||||||
premium.getMyBoosts#be77b4a = premium.MyBoosts;
|
premium.getMyBoosts#be77b4a = premium.MyBoosts;
|
||||||
premium.applyBoost#46b6a16b flags:# slot:flags.0?int peer:InputPeer = Bool;
|
premium.applyBoost#184bc3b9 flags:# slots:flags.0?Vector<int> peer:InputPeer = Bool;
|
||||||
premium.getBoostsStatus#42f1f61 peer:InputPeer = premium.BoostsStatus;
|
premium.getBoostsStatus#42f1f61 peer:InputPeer = premium.BoostsStatus;
|
||||||
|
|
|
@ -785,7 +785,7 @@ void SessionNavigation::applyBoostChecked(
|
||||||
Fn<void(bool)> done) {
|
Fn<void(bool)> done) {
|
||||||
_api.request(MTPpremium_ApplyBoost(
|
_api.request(MTPpremium_ApplyBoost(
|
||||||
MTP_flags(0),
|
MTP_flags(0),
|
||||||
MTPint(), // slot
|
MTPVector<MTPint>(), // slots
|
||||||
channel->input
|
channel->input
|
||||||
)).done([=](const MTPBool &result) {
|
)).done([=](const MTPBool &result) {
|
||||||
done(true);
|
done(true);
|
||||||
|
|
Loading…
Add table
Reference in a new issue