Added ability to show song cover in HistoryView and Overview::Layout.

This commit is contained in:
23rd 2021-01-09 22:52:55 +03:00
parent a483eb98a1
commit 8fffe7d128
7 changed files with 93 additions and 18 deletions

View file

@ -1488,6 +1488,10 @@ bool DocumentData::isSong() const {
return (type == SongDocument); return (type == SongDocument);
} }
bool DocumentData::isSongWithCover() const {
return isSong() && hasThumbnail();
}
bool DocumentData::isAudioFile() const { bool DocumentData::isAudioFile() const {
if (isVoiceMessage()) { if (isVoiceMessage()) {
return false; return false;

View file

@ -139,6 +139,7 @@ public:
[[nodiscard]] bool isVoiceMessage() const; [[nodiscard]] bool isVoiceMessage() const;
[[nodiscard]] bool isVideoMessage() const; [[nodiscard]] bool isVideoMessage() const;
[[nodiscard]] bool isSong() const; [[nodiscard]] bool isSong() const;
[[nodiscard]] bool isSongWithCover() const;
[[nodiscard]] bool isAudioFile() const; [[nodiscard]] bool isAudioFile() const;
[[nodiscard]] bool isVideoFile() const; [[nodiscard]] bool isVideoFile() const;
[[nodiscard]] bool isAnimation() const; [[nodiscard]] bool isAnimation() const;

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h" #include "ui/image/image.h"
#include "ui/text/format_values.h" #include "ui/text/format_values.h"
#include "ui/cached_round_corners.h" #include "ui/cached_round_corners.h"
#include "ui/ui_utility.h"
#include "layout.h" // FullSelection #include "layout.h" // FullSelection
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_document.h" #include "data/data_document.h"
@ -442,14 +443,14 @@ void Document::draw(
} }
} else { } else {
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
if (selected) {
p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected);
} else {
p.setBrush(outbg ? st::msgFileOutBg : st::msgFileInBg);
}
{ const auto coverDrawn = _data->isSongWithCover()
&& DrawThumbnailAsSongCover(p, _dataMedia, inner, selected);
if (!coverDrawn) {
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
p.setBrush(selected
? (outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected)
: (outbg ? st::msgFileOutBg : st::msgFileInBg));
p.drawEllipse(inner); p.drawEllipse(inner);
} }
@ -581,7 +582,7 @@ void Document::ensureDataMediaCreated() const {
return; return;
} }
_dataMedia = _data->createMediaView(); _dataMedia = _data->createMediaView();
if (Get<HistoryDocumentThumbed>()) { if (Get<HistoryDocumentThumbed>() || _data->isSongWithCover()) {
_dataMedia->thumbnailWanted(_realParent->fullId()); _dataMedia->thumbnailWanted(_realParent->fullId());
} }
history()->owner().registerHeavyViewPart(_parent); history()->owner().registerHeavyViewPart(_parent);
@ -1072,4 +1073,49 @@ Ui::Text::String Document::createCaption() {
timestampLinkBase); timestampLinkBase);
} }
bool DrawThumbnailAsSongCover(
Painter &p,
const std::shared_ptr<Data::DocumentMedia> &dataMedia,
const QRect &rect,
const bool selected) {
if (!dataMedia) {
return false;
}
QPixmap cover;
const auto ow = rect.width();
const auto oh = rect.height();
const auto r = ImageRoundRadius::Ellipse;
const auto c = RectPart::AllCorners;
const auto color = &st::songCoverOverlayFg;
const auto aspectRatio = Qt::KeepAspectRatioByExpanding;
const auto scaled = [&](not_null<Image*> image) -> std::pair<int, int> {
const auto size = image->size().scaled(ow, oh, aspectRatio);
return { size.width(), size.height() };
};
if (const auto normal = dataMedia->thumbnail()) {
const auto &[w, h] = scaled(normal);
cover = normal->pixSingle(w, h, ow, oh, r, c, color);
} else if (const auto blurred = dataMedia->thumbnailInline()) {
const auto &[w, h] = scaled(blurred);
cover = blurred->pixBlurredSingle(w, h, ow, oh, r, c, color);
} else {
return false;
}
if (selected) {
auto selectedCover = Images::prepareColored(
p.textPalette().selectOverlay,
cover.toImage());
cover = QPixmap::fromImage(
std::move(selectedCover),
Qt::ColorOnly);
}
p.drawPixmap(rect.topLeft(), cover);
return true;
}
} // namespace HistoryView } // namespace HistoryView

View file

@ -143,4 +143,10 @@ private:
}; };
bool DrawThumbnailAsSongCover(
Painter &p,
const std::shared_ptr<Data::DocumentMedia> &dataMedia,
const QRect &rect,
const bool selected = false);
} // namespace HistoryView } // namespace HistoryView

View file

@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item.h" #include "history/history_item.h"
#include "history/history_item_components.h" #include "history/history_item_components.h"
#include "history/view/history_view_cursor_state.h" #include "history/view/history_view_cursor_state.h"
#include "history/view/media/history_view_document.h" // DrawThumbnailAsSongCover
#include "base/unixtime.h" #include "base/unixtime.h"
#include "base/qt_adapters.h" #include "base/qt_adapters.h"
#include "ui/effects/round_checkbox.h" #include "ui/effects/round_checkbox.h"
@ -1008,21 +1009,33 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con
auto inner = style::rtlrect(_st.songPadding.left(), _st.songPadding.top(), _st.songThumbSize, _st.songThumbSize, _width); auto inner = style::rtlrect(_st.songPadding.left(), _st.songPadding.top(), _st.songThumbSize, _st.songThumbSize, _width);
if (clip.intersects(inner)) { if (clip.intersects(inner)) {
const auto isLoading = (!cornerDownload
&& (_data->loading() || _data->uploading()));
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
using namespace HistoryView;
const auto coverDrawn = _data->isSongWithCover()
&& DrawThumbnailAsSongCover(p, _dataMedia, inner, selected);
if (!coverDrawn) {
if (selected) { if (selected) {
p.setBrush(st::msgFileInBgSelected); p.setBrush(st::msgFileInBgSelected);
} else { } else {
auto over = ClickHandler::showAsActive((!cornerDownload && (_data->loading() || _data->uploading())) ? _cancell : (loaded || _dataMedia->canBePlayed()) ? _openl : _savel); const auto over = ClickHandler::showAsActive(isLoading
p.setBrush(anim::brush(_st.songIconBg, _st.songOverBg, _a_iconOver.value(over ? 1. : 0.))); ? _cancell
: (loaded || _dataMedia->canBePlayed())
? _openl
: _savel);
p.setBrush(anim::brush(
_st.songIconBg,
_st.songOverBg,
_a_iconOver.value(over ? 1. : 0.)));
} }
{
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
p.drawEllipse(inner); p.drawEllipse(inner);
} }
const auto icon = [&] { const auto icon = [&] {
if (!cornerDownload && (_data->loading() || _data->uploading())) { if (isLoading) {
return &(selected ? _st.songCancelSelected : _st.songCancel); return &(selected ? _st.songCancelSelected : _st.songCancel);
} else if (showPause) { } else if (showPause) {
return &(selected ? _st.songPauseSelected : _st.songPause); return &(selected ? _st.songPauseSelected : _st.songPause);

View file

@ -343,7 +343,8 @@ const QPixmap &Image::pixBlurredSingle(
int outerw, int outerw,
int outerh, int outerh,
ImageRoundRadius radius, ImageRoundRadius radius,
RectParts corners) const { RectParts corners,
const style::color *colored) const {
if (w <= 0 || !width() || !height()) { if (w <= 0 || !width() || !height()) {
w = width() * cIntRetinaFactor(); w = width() * cIntRetinaFactor();
} else { } else {
@ -365,11 +366,14 @@ const QPixmap &Image::pixBlurredSingle(
} else if (radius == ImageRoundRadius::Ellipse) { } else if (radius == ImageRoundRadius::Ellipse) {
options |= Option::Circled | cornerOptions(corners); options |= Option::Circled | cornerOptions(corners);
} }
if (colored) {
options |= Option::Colored;
}
auto k = SinglePixKey(options); auto k = SinglePixKey(options);
auto i = _cache.find(k); auto i = _cache.find(k);
if (i == _cache.cend() || i->second.width() != (outerw * cIntRetinaFactor()) || i->second.height() != (outerh * cIntRetinaFactor())) { if (i == _cache.cend() || i->second.width() != (outerw * cIntRetinaFactor()) || i->second.height() != (outerh * cIntRetinaFactor())) {
auto p = pixNoCache(w, h, options, outerw, outerh); auto p = pixNoCache(w, h, options, outerw, outerh, colored);
p.setDevicePixelRatio(cRetinaFactor()); p.setDevicePixelRatio(cRetinaFactor());
i = _cache.emplace_or_assign(k, p).first; i = _cache.emplace_or_assign(k, p).first;
} }

View file

@ -70,7 +70,8 @@ public:
int outerw, int outerw,
int outerh, int outerh,
ImageRoundRadius radius, ImageRoundRadius radius,
RectParts corners = RectPart::AllCorners) const; RectParts corners = RectPart::AllCorners,
const style::color *colored = nullptr) const;
[[nodiscard]] const QPixmap &pixCircled(int w = 0, int h = 0) const; [[nodiscard]] const QPixmap &pixCircled(int w = 0, int h = 0) const;
[[nodiscard]] const QPixmap &pixBlurredCircled(int w = 0, int h = 0) const; [[nodiscard]] const QPixmap &pixBlurredCircled(int w = 0, int h = 0) const;
[[nodiscard]] QPixmap pixNoCache( [[nodiscard]] QPixmap pixNoCache(