Show unsupported stories with an Update button.
This commit is contained in:
parent
ad5b96b049
commit
a2bf0fc511
|
@ -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";
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user