Load and show image previews in pinned bar.

This commit is contained in:
John Preston 2020-10-12 16:24:45 +03:00
parent 9b4b15ee6d
commit 37fb94cbfb
9 changed files with 136 additions and 15 deletions

View file

@ -1266,6 +1266,15 @@ Image *DocumentData::getReplyPreview(Data::FileOrigin origin) {
return _replyPreview->image(origin);
}
bool DocumentData::replyPreviewLoaded() const {
if (!hasThumbnail()) {
return true;
} else if (!_replyPreview) {
return false;
}
return _replyPreview->loaded();
}
StickerData *DocumentData::sticker() const {
return (type == StickerDocument)
? static_cast<StickerData*>(_additional.get())

View file

@ -126,6 +126,7 @@ public:
[[nodiscard]] bool saveToCache() const;
[[nodiscard]] Image *getReplyPreview(Data::FileOrigin origin);
[[nodiscard]] bool replyPreviewLoaded() const;
[[nodiscard]] StickerData *sticker() const;
[[nodiscard]] Data::FileOrigin stickerSetOrigin() const;

View file

@ -209,6 +209,10 @@ Image *Media::replyPreview() const {
return nullptr;
}
bool Media::replyPreviewLoaded() const {
return true;
}
bool Media::allowsForward() const {
return true;
}
@ -312,6 +316,10 @@ Image *MediaPhoto::replyPreview() const {
return _photo->getReplyPreview(parent()->fullId());
}
bool MediaPhoto::replyPreviewLoaded() const {
return _photo->replyPreviewLoaded();
}
QString MediaPhoto::notificationText() const {
return WithCaptionNotificationText(
tr::lng_in_dlg_photo(tr::now),
@ -476,6 +484,10 @@ Image *MediaFile::replyPreview() const {
return _document->getReplyPreview(parent()->fullId());
}
bool MediaFile::replyPreviewLoaded() const {
return _document->replyPreviewLoaded();
}
QString MediaFile::chatListText() const {
if (const auto sticker = _document->sticker()) {
return Media::chatListText();
@ -987,6 +999,15 @@ Image *MediaWebPage::replyPreview() const {
return nullptr;
}
bool MediaWebPage::replyPreviewLoaded() const {
if (const auto document = MediaWebPage::document()) {
return document->replyPreviewLoaded();
} else if (const auto photo = MediaWebPage::photo()) {
return photo->replyPreviewLoaded();
}
return true;
}
QString MediaWebPage::chatListText() const {
return notificationText();
}
@ -1051,6 +1072,15 @@ Image *MediaGame::replyPreview() const {
return nullptr;
}
bool MediaGame::replyPreviewLoaded() const {
if (const auto document = _game->document) {
return document->replyPreviewLoaded();
} else if (const auto photo = _game->photo) {
return photo->replyPreviewLoaded();
}
return true;
}
QString MediaGame::notificationText() const {
// Add a game controller emoji before game title.
auto result = QString();
@ -1153,6 +1183,13 @@ Image *MediaInvoice::replyPreview() const {
return nullptr;
}
bool MediaInvoice::replyPreviewLoaded() const {
if (const auto photo = _invoice.photo) {
return photo->replyPreviewLoaded();
}
return true;
}
QString MediaInvoice::notificationText() const {
return _invoice.title;
}

View file

@ -88,6 +88,7 @@ public:
virtual bool canBeGrouped() const;
virtual bool hasReplyPreview() const;
virtual Image *replyPreview() const;
virtual bool replyPreviewLoaded() const;
// Returns text with link-start and link-end commands for service-color highlighting.
// Example: "[link1-start]You:[link1-end] [link1-start]Photo,[link1-end] caption text"
virtual QString chatListText() const;
@ -143,6 +144,7 @@ public:
bool canBeGrouped() const override;
bool hasReplyPreview() const override;
Image *replyPreview() const override;
bool replyPreviewLoaded() const override;
QString chatListText() const override;
QString notificationText() const override;
QString pinnedTextSubstring() const override;
@ -180,6 +182,7 @@ public:
bool canBeGrouped() const override;
bool hasReplyPreview() const override;
Image *replyPreview() const override;
bool replyPreviewLoaded() const override;
QString chatListText() const override;
QString notificationText() const override;
QString pinnedTextSubstring() const override;
@ -311,6 +314,7 @@ public:
bool hasReplyPreview() const override;
Image *replyPreview() const override;
bool replyPreviewLoaded() const override;
QString chatListText() const override;
QString notificationText() const override;
QString pinnedTextSubstring() const override;
@ -341,6 +345,7 @@ public:
bool hasReplyPreview() const override;
Image *replyPreview() const override;
bool replyPreviewLoaded() const override;
QString notificationText() const override;
QString pinnedTextSubstring() const override;
TextForMimeData clipboardText() const override;
@ -377,6 +382,7 @@ public:
bool hasReplyPreview() const override;
Image *replyPreview() const override;
bool replyPreviewLoaded() const override;
QString notificationText() const override;
QString pinnedTextSubstring() const override;
TextForMimeData clipboardText() const override;

View file

@ -205,6 +205,13 @@ Image *PhotoData::getReplyPreview(Data::FileOrigin origin) {
return _replyPreview->image(origin);
}
bool PhotoData::replyPreviewLoaded() const {
if (!_replyPreview) {
return false;
}
return _replyPreview->loaded();
}
void PhotoData::setRemoteLocation(
int32 dc,
uint64 access,

View file

@ -65,6 +65,7 @@ public:
[[nodiscard]] bool waitingForAlbum() const;
[[nodiscard]] Image *getReplyPreview(Data::FileOrigin origin);
[[nodiscard]] bool replyPreviewLoaded() const;
void setRemoteLocation(
int32 dc,

View file

@ -107,4 +107,8 @@ Image *ReplyPreview::image(Data::FileOrigin origin) {
return _image.get();
}
bool ReplyPreview::loaded() const {
return _checked;
}
} // namespace Data

View file

@ -24,6 +24,7 @@ public:
~ReplyPreview();
[[nodiscard]] Image *image(Data::FileOrigin origin);
[[nodiscard]] bool loaded() const;
private:
void prepare(not_null<Image*> image, Images::Options options);

View file

@ -23,29 +23,84 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace HistoryView {
namespace {
[[nodiscard]] Ui::MessageBarContent ContentWithoutPreview(
not_null<HistoryItem*> item,
PinnedIdType type) {
const auto media = item->media();
const auto poll = media ? media->poll() : nullptr;
return Ui::MessageBarContent{
.id = item->id,
.title = ((type == PinnedIdType::First)
? tr::lng_pinned_previous(tr::now) // #TODO pinned first?
: (type == PinnedIdType::Middle)
? tr::lng_pinned_previous(tr::now)
: !poll
? tr::lng_pinned_message(tr::now)
: poll->quiz()
? tr::lng_pinned_quiz(tr::now)
: tr::lng_pinned_poll(tr::now)),
.text = item->inReplyText(),
};
}
[[nodiscard]] Ui::MessageBarContent ContentWithPreview(
not_null<HistoryItem*> item,
PinnedIdType type,
Image *preview) {
auto result = ContentWithoutPreview(item, type);
if (!preview) {
static const auto kEmpty = [&] {
const auto size = st::historyReplyHeight * cIntRetinaFactor();
auto result = QImage(
QSize(size, size),
QImage::Format_ARGB32_Premultiplied);
result.fill(Qt::transparent);
result.setDevicePixelRatio(cRetinaFactor());
return result;
}();
result.preview = kEmpty;
} else {
result.preview = preview->original();
}
return result;
}
[[nodiscard]] rpl::producer<Ui::MessageBarContent> ContentByItem(
not_null<HistoryItem*> item,
PinnedIdType type) {
return item->history()->session().changes().messageFlagsValue(
item,
Data::MessageUpdate::Flag::Edited
) | rpl::map([=] {
) | rpl::map([=]() -> rpl::producer<Ui::MessageBarContent> {
const auto media = item->media();
const auto poll = media ? media->poll() : nullptr;
return Ui::MessageBarContent{
.id = item->id,
.title = ((type == PinnedIdType::First)
? tr::lng_pinned_previous(tr::now) // #TODO pinned first?
: (type == PinnedIdType::Middle)
? tr::lng_pinned_previous(tr::now)
: !poll
? tr::lng_pinned_message(tr::now)
: poll->quiz()
? tr::lng_pinned_quiz(tr::now)
: tr::lng_pinned_poll(tr::now)),
.text = item->inReplyText(),
if (!media || !media->hasReplyPreview()) {
return rpl::single(ContentWithoutPreview(item, type));
}
constexpr auto kFullLoaded = 2;
constexpr auto kSomeLoaded = 1;
constexpr auto kNotLoaded = 0;
const auto loadedLevel = [=] {
const auto preview = media->replyPreview();
return media->replyPreviewLoaded()
? kFullLoaded
: preview
? kSomeLoaded
: kNotLoaded;
};
});
return rpl::single(
loadedLevel()
) | rpl::then(
item->history()->session().downloaderTaskFinished(
) | rpl::map(loadedLevel)
) | rpl::distinct_until_changed(
) | rpl::take_while([=](int loadLevel) {
return loadLevel < kFullLoaded;
}) | rpl::then(
rpl::single(kFullLoaded)
) | rpl::map([=] {
return ContentWithPreview(item, type, media->replyPreview());
});
}) | rpl::flatten_latest();
}
[[nodiscard]] rpl::producer<Ui::MessageBarContent> ContentByItemId(