mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Implement story mention messages.
This commit is contained in:
parent
75d4ba7be1
commit
3d795f2f67
26 changed files with 386 additions and 84 deletions
|
@ -700,6 +700,8 @@ PRIVATE
|
||||||
history/view/media/history_view_sticker_player.cpp
|
history/view/media/history_view_sticker_player.cpp
|
||||||
history/view/media/history_view_sticker_player.h
|
history/view/media/history_view_sticker_player.h
|
||||||
history/view/media/history_view_sticker_player_abstract.h
|
history/view/media/history_view_sticker_player_abstract.h
|
||||||
|
history/view/media/history_view_story_mention.cpp
|
||||||
|
history/view/media/history_view_story_mention.h
|
||||||
history/view/media/history_view_theme_document.cpp
|
history/view/media/history_view_theme_document.cpp
|
||||||
history/view/media/history_view_theme_document.h
|
history/view/media/history_view_theme_document.h
|
||||||
history/view/media/history_view_userpic_suggestion.cpp
|
history/view/media/history_view_userpic_suggestion.cpp
|
||||||
|
|
|
@ -1574,6 +1574,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_action_topic_icon_changed" = "{from} changed the {link} icon to {emoji}";
|
"lng_action_topic_icon_changed" = "{from} changed the {link} icon to {emoji}";
|
||||||
"lng_action_topic_icon_removed" = "{from} removed the {link} icon";
|
"lng_action_topic_icon_removed" = "{from} removed the {link} icon";
|
||||||
"lng_action_shared_chat_with_bot" = "You shared {chat} with {bot}";
|
"lng_action_shared_chat_with_bot" = "You shared {chat} with {bot}";
|
||||||
|
"lng_action_story_mention_me" = "You mentioned {user} in a story";
|
||||||
|
"lng_action_story_mention" = "{user} mentioned you in a story";
|
||||||
|
"lng_action_story_mention_button" = "View Story";
|
||||||
|
"lng_action_story_mention_me_unavailable" = "The story where you mentioned {user} is no longer available.";
|
||||||
|
"lng_action_story_mention_unavailable" = "The story where {user} mentioned you is no longer available.";
|
||||||
|
|
||||||
"lng_premium_gift_duration_months#one" = "for {count} month";
|
"lng_premium_gift_duration_months#one" = "for {count} month";
|
||||||
"lng_premium_gift_duration_months#other" = "for {count} months";
|
"lng_premium_gift_duration_months#other" = "for {count} months";
|
||||||
|
|
|
@ -301,6 +301,7 @@ private:
|
||||||
PossibleCoverThumbnail = 0x0400,
|
PossibleCoverThumbnail = 0x0400,
|
||||||
UseTextColor = 0x0800,
|
UseTextColor = 0x0800,
|
||||||
StoryDocument = 0x1000,
|
StoryDocument = 0x1000,
|
||||||
|
SilentVideo = 0x2000,
|
||||||
};
|
};
|
||||||
using Flags = base::flags<Flag>;
|
using Flags = base::flags<Flag>;
|
||||||
friend constexpr bool is_flag_type(Flag) { return true; };
|
friend constexpr bool is_flag_type(Flag) { return true; };
|
||||||
|
|
|
@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/media/history_view_slot_machine.h"
|
#include "history/view/media/history_view_slot_machine.h"
|
||||||
#include "history/view/media/history_view_dice.h"
|
#include "history/view/media/history_view_dice.h"
|
||||||
#include "history/view/media/history_view_service_box.h"
|
#include "history/view/media/history_view_service_box.h"
|
||||||
|
#include "history/view/media/history_view_story_mention.h"
|
||||||
#include "history/view/media/history_view_premium_gift.h"
|
#include "history/view/media/history_view_premium_gift.h"
|
||||||
#include "history/view/media/history_view_userpic_suggestion.h"
|
#include "history/view/media/history_view_userpic_suggestion.h"
|
||||||
#include "dialogs/ui/dialogs_message_view.h"
|
#include "dialogs/ui/dialogs_message_view.h"
|
||||||
|
@ -415,6 +416,10 @@ bool Media::storyExpired() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Media::storyMention() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Media::uploading() const {
|
bool Media::uploading() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1979,20 +1984,31 @@ std::unique_ptr<HistoryView::Media> MediaWallPaper::createView(
|
||||||
std::make_unique<HistoryView::ThemeDocumentBox>(message, _paper));
|
std::make_unique<HistoryView::ThemeDocumentBox>(message, _paper));
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaStory::MediaStory(not_null<HistoryItem*> parent, FullStoryId storyId)
|
MediaStory::MediaStory(
|
||||||
|
not_null<HistoryItem*> parent,
|
||||||
|
FullStoryId storyId,
|
||||||
|
bool mention)
|
||||||
: Media(parent)
|
: Media(parent)
|
||||||
, _storyId(storyId) {
|
, _storyId(storyId)
|
||||||
|
, _mention(mention) {
|
||||||
const auto stories = &parent->history()->owner().stories();
|
const auto stories = &parent->history()->owner().stories();
|
||||||
if (const auto maybeStory = stories->lookup(storyId)) {
|
if (const auto maybeStory = stories->lookup(storyId)) {
|
||||||
parent->setText((*maybeStory)->caption());
|
if (!_mention) {
|
||||||
|
parent->setText((*maybeStory)->caption());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (maybeStory.error() == NoStory::Unknown) {
|
if (maybeStory.error() == NoStory::Unknown) {
|
||||||
stories->resolve(storyId, crl::guard(this, [=] {
|
stories->resolve(storyId, crl::guard(this, [=] {
|
||||||
if (const auto maybeStory = stories->lookup(storyId)) {
|
if (const auto maybeStory = stories->lookup(storyId)) {
|
||||||
parent->setText((*maybeStory)->caption());
|
if (!_mention) {
|
||||||
|
parent->setText((*maybeStory)->caption());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_expired = true;
|
_expired = true;
|
||||||
}
|
}
|
||||||
|
if (_mention) {
|
||||||
|
parent->updateStoryMentionText();
|
||||||
|
}
|
||||||
parent->history()->owner().requestItemViewRefresh(parent);
|
parent->history()->owner().requestItemViewRefresh(parent);
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
|
@ -2002,7 +2018,7 @@ MediaStory::MediaStory(not_null<HistoryItem*> parent, FullStoryId storyId)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Media> MediaStory::clone(not_null<HistoryItem*> parent) {
|
std::unique_ptr<Media> MediaStory::clone(not_null<HistoryItem*> parent) {
|
||||||
return std::make_unique<MediaStory>(parent, _storyId);
|
return std::make_unique<MediaStory>(parent, _storyId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FullStoryId MediaStory::storyId() const {
|
FullStoryId MediaStory::storyId() const {
|
||||||
|
@ -2013,6 +2029,10 @@ bool MediaStory::storyExpired() const {
|
||||||
return _expired;
|
return _expired;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MediaStory::storyMention() const {
|
||||||
|
return _mention;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
@ -2064,12 +2084,17 @@ 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 (!_mention) {
|
||||||
|
realParent->setText(TextWithEntities());
|
||||||
|
}
|
||||||
if (maybeStory.error() == Data::NoStory::Deleted) {
|
if (maybeStory.error() == Data::NoStory::Deleted) {
|
||||||
_expired = true;
|
_expired = true;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
_expired = false;
|
_expired = false;
|
||||||
|
if (_mention) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return std::make_unique<HistoryView::Photo>(
|
return std::make_unique<HistoryView::Photo>(
|
||||||
message,
|
message,
|
||||||
realParent,
|
realParent,
|
||||||
|
@ -2078,19 +2103,25 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
|
||||||
}
|
}
|
||||||
_expired = false;
|
_expired = false;
|
||||||
const auto story = *maybeStory;
|
const auto story = *maybeStory;
|
||||||
realParent->setText(story->caption());
|
if (_mention) {
|
||||||
if (const auto photo = story->photo()) {
|
return std::make_unique<HistoryView::ServiceBox>(
|
||||||
return std::make_unique<HistoryView::Photo>(
|
|
||||||
message,
|
message,
|
||||||
realParent,
|
std::make_unique<HistoryView::StoryMention>(message, story));
|
||||||
photo,
|
|
||||||
spoiler);
|
|
||||||
} else {
|
} else {
|
||||||
return std::make_unique<HistoryView::Gif>(
|
realParent->setText(story->caption());
|
||||||
message,
|
if (const auto photo = story->photo()) {
|
||||||
realParent,
|
return std::make_unique<HistoryView::Photo>(
|
||||||
story->document(),
|
message,
|
||||||
spoiler);
|
realParent,
|
||||||
|
photo,
|
||||||
|
spoiler);
|
||||||
|
} else {
|
||||||
|
return std::make_unique<HistoryView::Gif>(
|
||||||
|
message,
|
||||||
|
realParent,
|
||||||
|
story->document(),
|
||||||
|
spoiler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,7 @@ public:
|
||||||
virtual const WallPaper *paper() const;
|
virtual const WallPaper *paper() const;
|
||||||
virtual FullStoryId storyId() const;
|
virtual FullStoryId storyId() const;
|
||||||
virtual bool storyExpired() const;
|
virtual bool storyExpired() const;
|
||||||
|
virtual bool storyMention() const;
|
||||||
|
|
||||||
virtual bool uploading() const;
|
virtual bool uploading() const;
|
||||||
virtual Storage::SharedMediaTypesMask sharedMediaTypes() const;
|
virtual Storage::SharedMediaTypesMask sharedMediaTypes() const;
|
||||||
|
@ -570,12 +571,16 @@ private:
|
||||||
|
|
||||||
class MediaStory final : public Media, public base::has_weak_ptr {
|
class MediaStory final : public Media, public base::has_weak_ptr {
|
||||||
public:
|
public:
|
||||||
MediaStory(not_null<HistoryItem*> parent, FullStoryId storyId);
|
MediaStory(
|
||||||
|
not_null<HistoryItem*> parent,
|
||||||
|
FullStoryId storyId,
|
||||||
|
bool mention);
|
||||||
|
|
||||||
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
|
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
|
||||||
|
|
||||||
FullStoryId storyId() const override;
|
FullStoryId storyId() const override;
|
||||||
bool storyExpired() const override;
|
bool storyExpired() const override;
|
||||||
|
bool storyMention() const override;
|
||||||
|
|
||||||
TextWithEntities notificationText() const override;
|
TextWithEntities notificationText() const override;
|
||||||
QString pinnedTextSubstring() const override;
|
QString pinnedTextSubstring() const override;
|
||||||
|
@ -594,6 +599,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FullStoryId _storyId;
|
const FullStoryId _storyId;
|
||||||
|
const bool _mention = false;
|
||||||
bool _expired = false;
|
bool _expired = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -248,28 +248,24 @@ bool Story::pinned() const {
|
||||||
return _pinned;
|
return _pinned;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Story::setIsPublic(bool isPublic) {
|
|
||||||
_isPublic = isPublic;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Story::isPublic() const {
|
bool Story::isPublic() const {
|
||||||
return _isPublic;
|
return _isPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Story::setCloseFriends(bool closeFriends) {
|
|
||||||
_closeFriends = closeFriends;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Story::closeFriends() const {
|
bool Story::closeFriends() const {
|
||||||
return _closeFriends;
|
return _closeFriends;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Story::forbidsForward() const {
|
||||||
|
return _noForwards;
|
||||||
|
}
|
||||||
|
|
||||||
bool Story::canDownload() const {
|
bool Story::canDownload() const {
|
||||||
return _peer->isSelf();
|
return !forbidsForward() || _peer->isSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Story::canShare() const {
|
bool Story::canShare() const {
|
||||||
return isPublic() && (pinned() || !expired());
|
return isPublic() && !forbidsForward() && (pinned() || !expired());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Story::canDelete() const {
|
bool Story::canDelete() const {
|
||||||
|
@ -375,6 +371,7 @@ bool Story::applyChanges(StoryMedia media, const MTPDstoryItem &data) {
|
||||||
const auto pinned = data.is_pinned();
|
const auto pinned = data.is_pinned();
|
||||||
const auto isPublic = data.is_public();
|
const auto isPublic = data.is_public();
|
||||||
const auto closeFriends = data.is_close_friends();
|
const auto closeFriends = data.is_close_friends();
|
||||||
|
const auto noForwards = data.is_noforwards();
|
||||||
auto caption = TextWithEntities{
|
auto caption = TextWithEntities{
|
||||||
data.vcaption().value_or_empty(),
|
data.vcaption().value_or_empty(),
|
||||||
Api::EntitiesFromMTP(
|
Api::EntitiesFromMTP(
|
||||||
|
@ -400,6 +397,7 @@ bool Story::applyChanges(StoryMedia media, const MTPDstoryItem &data) {
|
||||||
|| (_pinned != pinned)
|
|| (_pinned != pinned)
|
||||||
|| (_isPublic != isPublic)
|
|| (_isPublic != isPublic)
|
||||||
|| (_closeFriends != closeFriends)
|
|| (_closeFriends != closeFriends)
|
||||||
|
|| (_noForwards != noForwards)
|
||||||
|| (_caption != caption)
|
|| (_caption != caption)
|
||||||
|| (views >= 0 && _views != views)
|
|| (views >= 0 && _views != views)
|
||||||
|| (_recentViewers != recent);
|
|| (_recentViewers != recent);
|
||||||
|
@ -410,6 +408,7 @@ bool Story::applyChanges(StoryMedia media, const MTPDstoryItem &data) {
|
||||||
_pinned = pinned;
|
_pinned = pinned;
|
||||||
_isPublic = isPublic;
|
_isPublic = isPublic;
|
||||||
_closeFriends = closeFriends;
|
_closeFriends = closeFriends;
|
||||||
|
_noForwards = noForwards;
|
||||||
_caption = std::move(caption);
|
_caption = std::move(caption);
|
||||||
if (views >= 0) {
|
if (views >= 0) {
|
||||||
_views = views;
|
_views = views;
|
||||||
|
|
|
@ -86,10 +86,9 @@ public:
|
||||||
|
|
||||||
void setPinned(bool pinned);
|
void setPinned(bool pinned);
|
||||||
[[nodiscard]] bool pinned() const;
|
[[nodiscard]] bool pinned() const;
|
||||||
void setIsPublic(bool isPublic);
|
|
||||||
[[nodiscard]] bool isPublic() const;
|
[[nodiscard]] bool isPublic() const;
|
||||||
void setCloseFriends(bool closeFriends);
|
|
||||||
[[nodiscard]] bool closeFriends() const;
|
[[nodiscard]] bool closeFriends() const;
|
||||||
|
[[nodiscard]] bool forbidsForward() const;
|
||||||
|
|
||||||
[[nodiscard]] bool canDownload() const;
|
[[nodiscard]] bool canDownload() const;
|
||||||
[[nodiscard]] bool canShare() const;
|
[[nodiscard]] bool canShare() const;
|
||||||
|
@ -128,6 +127,7 @@ private:
|
||||||
bool _pinned : 1 = false;
|
bool _pinned : 1 = false;
|
||||||
bool _isPublic : 1 = false;
|
bool _isPublic : 1 = false;
|
||||||
bool _closeFriends : 1 = false;
|
bool _closeFriends : 1 = false;
|
||||||
|
bool _noForwards : 1 = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -144,11 +144,12 @@ QImage PeerUserpic::image(int size) {
|
||||||
const auto good = (_frame.width() == size * _frame.devicePixelRatio());
|
const auto good = (_frame.width() == size * _frame.devicePixelRatio());
|
||||||
const auto key = _peer->userpicUniqueKey(_subscribed->view);
|
const auto key = _peer->userpicUniqueKey(_subscribed->view);
|
||||||
if (!good || (_subscribed->key != key && !waitingUserpicLoad())) {
|
if (!good || (_subscribed->key != key && !waitingUserpicLoad())) {
|
||||||
|
const auto ratio = style::DevicePixelRatio();
|
||||||
_subscribed->key = key;
|
_subscribed->key = key;
|
||||||
_frame = QImage(
|
_frame = QImage(
|
||||||
QSize(size, size) * style::DevicePixelRatio(),
|
QSize(size, size) * ratio,
|
||||||
QImage::Format_ARGB32_Premultiplied);
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
_frame.setDevicePixelRatio(style::DevicePixelRatio());
|
_frame.setDevicePixelRatio(ratio);
|
||||||
_frame.fill(Qt::transparent);
|
_frame.fill(Qt::transparent);
|
||||||
|
|
||||||
auto p = Painter(&_frame);
|
auto p = Painter(&_frame);
|
||||||
|
@ -216,6 +217,7 @@ QImage StoryThumbnail::image(int size) {
|
||||||
Qt::SmoothTransformation);
|
Qt::SmoothTransformation);
|
||||||
}
|
}
|
||||||
_prepared = Images::Circle(std::move(_prepared));
|
_prepared = Images::Circle(std::move(_prepared));
|
||||||
|
_prepared.setDevicePixelRatio(ratio);
|
||||||
}
|
}
|
||||||
return _prepared;
|
return _prepared;
|
||||||
}
|
}
|
||||||
|
@ -309,6 +311,7 @@ QImage EmptyThumbnail::image(int size) {
|
||||||
QSize(size, size) * ratio,
|
QSize(size, size) * ratio,
|
||||||
QImage::Format_ARGB32_Premultiplied);
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
_cached.fill(Qt::black);
|
_cached.fill(Qt::black);
|
||||||
|
_cached.setDevicePixelRatio(ratio);
|
||||||
}
|
}
|
||||||
return _cached;
|
return _cached;
|
||||||
}
|
}
|
||||||
|
@ -336,7 +339,7 @@ Content State::next() {
|
||||||
if (const auto i = _userpics.find(user); i != end(_userpics)) {
|
if (const auto i = _userpics.find(user); i != end(_userpics)) {
|
||||||
userpic = i->second;
|
userpic = i->second;
|
||||||
} else {
|
} else {
|
||||||
userpic = std::make_shared<PeerUserpic>(user);
|
userpic = MakeUserpicThumbnail(user);
|
||||||
_userpics.emplace(user, userpic);
|
_userpics.emplace(user, userpic);
|
||||||
}
|
}
|
||||||
result.elements.push_back({
|
result.elements.push_back({
|
||||||
|
@ -375,19 +378,6 @@ rpl::producer<Content> ContentForSession(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::shared_ptr<Thumbnail> PrepareThumbnail(
|
|
||||||
not_null<Data::Story*> story) {
|
|
||||||
using Result = std::shared_ptr<Thumbnail>;
|
|
||||||
const auto id = story->fullId();
|
|
||||||
return v::match(story->media().data, [](v::null_t) -> Result {
|
|
||||||
return std::make_shared<EmptyThumbnail>();
|
|
||||||
}, [&](not_null<PhotoData*> photo) -> Result {
|
|
||||||
return std::make_shared<PhotoThumbnail>(photo, id);
|
|
||||||
}, [&](not_null<DocumentData*> video) -> Result {
|
|
||||||
return std::make_shared<VideoThumbnail>(video, id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
rpl::producer<Content> LastForPeer(not_null<PeerData*> peer) {
|
rpl::producer<Content> LastForPeer(not_null<PeerData*> peer) {
|
||||||
using namespace rpl::mappers;
|
using namespace rpl::mappers;
|
||||||
|
|
||||||
|
@ -432,7 +422,7 @@ rpl::producer<Content> LastForPeer(not_null<PeerData*> peer) {
|
||||||
result.elements.reserve(ids.size());
|
result.elements.reserve(ids.size());
|
||||||
result.elements.push_back({
|
result.elements.push_back({
|
||||||
.id = uint64(id),
|
.id = uint64(id),
|
||||||
.thumbnail = PrepareThumbnail(*maybe),
|
.thumbnail = MakeStoryThumbnail(*maybe),
|
||||||
.unread = (id > readTill),
|
.unread = (id > readTill),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -459,4 +449,21 @@ rpl::producer<Content> LastForPeer(not_null<PeerData*> peer) {
|
||||||
}) | rpl::flatten_latest();
|
}) | rpl::flatten_latest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Thumbnail> MakeUserpicThumbnail(not_null<PeerData*> peer) {
|
||||||
|
return std::make_shared<PeerUserpic>(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Thumbnail> MakeStoryThumbnail(
|
||||||
|
not_null<Data::Story*> story) {
|
||||||
|
using Result = std::shared_ptr<Thumbnail>;
|
||||||
|
const auto id = story->fullId();
|
||||||
|
return v::match(story->media().data, [](v::null_t) -> Result {
|
||||||
|
return std::make_shared<EmptyThumbnail>();
|
||||||
|
}, [&](not_null<PhotoData*> photo) -> Result {
|
||||||
|
return std::make_shared<PhotoThumbnail>(photo, id);
|
||||||
|
}, [&](not_null<DocumentData*> video) -> Result {
|
||||||
|
return std::make_shared<VideoThumbnail>(video, id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Dialogs::Stories
|
} // namespace Dialogs::Stories
|
||||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
enum class StorySourcesList : uchar;
|
enum class StorySourcesList : uchar;
|
||||||
|
class Story;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
|
@ -18,6 +19,7 @@ class Session;
|
||||||
namespace Dialogs::Stories {
|
namespace Dialogs::Stories {
|
||||||
|
|
||||||
struct Content;
|
struct Content;
|
||||||
|
class Thumbnail;
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<Content> ContentForSession(
|
[[nodiscard]] rpl::producer<Content> ContentForSession(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
|
@ -25,4 +27,9 @@ struct Content;
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<Content> LastForPeer(not_null<PeerData*> peer);
|
[[nodiscard]] rpl::producer<Content> LastForPeer(not_null<PeerData*> peer);
|
||||||
|
|
||||||
|
[[nodiscard]] std::shared_ptr<Thumbnail> MakeUserpicThumbnail(
|
||||||
|
not_null<PeerData*> peer);
|
||||||
|
[[nodiscard]] std::shared_ptr<Thumbnail> MakeStoryThumbnail(
|
||||||
|
not_null<Data::Story*> story);
|
||||||
|
|
||||||
} // namespace Dialogs::Stories
|
} // namespace Dialogs::Stories
|
||||||
|
|
|
@ -294,7 +294,7 @@ std::unique_ptr<Data::Media> HistoryItem::CreateMedia(
|
||||||
return std::make_unique<Data::MediaStory>(item, FullStoryId{
|
return std::make_unique<Data::MediaStory>(item, FullStoryId{
|
||||||
peerFromUser(media.vuser_id()),
|
peerFromUser(media.vuser_id()),
|
||||||
media.vid().v,
|
media.vid().v,
|
||||||
});
|
}, media.is_via_mention());
|
||||||
}, [](const MTPDmessageMediaEmpty &) -> Result {
|
}, [](const MTPDmessageMediaEmpty &) -> Result {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}, [](const MTPDmessageMediaUnsupported &) -> Result {
|
}, [](const MTPDmessageMediaUnsupported &) -> Result {
|
||||||
|
@ -330,6 +330,10 @@ HistoryItem::HistoryItem(
|
||||||
} else if (checked == MediaCheckResult::HasTimeToLive) {
|
} else if (checked == MediaCheckResult::HasTimeToLive) {
|
||||||
createServiceFromMtp(data);
|
createServiceFromMtp(data);
|
||||||
applyTTL(data);
|
applyTTL(data);
|
||||||
|
} else if (checked == MediaCheckResult::HasStoryMention) {
|
||||||
|
setMedia(*data.vmedia());
|
||||||
|
createServiceFromMtp(data);
|
||||||
|
applyTTL(data);
|
||||||
} else {
|
} else {
|
||||||
createComponents(data);
|
createComponents(data);
|
||||||
if (const auto media = data.vmedia()) {
|
if (const auto media = data.vmedia()) {
|
||||||
|
@ -1055,6 +1059,10 @@ void HistoryItem::updateServiceText(PreparedServiceText &&text) {
|
||||||
_history->owner().updateDependentMessages(this);
|
_history->owner().updateDependentMessages(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryItem::updateStoryMentionText() {
|
||||||
|
setServiceText(prepareStoryMentionText());
|
||||||
|
}
|
||||||
|
|
||||||
HistoryMessageReplyMarkup *HistoryItem::inlineReplyMarkup() {
|
HistoryMessageReplyMarkup *HistoryItem::inlineReplyMarkup() {
|
||||||
if (const auto markup = Get<HistoryMessageReplyMarkup>()) {
|
if (const auto markup = Get<HistoryMessageReplyMarkup>()) {
|
||||||
if (markup->data.flags & ReplyMarkupFlag::Inline) {
|
if (markup->data.flags & ReplyMarkupFlag::Inline) {
|
||||||
|
@ -3386,15 +3394,13 @@ void HistoryItem::refreshSentMedia(const MTPMessageMedia *media) {
|
||||||
void HistoryItem::createServiceFromMtp(const MTPDmessage &message) {
|
void HistoryItem::createServiceFromMtp(const MTPDmessage &message) {
|
||||||
AddComponents(HistoryServiceData::Bit());
|
AddComponents(HistoryServiceData::Bit());
|
||||||
|
|
||||||
|
const auto unread = message.is_media_unread();
|
||||||
const auto media = message.vmedia();
|
const auto media = message.vmedia();
|
||||||
Assert(media != nullptr);
|
Assert(media != nullptr);
|
||||||
|
|
||||||
const auto mediaType = media->type();
|
media->match([&](const MTPDmessageMediaPhoto &data) {
|
||||||
switch (mediaType) {
|
if (unread) {
|
||||||
case mtpc_messageMediaPhoto: {
|
const auto ttl = data.vttl_seconds();
|
||||||
if (message.is_media_unread()) {
|
|
||||||
const auto &photo = media->c_messageMediaPhoto();
|
|
||||||
const auto ttl = photo.vttl_seconds();
|
|
||||||
Assert(ttl != nullptr);
|
Assert(ttl != nullptr);
|
||||||
|
|
||||||
setSelfDestruct(HistoryServiceSelfDestruct::Type::Photo, ttl->v);
|
setSelfDestruct(HistoryServiceSelfDestruct::Type::Photo, ttl->v);
|
||||||
|
@ -3417,11 +3423,9 @@ void HistoryItem::createServiceFromMtp(const MTPDmessage &message) {
|
||||||
tr::lng_ttl_photo_expired(tr::now, Ui::Text::WithEntities)
|
tr::lng_ttl_photo_expired(tr::now, Ui::Text::WithEntities)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} break;
|
}, [&](const MTPDmessageMediaDocument &data) {
|
||||||
case mtpc_messageMediaDocument: {
|
if (unread) {
|
||||||
if (message.is_media_unread()) {
|
const auto ttl = data.vttl_seconds();
|
||||||
const auto &document = media->c_messageMediaDocument();
|
|
||||||
const auto ttl = document.vttl_seconds();
|
|
||||||
Assert(ttl != nullptr);
|
Assert(ttl != nullptr);
|
||||||
|
|
||||||
setSelfDestruct(HistoryServiceSelfDestruct::Type::Video, ttl->v);
|
setSelfDestruct(HistoryServiceSelfDestruct::Type::Video, ttl->v);
|
||||||
|
@ -3444,10 +3448,11 @@ void HistoryItem::createServiceFromMtp(const MTPDmessage &message) {
|
||||||
tr::lng_ttl_video_expired(tr::now, Ui::Text::WithEntities)
|
tr::lng_ttl_video_expired(tr::now, Ui::Text::WithEntities)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} break;
|
}, [&](const MTPDmessageMediaStory &data) {
|
||||||
|
setServiceText(prepareStoryMentionText());
|
||||||
default: Unexpected("Media type in HistoryItem::createServiceFromMtp()");
|
}, [](const auto &) {
|
||||||
}
|
Unexpected("Media type in HistoryItem::createServiceFromMtp()");
|
||||||
|
});
|
||||||
|
|
||||||
if (const auto reactions = message.vreactions()) {
|
if (const auto reactions = message.vreactions()) {
|
||||||
updateReactions(reactions);
|
updateReactions(reactions);
|
||||||
|
@ -4816,6 +4821,28 @@ PreparedServiceText HistoryItem::preparePaymentSentText() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PreparedServiceText HistoryItem::prepareStoryMentionText() {
|
||||||
|
auto result = PreparedServiceText();
|
||||||
|
const auto peer = history()->peer;
|
||||||
|
result.links.push_back(peer->createOpenLink());
|
||||||
|
const auto phrase = (this->media() && this->media()->storyExpired())
|
||||||
|
? (out()
|
||||||
|
? tr::lng_action_story_mention_me_unavailable
|
||||||
|
: tr::lng_action_story_mention_unavailable)
|
||||||
|
: (out()
|
||||||
|
? tr::lng_action_story_mention_me
|
||||||
|
: tr::lng_action_story_mention);
|
||||||
|
result.text = phrase(
|
||||||
|
tr::now,
|
||||||
|
lt_user,
|
||||||
|
Ui::Text::Wrapped(
|
||||||
|
Ui::Text::Bold(peer->shortName()),
|
||||||
|
EntityType::CustomUrl,
|
||||||
|
u"internal:index"_q + QChar(1)),
|
||||||
|
Ui::Text::WithEntities);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
PreparedServiceText HistoryItem::prepareCallScheduledText(
|
PreparedServiceText HistoryItem::prepareCallScheduledText(
|
||||||
TimeId scheduleDate) {
|
TimeId scheduleDate) {
|
||||||
const auto call = Get<HistoryServiceOngoingCall>();
|
const auto call = Get<HistoryServiceOngoingCall>();
|
||||||
|
|
|
@ -196,6 +196,7 @@ public:
|
||||||
void checkBuyButton();
|
void checkBuyButton();
|
||||||
|
|
||||||
void updateServiceText(PreparedServiceText &&text);
|
void updateServiceText(PreparedServiceText &&text);
|
||||||
|
void updateStoryMentionText();
|
||||||
|
|
||||||
[[nodiscard]] UserData *viaBot() const;
|
[[nodiscard]] UserData *viaBot() const;
|
||||||
[[nodiscard]] UserData *getMessageBot() const;
|
[[nodiscard]] UserData *getMessageBot() const;
|
||||||
|
@ -608,6 +609,7 @@ private:
|
||||||
[[nodiscard]] PreparedServiceText preparePinnedText();
|
[[nodiscard]] PreparedServiceText preparePinnedText();
|
||||||
[[nodiscard]] PreparedServiceText prepareGameScoreText();
|
[[nodiscard]] PreparedServiceText prepareGameScoreText();
|
||||||
[[nodiscard]] PreparedServiceText preparePaymentSentText();
|
[[nodiscard]] PreparedServiceText preparePaymentSentText();
|
||||||
|
[[nodiscard]] PreparedServiceText prepareStoryMentionText();
|
||||||
[[nodiscard]] PreparedServiceText prepareInvitedToCallText(
|
[[nodiscard]] PreparedServiceText prepareInvitedToCallText(
|
||||||
const std::vector<not_null<UserData*>> &users,
|
const std::vector<not_null<UserData*>> &users,
|
||||||
CallId linkCallId);
|
CallId linkCallId);
|
||||||
|
|
|
@ -450,7 +450,9 @@ MediaCheckResult CheckMessageMedia(const MTPMessageMedia &media) {
|
||||||
}, [](const MTPDmessageMediaDice &) {
|
}, [](const MTPDmessageMediaDice &) {
|
||||||
return Result::Good;
|
return Result::Good;
|
||||||
}, [](const MTPDmessageMediaStory &data) {
|
}, [](const MTPDmessageMediaStory &data) {
|
||||||
return Result::Good;
|
return data.is_via_mention()
|
||||||
|
? Result::HasStoryMention
|
||||||
|
: Result::Good;
|
||||||
}, [](const MTPDmessageMediaUnsupported &) {
|
}, [](const MTPDmessageMediaUnsupported &) {
|
||||||
return Result::Unsupported;
|
return Result::Unsupported;
|
||||||
});
|
});
|
||||||
|
|
|
@ -44,6 +44,7 @@ enum class MediaCheckResult {
|
||||||
Unsupported,
|
Unsupported,
|
||||||
Empty,
|
Empty,
|
||||||
HasTimeToLive,
|
HasTimeToLive,
|
||||||
|
HasStoryMention,
|
||||||
};
|
};
|
||||||
[[nodiscard]] MediaCheckResult CheckMessageMedia(
|
[[nodiscard]] MediaCheckResult CheckMessageMedia(
|
||||||
const MTPMessageMedia &media);
|
const MTPMessageMedia &media);
|
||||||
|
|
|
@ -841,13 +841,18 @@ void Element::validateText() {
|
||||||
const auto item = data();
|
const auto item = data();
|
||||||
const auto &text = item->_text;
|
const auto &text = item->_text;
|
||||||
const auto media = item->media();
|
const auto media = item->media();
|
||||||
|
const auto storyMention = media && media->storyMention();
|
||||||
if (media && media->storyExpired()) {
|
if (media && media->storyExpired()) {
|
||||||
_media = nullptr;
|
_media = nullptr;
|
||||||
if (_text.isEmpty()) {
|
if (!storyMention) {
|
||||||
setTextWithLinks(
|
if (_text.isEmpty()) {
|
||||||
Ui::Text::Italic(u"This story has expired"_q));
|
setTextWithLinks(
|
||||||
|
Ui::Text::Italic(u"This story has expired"_q));
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else if (_text.isEmpty() == text.empty()) {
|
}
|
||||||
|
if (_text.isEmpty() == text.empty()) {
|
||||||
} else if (_flags & Flag::ServiceMessage) {
|
} 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()
|
||||||
|
|
|
@ -54,8 +54,8 @@ QString PremiumGift::title() {
|
||||||
return tr::lng_premium_summary_title(tr::now);
|
return tr::lng_premium_summary_title(tr::now);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PremiumGift::subtitle() {
|
TextWithEntities PremiumGift::subtitle() {
|
||||||
return FormatGiftMonths(_gift->months());
|
return { FormatGiftMonths(_gift->months()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PremiumGift::button() {
|
QString PremiumGift::button() {
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
int top() override;
|
int top() override;
|
||||||
QSize size() override;
|
QSize size() override;
|
||||||
QString title() override;
|
QString title() override;
|
||||||
QString subtitle() override;
|
TextWithEntities subtitle() override;
|
||||||
QString button() override;
|
QString button() override;
|
||||||
void draw(
|
void draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "ui/chat/chat_style.h"
|
#include "ui/chat/chat_style.h"
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
#include "styles/style_premium.h"
|
#include "styles/style_premium.h"
|
||||||
|
@ -57,8 +58,15 @@ ServiceBox::ServiceBox(
|
||||||
_maxWidth)
|
_maxWidth)
|
||||||
, _subtitle(
|
, _subtitle(
|
||||||
st::premiumPreviewAbout.style,
|
st::premiumPreviewAbout.style,
|
||||||
_content->subtitle(),
|
Ui::Text::Filtered(
|
||||||
kDefaultTextOptions,
|
_content->subtitle(),
|
||||||
|
{
|
||||||
|
EntityType::Bold,
|
||||||
|
EntityType::StrikeOut,
|
||||||
|
EntityType::Underline,
|
||||||
|
EntityType::Italic,
|
||||||
|
}),
|
||||||
|
kMarkupTextOptions,
|
||||||
_maxWidth)
|
_maxWidth)
|
||||||
, _size(
|
, _size(
|
||||||
st::msgServiceGiftBoxSize.width(),
|
st::msgServiceGiftBoxSize.width(),
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
[[nodiscard]] virtual int top() = 0;
|
[[nodiscard]] virtual int top() = 0;
|
||||||
[[nodiscard]] virtual QSize size() = 0;
|
[[nodiscard]] virtual QSize size() = 0;
|
||||||
[[nodiscard]] virtual QString title() = 0;
|
[[nodiscard]] virtual QString title() = 0;
|
||||||
[[nodiscard]] virtual QString subtitle() = 0;
|
[[nodiscard]] virtual TextWithEntities subtitle() = 0;
|
||||||
[[nodiscard]] virtual QString button() = 0;
|
[[nodiscard]] virtual QString button() = 0;
|
||||||
virtual void draw(
|
virtual void draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
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 "history/view/media/history_view_story_mention.h"
|
||||||
|
|
||||||
|
#include "core/click_handler_types.h" // ClickHandlerContext
|
||||||
|
#include "data/data_document.h"
|
||||||
|
#include "data/data_photo.h"
|
||||||
|
#include "data/data_user.h"
|
||||||
|
#include "data/data_photo_media.h"
|
||||||
|
#include "data/data_file_click_handler.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_stories.h"
|
||||||
|
#include "dialogs/ui/dialogs_stories_content.h"
|
||||||
|
#include "dialogs/ui/dialogs_stories_list.h"
|
||||||
|
#include "editor/photo_editor_common.h"
|
||||||
|
#include "editor/photo_editor_layer_widget.h"
|
||||||
|
#include "history/history.h"
|
||||||
|
#include "history/history_item.h"
|
||||||
|
#include "history/view/media/history_view_sticker_player_abstract.h"
|
||||||
|
#include "history/view/history_view_element.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "window/window_session_controller.h"
|
||||||
|
#include "ui/boxes/confirm_box.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
|
#include "ui/toast/toast.h"
|
||||||
|
#include "ui/painter.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "api/api_peer_photo.h"
|
||||||
|
#include "settings/settings_information.h" // UpdatePhotoLocally
|
||||||
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
|
namespace HistoryView {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
StoryMention::StoryMention(
|
||||||
|
not_null<Element*> parent,
|
||||||
|
not_null<Data::Story*> story)
|
||||||
|
: _parent(parent)
|
||||||
|
, _story(story) {
|
||||||
|
}
|
||||||
|
|
||||||
|
StoryMention::~StoryMention() = default;
|
||||||
|
|
||||||
|
int StoryMention::top() {
|
||||||
|
return st::msgServiceGiftBoxButtonMargins.top();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize StoryMention::size() {
|
||||||
|
return { st::msgServicePhotoWidth, st::msgServicePhotoWidth };
|
||||||
|
}
|
||||||
|
|
||||||
|
QString StoryMention::title() {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString StoryMention::button() {
|
||||||
|
return tr::lng_action_story_mention_button(tr::now);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextWithEntities StoryMention::subtitle() {
|
||||||
|
return _parent->data()->notificationText();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClickHandlerPtr StoryMention::createViewLink() {
|
||||||
|
const auto itemId = _parent->data()->fullId();
|
||||||
|
return std::make_shared<LambdaClickHandler>(crl::guard(this, [=](
|
||||||
|
ClickContext) {
|
||||||
|
if (const auto photo = _story->photo()) {
|
||||||
|
_parent->delegate()->elementOpenPhoto(photo, itemId);
|
||||||
|
} else if (const auto video = _story->document()) {
|
||||||
|
_parent->delegate()->elementOpenDocument(video, itemId);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoryMention::draw(
|
||||||
|
Painter &p,
|
||||||
|
const PaintContext &context,
|
||||||
|
const QRect &geometry) {
|
||||||
|
const auto showStory = !_story->forbidsForward();
|
||||||
|
if (!_thumbnail || _thumbnailFromStory != showStory) {
|
||||||
|
using namespace Dialogs::Stories;
|
||||||
|
const auto item = _parent->data();
|
||||||
|
const auto history = item->history();
|
||||||
|
_thumbnail = showStory
|
||||||
|
? MakeStoryThumbnail(_story)
|
||||||
|
: MakeUserpicThumbnail(item->out()
|
||||||
|
? history->session().user()
|
||||||
|
: history->peer);
|
||||||
|
_thumbnailFromStory = showStory;
|
||||||
|
_subscribed = false;
|
||||||
|
}
|
||||||
|
if (!_subscribed) {
|
||||||
|
_thumbnail->subscribeToUpdates([=] {
|
||||||
|
_parent->data()->history()->owner().requestViewRepaint(_parent);
|
||||||
|
});
|
||||||
|
_subscribed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.drawImage(
|
||||||
|
geometry.topLeft(),
|
||||||
|
_thumbnail->image(st::msgServicePhotoWidth));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoryMention::stickerClearLoopPlayed() {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<StickerPlayer> StoryMention::stickerTakePlayer(
|
||||||
|
not_null<DocumentData*> data,
|
||||||
|
const Lottie::ColorReplacements *replacements) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StoryMention::hasHeavyPart() {
|
||||||
|
return _subscribed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoryMention::unloadHeavyPart() {
|
||||||
|
if (_subscribed) {
|
||||||
|
_subscribed = false;
|
||||||
|
_thumbnail->subscribeToUpdates(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace HistoryView
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "history/view/media/history_view_media.h"
|
||||||
|
#include "history/view/media/history_view_media_unwrapped.h"
|
||||||
|
#include "history/view/media/history_view_service_box.h"
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
class Story;
|
||||||
|
} // namespace Data
|
||||||
|
|
||||||
|
namespace Dialogs::Stories {
|
||||||
|
class Thumbnail;
|
||||||
|
} // namespace Dialogs::Stories
|
||||||
|
|
||||||
|
namespace HistoryView {
|
||||||
|
|
||||||
|
class StoryMention final
|
||||||
|
: public ServiceBoxContent
|
||||||
|
, public base::has_weak_ptr {
|
||||||
|
public:
|
||||||
|
StoryMention(not_null<Element*> parent, not_null<Data::Story*> story);
|
||||||
|
~StoryMention();
|
||||||
|
|
||||||
|
int top() override;
|
||||||
|
QSize size() override;
|
||||||
|
QString title() override;
|
||||||
|
TextWithEntities subtitle() override;
|
||||||
|
QString button() override;
|
||||||
|
void draw(
|
||||||
|
Painter &p,
|
||||||
|
const PaintContext &context,
|
||||||
|
const QRect &geometry) override;
|
||||||
|
ClickHandlerPtr createViewLink() override;
|
||||||
|
|
||||||
|
bool hideServiceText() override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stickerClearLoopPlayed() override;
|
||||||
|
std::unique_ptr<StickerPlayer> stickerTakePlayer(
|
||||||
|
not_null<DocumentData*> data,
|
||||||
|
const Lottie::ColorReplacements *replacements) override;
|
||||||
|
|
||||||
|
bool hasHeavyPart() override;
|
||||||
|
void unloadHeavyPart() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using Thumbnail = Dialogs::Stories::Thumbnail;
|
||||||
|
|
||||||
|
const not_null<Element*> _parent;
|
||||||
|
const not_null<Data::Story*> _story;
|
||||||
|
std::shared_ptr<Thumbnail> _thumbnail;
|
||||||
|
bool _thumbnailFromStory = false;
|
||||||
|
bool _subscribed = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace HistoryView
|
|
@ -460,8 +460,8 @@ QString ThemeDocumentBox::title() {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ThemeDocumentBox::subtitle() {
|
TextWithEntities ThemeDocumentBox::subtitle() {
|
||||||
return _parent->data()->notificationText().text;
|
return _parent->data()->notificationText();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ThemeDocumentBox::button() {
|
QString ThemeDocumentBox::button() {
|
||||||
|
|
|
@ -99,7 +99,7 @@ public:
|
||||||
int top() override;
|
int top() override;
|
||||||
QSize size() override;
|
QSize size() override;
|
||||||
QString title() override;
|
QString title() override;
|
||||||
QString subtitle() override;
|
TextWithEntities subtitle() override;
|
||||||
QString button() override;
|
QString button() override;
|
||||||
void draw(
|
void draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
|
|
@ -211,8 +211,8 @@ QString UserpicSuggestion::button() {
|
||||||
: tr::lng_action_suggested_photo_button(tr::now);
|
: tr::lng_action_suggested_photo_button(tr::now);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString UserpicSuggestion::subtitle() {
|
TextWithEntities UserpicSuggestion::subtitle() {
|
||||||
return _photo.parent()->data()->notificationText().text;
|
return _photo.parent()->data()->notificationText();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClickHandlerPtr UserpicSuggestion::createViewLink() {
|
ClickHandlerPtr UserpicSuggestion::createViewLink() {
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
int top() override;
|
int top() override;
|
||||||
QSize size() override;
|
QSize size() override;
|
||||||
QString title() override;
|
QString title() override;
|
||||||
QString subtitle() override;
|
TextWithEntities subtitle() override;
|
||||||
QString button() override;
|
QString button() override;
|
||||||
void draw(
|
void draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
|
|
@ -1135,7 +1135,7 @@ codeSettings#ad253d78 flags:# allow_flashcall:flags.0?true current_number:flags.
|
||||||
|
|
||||||
wallPaperSettings#1dc1bca4 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int second_background_color:flags.4?int third_background_color:flags.5?int fourth_background_color:flags.6?int intensity:flags.3?int rotation:flags.4?int = WallPaperSettings;
|
wallPaperSettings#1dc1bca4 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int second_background_color:flags.4?int third_background_color:flags.5?int fourth_background_color:flags.6?int intensity:flags.3?int rotation:flags.4?int = WallPaperSettings;
|
||||||
|
|
||||||
autoDownloadSettings#baa57628 flags:# disabled:flags.0?true video_preload_large:flags.1?true audio_preload_next:flags.2?true phonecalls_less_data:flags.3?true photo_size_max:int video_size_max:long file_size_max:long video_upload_maxbitrate:int small_queue_active_operations_max:int large_queue_active_operations_max:int = AutoDownloadSettings;
|
autoDownloadSettings#baa57628 flags:# disabled:flags.0?true video_preload_large:flags.1?true audio_preload_next:flags.2?true phonecalls_less_data:flags.3?true stories_preload:flags.4?true photo_size_max:int video_size_max:long file_size_max:long video_upload_maxbitrate:int small_queue_active_operations_max:int large_queue_active_operations_max:int = AutoDownloadSettings;
|
||||||
|
|
||||||
account.autoDownloadSettings#63cacf26 low:AutoDownloadSettings medium:AutoDownloadSettings high:AutoDownloadSettings = account.AutoDownloadSettings;
|
account.autoDownloadSettings#63cacf26 low:AutoDownloadSettings medium:AutoDownloadSettings high:AutoDownloadSettings = account.AutoDownloadSettings;
|
||||||
|
|
||||||
|
@ -1530,7 +1530,7 @@ storyViews#d36760cf flags:# views_count:int recent_viewers:flags.0?Vector<long>
|
||||||
|
|
||||||
storyItemDeleted#51e6ee4f id:int = StoryItem;
|
storyItemDeleted#51e6ee4f id:int = StoryItem;
|
||||||
storyItemSkipped#693206a2 id:int date:int expire_date:int = StoryItem;
|
storyItemSkipped#693206a2 id:int date:int expire_date:int = StoryItem;
|
||||||
storyItem#562aa637 flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true id:int date:int expire_date:int caption:flags.0?string entities:flags.1?Vector<MessageEntity> media:MessageMedia privacy:flags.2?Vector<PrivacyRule> views:flags.3?StoryViews = StoryItem;
|
storyItem#562aa637 flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true noforwards:flags.10?true edited:flags.11?true id:int date:int expire_date:int caption:flags.0?string entities:flags.1?Vector<MessageEntity> media:MessageMedia privacy:flags.2?Vector<PrivacyRule> views:flags.3?StoryViews = StoryItem;
|
||||||
|
|
||||||
userStories#8611a200 flags:# user_id:long max_read_id:flags.0?int stories:Vector<StoryItem> = UserStories;
|
userStories#8611a200 flags:# user_id:long max_read_id:flags.0?int stories:Vector<StoryItem> = UserStories;
|
||||||
|
|
||||||
|
@ -2087,7 +2087,7 @@ chatlists.hideChatlistUpdates#66e486fb chatlist:InputChatlist = Bool;
|
||||||
chatlists.getLeaveChatlistSuggestions#fdbcd714 chatlist:InputChatlist = Vector<Peer>;
|
chatlists.getLeaveChatlistSuggestions#fdbcd714 chatlist:InputChatlist = Vector<Peer>;
|
||||||
chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector<InputPeer> = Updates;
|
chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector<InputPeer> = Updates;
|
||||||
|
|
||||||
stories.sendStory#424cd47a flags:# pinned:flags.2?true media:InputMedia caption:flags.0?string entities:flags.1?Vector<MessageEntity> privacy_rules:Vector<InputPrivacyRule> random_id:long period:flags.3?int = Updates;
|
stories.sendStory#424cd47a flags:# pinned:flags.2?true noforwards:flags.4?true media:InputMedia caption:flags.0?string entities:flags.1?Vector<MessageEntity> privacy_rules:Vector<InputPrivacyRule> random_id:long period:flags.3?int = Updates;
|
||||||
stories.editStory#2aae7a41 flags:# id:int media:flags.0?InputMedia caption:flags.1?string entities:flags.1?Vector<MessageEntity> privacy_rules:flags.2?Vector<InputPrivacyRule> = Updates;
|
stories.editStory#2aae7a41 flags:# id:int media:flags.0?InputMedia caption:flags.1?string entities:flags.1?Vector<MessageEntity> privacy_rules:flags.2?Vector<InputPrivacyRule> = Updates;
|
||||||
stories.deleteStories#b5d501d7 id:Vector<int> = Vector<int>;
|
stories.deleteStories#b5d501d7 id:Vector<int> = Vector<int>;
|
||||||
stories.togglePinned#51602944 id:Vector<int> pinned:Bool = Vector<int>;
|
stories.togglePinned#51602944 id:Vector<int> pinned:Bool = Vector<int>;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 855f8f7b75f83127642eb5bbb1457f2087b3f1de
|
Subproject commit ed00cd28098e1b04979e7b2dd3a582b7a8a6713a
|
Loading…
Add table
Reference in a new issue