Show unsupported stories with an Update button.

This commit is contained in:
John Preston 2023-06-16 13:34:08 +04:00
parent ad5b96b049
commit a2bf0fc511
13 changed files with 138 additions and 20 deletions

View File

@ -3807,6 +3807,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stories_views#one" = "{count} view"; "lng_stories_views#one" = "{count} view";
"lng_stories_views#other" = "{count} views"; "lng_stories_views#other" = "{count} views";
"lng_stories_no_views" = "No views"; "lng_stories_no_views" = "No views";
"lng_stories_unsupported" = "This story is not supported\nby your version of Telegram.";
"lng_stories_my_title" = "My Stories"; "lng_stories_my_title" = "My Stories";
"lng_stories_archive_button" = "Archive"; "lng_stories_archive_button" = "Archive";

View File

@ -2039,6 +2039,11 @@ bool MediaStory::updateSentMedia(const MTPMessageMedia &media) {
return false; return false;
} }
not_null<PhotoData*> MediaStory::LoadingStoryPhoto(
not_null<Session*> owner) {
return owner->photo(kLoadingStoryPhotoId);
}
std::unique_ptr<HistoryView::Media> MediaStory::createView( std::unique_ptr<HistoryView::Media> MediaStory::createView(
not_null<HistoryView::Element*> message, not_null<HistoryView::Element*> message,
not_null<HistoryItem*> realParent, not_null<HistoryItem*> realParent,
@ -2055,7 +2060,7 @@ std::unique_ptr<HistoryView::Media> MediaStory::createView(
return std::make_unique<HistoryView::Photo>( return std::make_unique<HistoryView::Photo>(
message, message,
realParent, realParent,
realParent->history()->owner().photo(kLoadingStoryPhotoId), LoadingStoryPhoto(&realParent->history()->owner()),
spoiler); spoiler);
} }
_expired = false; _expired = false;

View File

@ -38,6 +38,7 @@ namespace Data {
class CloudImage; class CloudImage;
class WallPaper; class WallPaper;
class Session;
enum class CallFinishReason : char { enum class CallFinishReason : char {
Missed, Missed,
@ -59,6 +60,7 @@ struct Call {
int duration = 0; int duration = 0;
FinishReason finishReason = FinishReason::Missed; FinishReason finishReason = FinishReason::Missed;
bool video = false; bool video = false;
}; };
struct ExtendedPreview { struct ExtendedPreview {
@ -587,6 +589,9 @@ public:
not_null<HistoryItem*> realParent, not_null<HistoryItem*> realParent,
HistoryView::Element *replacing = nullptr) override; HistoryView::Element *replacing = nullptr) override;
[[nodiscard]] static not_null<PhotoData*> LoadingStoryPhoto(
not_null<Session*> owner);
private: private:
const FullStoryId _storyId; const FullStoryId _storyId;
bool _expired = false; bool _expired = false;

View File

@ -63,6 +63,8 @@ using UpdateFlag = StoryUpdate::Flag;
} }
} }
return {}; return {};
}, [&](const MTPDmessageMediaUnsupported &data) {
return std::make_optional(StoryMedia{ v::null });
}, [](const auto &) { return std::optional<StoryMedia>(); }); }, [](const auto &) { return std::optional<StoryMedia>(); });
} }
@ -135,6 +137,10 @@ bool Story::expired(TimeId now) const {
return _expires <= (now ? now : base::unixtime::now()); return _expires <= (now ? now : base::unixtime::now());
} }
bool Story::unsupported() const {
return v::is_null(_media.data);
}
const StoryMedia &Story::media() const { const StoryMedia &Story::media() const {
return _media; return _media;
} }
@ -154,6 +160,8 @@ bool Story::hasReplyPreview() const {
return !photo->isNull(); return !photo->isNull();
}, [](not_null<DocumentData*> document) { }, [](not_null<DocumentData*> document) {
return document->hasThumbnail(); return document->hasThumbnail();
}, [](v::null_t) {
return false;
}); });
} }
@ -168,6 +176,8 @@ Image *Story::replyPreview() const {
Data::FileOriginStory(_peer->id, _id), Data::FileOriginStory(_peer->id, _id),
_peer, _peer,
false); false);
}, [](v::null_t) {
return (Image*)nullptr;
}); });
} }
@ -246,7 +256,8 @@ void Story::setCaption(TextWithEntities &&caption) {
} }
const TextWithEntities &Story::caption() const { const TextWithEntities &Story::caption() const {
return _caption; static const auto empty = TextWithEntities();
return unsupported() ? empty : _caption;
} }
void Story::setViewsData( void Story::setViewsData(

View File

@ -55,7 +55,10 @@ struct StoriesIds {
}; };
struct StoryMedia { struct StoryMedia {
std::variant<not_null<PhotoData*>, not_null<DocumentData*>> data; std::variant<
v::null_t,
not_null<PhotoData*>,
not_null<DocumentData*>> data;
friend inline bool operator==(StoryMedia, StoryMedia) = default; friend inline bool operator==(StoryMedia, StoryMedia) = default;
}; };
@ -86,6 +89,7 @@ public:
[[nodiscard]] FullStoryId fullId() const; [[nodiscard]] FullStoryId fullId() const;
[[nodiscard]] TimeId date() const; [[nodiscard]] TimeId date() const;
[[nodiscard]] TimeId expires() const; [[nodiscard]] TimeId expires() const;
[[nodiscard]] bool unsupported() const;
[[nodiscard]] bool expired(TimeId now = 0) const; [[nodiscard]] bool expired(TimeId now = 0) const;
[[nodiscard]] const StoryMedia &media() const; [[nodiscard]] const StoryMedia &media() const;
[[nodiscard]] PhotoData *photo() const; [[nodiscard]] PhotoData *photo() const;

View File

@ -685,7 +685,10 @@ HistoryItem::HistoryItem(
: id(StoryIdToMsgId(story->id())) : id(StoryIdToMsgId(story->id()))
, _history(history) , _history(history)
, _from(history->peer) , _from(history->peer)
, _flags(MessageFlag::Local | MessageFlag::Outgoing | MessageFlag::FakeHistoryItem | MessageFlag::StoryItem) , _flags(MessageFlag::Local
| MessageFlag::Outgoing
| MessageFlag::FakeHistoryItem
| MessageFlag::StoryItem)
, _date(story->date()) { , _date(story->date()) {
setStoryFields(story); setStoryFields(story);
} }
@ -1522,8 +1525,7 @@ void HistoryItem::setStoryFields(not_null<Data::Story*> story) {
const auto spoiler = false; const auto spoiler = false;
if (const auto photo = story->photo()) { if (const auto photo = story->photo()) {
_media = std::make_unique<Data::MediaPhoto>(this, photo, spoiler); _media = std::make_unique<Data::MediaPhoto>(this, photo, spoiler);
} else { } else if (const auto document = story->document()) {
const auto document = story->document();
_media = std::make_unique<Data::MediaFile>( _media = std::make_unique<Data::MediaFile>(
this, this,
document, document,

View File

@ -302,6 +302,12 @@ std::unique_ptr<BaseLayout> Provider::createLayout(
return std::make_unique<Photo>(delegate, item, photo, spoiler); return std::make_unique<Photo>(delegate, item, photo, spoiler);
} else if (const auto file = getFile()) { } else if (const auto file = getFile()) {
return std::make_unique<Video>(delegate, item, file, spoiler); return std::make_unique<Video>(delegate, item, file, spoiler);
} else {
return std::make_unique<Photo>(
delegate,
item,
Data::MediaStory::LoadingStoryPhoto(&item->history()->owner()),
spoiler);
} }
return nullptr; return nullptr;
} }

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/power_save_blocker.h" #include "base/power_save_blocker.h"
#include "base/qt_signal_producer.h" #include "base/qt_signal_producer.h"
#include "chat_helpers/compose/compose_show.h" #include "chat_helpers/compose/compose_show.h"
#include "core/update_checker.h"
#include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_custom_emoji.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
@ -19,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_stories.h" #include "data/data_stories.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "history/view/reactions/history_view_reactions_strip.h" #include "history/view/reactions/history_view_reactions_strip.h"
#include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "media/stories/media_stories_caption_full_view.h" #include "media/stories/media_stories_caption_full_view.h"
#include "media/stories/media_stories_delegate.h" #include "media/stories/media_stories_delegate.h"
@ -35,6 +37,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/message_sending_animation_common.h" #include "ui/effects/message_sending_animation_common.h"
#include "ui/effects/reaction_fly_animation.h" #include "ui/effects/reaction_fly_animation.h"
#include "ui/layers/box_content.h" #include "ui/layers/box_content.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "styles/style_media_view.h" #include "styles/style_media_view.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
@ -78,6 +82,19 @@ private:
}; };
class Controller::Unsupported final {
public:
explicit Unsupported(not_null<Controller*> controller);
private:
void setup();
const not_null<Controller*> _controller;
std::unique_ptr<Ui::FlatLabel> _text;
std::unique_ptr<Ui::RoundButton> _button;
};
Controller::PhotoPlayback::PhotoPlayback(not_null<Controller*> controller) Controller::PhotoPlayback::PhotoPlayback(not_null<Controller*> controller)
: _controller(controller) : _controller(controller)
, _timer([=] { callback(); }) , _timer([=] { callback(); })
@ -129,6 +146,42 @@ void Controller::PhotoPlayback::callback() {
}); });
} }
Controller::Unsupported::Unsupported(not_null<Controller*> controller)
: _controller(controller) {
setup();
}
void Controller::Unsupported::setup() {
const auto wrap = _controller->wrap();
_text = std::make_unique<Ui::FlatLabel>(
wrap,
tr::lng_stories_unsupported(),
st::storiesUnsupportedLabel);
_text->show();
_button = std::make_unique<Ui::RoundButton>(
wrap,
tr::lng_update_telegram(),
st::storiesUnsupportedUpdate);
_button->show();
rpl::combine(
wrap->sizeValue(),
_text->sizeValue(),
_button->sizeValue()
) | rpl::start_with_next([=](QSize wrap, QSize text, QSize button) {
_text->move((wrap.width() - text.width()) / 2, wrap.height() / 3);
_button->move(
(wrap.width() - button.width()) / 2,
2 * wrap.height() / 3);
}, _button->lifetime());
_button->setClickedCallback([=] {
Core::UpdateApplication();
});
}
Controller::Controller(not_null<Delegate*> delegate) Controller::Controller(not_null<Delegate*> delegate)
: _delegate(delegate) : _delegate(delegate)
, _wrap(_delegate->storiesWrap()) , _wrap(_delegate->storiesWrap())
@ -584,13 +637,19 @@ void Controller::show(
const auto guard = gsl::finally([&] { const auto guard = gsl::finally([&] {
_paused = false; _paused = false;
_started = false; _started = false;
if (story->photo()) { if (!story->document()) {
_photoPlayback = std::make_unique<PhotoPlayback>(this); _photoPlayback = std::make_unique<PhotoPlayback>(this);
} else { } else {
_photoPlayback = nullptr; _photoPlayback = nullptr;
} }
}); });
if (!story->unsupported()) {
_unsupported = nullptr;
} else {
_unsupported = std::make_unique<Unsupported>(this);
}
if (_shown == storyId) { if (_shown == storyId) {
return; return;
} }

View File

@ -148,6 +148,7 @@ private:
const StoriesList &) = default; const StoriesList &) = default;
}; };
class PhotoPlayback; class PhotoPlayback;
class Unsupported;
void initLayout(); void initLayout();
void updatePhotoPlayback(const Player::TrackState &state); void updatePhotoPlayback(const Player::TrackState &state);
@ -200,6 +201,7 @@ private:
const std::unique_ptr<ReplyArea> _replyArea; const std::unique_ptr<ReplyArea> _replyArea;
const std::unique_ptr<Reactions> _reactions; const std::unique_ptr<Reactions> _reactions;
const std::unique_ptr<RecentViews> _recentViews; const std::unique_ptr<RecentViews> _recentViews;
std::unique_ptr<Unsupported> _unsupported;
std::unique_ptr<PhotoPlayback> _photoPlayback; std::unique_ptr<PhotoPlayback> _photoPlayback;
std::unique_ptr<CaptionFullView> _captionFullView; std::unique_ptr<CaptionFullView> _captionFullView;

View File

@ -242,11 +242,7 @@ void Sibling::checkStory() {
const auto maybeStory = _peer->owner().stories().lookup(_id); const auto maybeStory = _peer->owner().stories().lookup(_id);
if (!maybeStory) { if (!maybeStory) {
if (_blurred.isNull()) { if (_blurred.isNull()) {
_blurred = QImage( setBlackThumbnail();
st::storiesMaxSize,
QImage::Format_ARGB32_Premultiplied);
_blurred.fill(Qt::black);
if (maybeStory.error() == Data::NoStory::Unknown) { if (maybeStory.error() == Data::NoStory::Unknown) {
_peer->owner().stories().resolve(_id, crl::guard(this, [=] { _peer->owner().stories().resolve(_id, crl::guard(this, [=] {
checkStory(); checkStory();
@ -266,11 +262,24 @@ void Sibling::checkStory() {
_loader = std::make_unique<LoaderVideo>(document, origin, [=] { _loader = std::make_unique<LoaderVideo>(document, origin, [=] {
check(); check();
}); });
}, [&](v::null_t) {
_loader = nullptr;
}); });
if (!_loader) {
setBlackThumbnail();
return;
}
_blurred = _loader->blurred(); _blurred = _loader->blurred();
check(); check();
} }
void Sibling::setBlackThumbnail() {
_blurred = QImage(
st::storiesMaxSize,
QImage::Format_ARGB32_Premultiplied);
_blurred.fill(Qt::black);
}
FullStoryId Sibling::shownId() const { FullStoryId Sibling::shownId() const {
return _id; return _id;
} }

View File

@ -45,6 +45,7 @@ private:
void checkStory(); void checkStory();
void check(); void check();
void setBlackThumbnail();
[[nodiscard]] QImage userpicImage(const SiblingLayout &layout); [[nodiscard]] QImage userpicImage(const SiblingLayout &layout);
[[nodiscard]] QImage nameImage(const SiblingLayout &layout); [[nodiscard]] QImage nameImage(const SiblingLayout &layout);
[[nodiscard]] QPoint namePosition( [[nodiscard]] QPoint namePosition(

View File

@ -782,3 +782,14 @@ storiesReactionsPan: EmojiPan(storiesEmojiPan) {
storiesReactionsWidth: 210px; storiesReactionsWidth: 210px;
storiesReactionsBottomSkip: 29px; storiesReactionsBottomSkip: 29px;
storiesReactionsAddedTop: 200px; storiesReactionsAddedTop: 200px;
storiesUnsupportedLabel: FlatLabel(defaultFlatLabel) {
textFg: mediaviewControlFg;
style: TextStyle(defaultTextStyle) {
font: font(15px semibold);
linkFont: font(15px semibold);
linkFontOver: font(15px semibold underline);
}
align: align(top);
}
storiesUnsupportedUpdate: themePreviewApplyButton;

View File

@ -3111,8 +3111,8 @@ void OverlayWidget::show(OpenRequest request) {
displayPhoto(photo); displayPhoto(photo);
preloadData(0); preloadData(0);
activateControls(); activateControls();
} else if (document) { } else if (story || document) {
setSession(&document->session()); setSession(document ? &document->session() : &story->session());
if (story) { if (story) {
setContext(StoriesContext{ setContext(StoriesContext{
@ -4093,6 +4093,8 @@ void OverlayWidget::storiesJumpTo(
displayPhoto(photo, anim::activation::background); displayPhoto(photo, anim::activation::background);
}, [&](not_null<DocumentData*> document) { }, [&](not_null<DocumentData*> document) {
displayDocument(document, anim::activation::background); displayDocument(document, anim::activation::background);
}, [&](v::null_t) {
displayDocument(nullptr, anim::activation::background);
}); });
} }
@ -4325,12 +4327,12 @@ void OverlayWidget::paint(not_null<Renderer*> renderer) {
paint(right, kRightSiblingTextureIndex); paint(right, kRightSiblingTextureIndex);
} }
} }
} else { } else if (_stories) {
if (_themePreviewShown) { // Unsupported story.
renderer->paintThemePreview(_themePreviewRect); } else if (_themePreviewShown) {
} else if (documentBubbleShown() && !_docRect.isEmpty()) { renderer->paintThemePreview(_themePreviewRect);
renderer->paintDocumentBubble(_docRect, _docIconRect); } else if (documentBubbleShown() && !_docRect.isEmpty()) {
} renderer->paintDocumentBubble(_docRect, _docIconRect);
} }
if (isSaveMsgShown()) { if (isSaveMsgShown()) {
renderer->paintSaveMsg(_saveMsg); renderer->paintSaveMsg(_saveMsg);