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#other" = "{count} 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_archive_button" = "Archive";

View File

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

View File

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

View File

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

View File

@ -55,7 +55,10 @@ struct StoriesIds {
};
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;
};
@ -86,6 +89,7 @@ public:
[[nodiscard]] FullStoryId fullId() const;
[[nodiscard]] TimeId date() const;
[[nodiscard]] TimeId expires() const;
[[nodiscard]] bool unsupported() const;
[[nodiscard]] bool expired(TimeId now = 0) const;
[[nodiscard]] const StoryMedia &media() const;
[[nodiscard]] PhotoData *photo() const;

View File

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

View File

@ -302,6 +302,12 @@ std::unique_ptr<BaseLayout> Provider::createLayout(
return std::make_unique<Photo>(delegate, item, photo, spoiler);
} else if (const auto file = getFile()) {
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;
}

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/power_save_blocker.h"
#include "base/qt_signal_producer.h"
#include "chat_helpers/compose/compose_show.h"
#include "core/update_checker.h"
#include "data/stickers/data_custom_emoji.h"
#include "data/data_changes.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_user.h"
#include "history/view/reactions/history_view_reactions_strip.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "media/stories/media_stories_caption_full_view.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/reaction_fly_animation.h"
#include "ui/layers/box_content.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/rp_widget.h"
#include "styles/style_media_view.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(controller)
, _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)
: _delegate(delegate)
, _wrap(_delegate->storiesWrap())
@ -584,13 +637,19 @@ void Controller::show(
const auto guard = gsl::finally([&] {
_paused = false;
_started = false;
if (story->photo()) {
if (!story->document()) {
_photoPlayback = std::make_unique<PhotoPlayback>(this);
} else {
_photoPlayback = nullptr;
}
});
if (!story->unsupported()) {
_unsupported = nullptr;
} else {
_unsupported = std::make_unique<Unsupported>(this);
}
if (_shown == storyId) {
return;
}

View File

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

View File

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

View File

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

View File

@ -782,3 +782,14 @@ storiesReactionsPan: EmojiPan(storiesEmojiPan) {
storiesReactionsWidth: 210px;
storiesReactionsBottomSkip: 29px;
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);
preloadData(0);
activateControls();
} else if (document) {
setSession(&document->session());
} else if (story || document) {
setSession(document ? &document->session() : &story->session());
if (story) {
setContext(StoriesContext{
@ -4093,6 +4093,8 @@ void OverlayWidget::storiesJumpTo(
displayPhoto(photo, anim::activation::background);
}, [&](not_null<DocumentData*> document) {
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);
}
}
} else {
if (_themePreviewShown) {
renderer->paintThemePreview(_themePreviewRect);
} else if (documentBubbleShown() && !_docRect.isEmpty()) {
renderer->paintDocumentBubble(_docRect, _docIconRect);
}
} else if (_stories) {
// Unsupported story.
} else if (_themePreviewShown) {
renderer->paintThemePreview(_themePreviewRect);
} else if (documentBubbleShown() && !_docRect.isEmpty()) {
renderer->paintDocumentBubble(_docRect, _docIconRect);
}
if (isSaveMsgShown()) {
renderer->paintSaveMsg(_saveMsg);