mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 23:53:58 +02:00
Support single download file thumbnail display.
This commit is contained in:
parent
c04a789d70
commit
bde79210ca
4 changed files with 202 additions and 67 deletions
|
@ -10,9 +10,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_session.h"
|
||||
#include "data/data_photo.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "base/random.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -846,26 +848,99 @@ rpl::producer<Ui::DownloadBarProgress> MakeDownloadBarProgress() {
|
|||
}
|
||||
|
||||
rpl::producer<Ui::DownloadBarContent> MakeDownloadBarContent() {
|
||||
return [](auto consumer) {
|
||||
auto lifetime = rpl::lifetime();
|
||||
|
||||
struct State {
|
||||
DocumentData *document = nullptr;
|
||||
std::shared_ptr<Data::DocumentMedia> media;
|
||||
rpl::lifetime downloadTaskLifetime;
|
||||
QImage thumbnail;
|
||||
Fn<void()> push;
|
||||
};
|
||||
|
||||
const auto state = lifetime.make_state<State>();
|
||||
auto &manager = Core::App().downloadManager();
|
||||
return rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(
|
||||
manager.loadingListChanges() | rpl::to_empty
|
||||
) | rpl::map([=, &manager] {
|
||||
auto result = Ui::DownloadBarContent();
|
||||
for (const auto id : manager.loadingList()) {
|
||||
if (result.singleName.text.isEmpty()) {
|
||||
const auto document = id->object.document;
|
||||
result.singleName = Ui::Text::FormatDownloadsName(document);
|
||||
result.singleThumbnail = QImage();
|
||||
|
||||
const auto resolveThumbnailRecursive = [=](auto &&self) -> bool {
|
||||
if (state->document
|
||||
&& (!state->document->hasThumbnail()
|
||||
|| state->document->thumbnailFailed())) {
|
||||
state->media = nullptr;
|
||||
}
|
||||
++result.count;
|
||||
if (id->done) {
|
||||
++result.done;
|
||||
if (!state->media) {
|
||||
state->downloadTaskLifetime.destroy();
|
||||
if (!state->thumbnail.isNull()) {
|
||||
return false;
|
||||
}
|
||||
state->thumbnail = QImage();
|
||||
return true;
|
||||
}
|
||||
return result;
|
||||
if (const auto image = state->media->thumbnail()) {
|
||||
state->thumbnail = image->original();
|
||||
state->downloadTaskLifetime.destroy();
|
||||
state->media = nullptr;
|
||||
return true;
|
||||
} else if (const auto embed = state->media->thumbnailInline()) {
|
||||
if (!state->thumbnail.isNull()) {
|
||||
return false;
|
||||
}
|
||||
state->thumbnail = Images::Prepare(embed->original(), 0, {
|
||||
.options = Images::Option::Blur,
|
||||
});
|
||||
}
|
||||
state->document->session().downloaderTaskFinished(
|
||||
) | rpl::filter([=] {
|
||||
return self(self);
|
||||
}) | rpl::start_with_next(
|
||||
state->push,
|
||||
state->downloadTaskLifetime);
|
||||
return !state->thumbnail.isNull();
|
||||
};
|
||||
const auto resolveThumbnail = [=] {
|
||||
return resolveThumbnailRecursive(resolveThumbnailRecursive);
|
||||
};
|
||||
|
||||
state->push = [=, &manager] {
|
||||
auto content = Ui::DownloadBarContent();
|
||||
auto single = (const Data::DownloadObject*) nullptr;
|
||||
for (const auto id : manager.loadingList()) {
|
||||
if (!single) {
|
||||
single = &id->object;
|
||||
}
|
||||
++content.count;
|
||||
if (id->done) {
|
||||
++content.done;
|
||||
}
|
||||
}
|
||||
if (content.count == 1) {
|
||||
const auto document = single->document;
|
||||
const auto thumbnailed = (single->item
|
||||
&& document->hasThumbnail())
|
||||
? document
|
||||
: nullptr;
|
||||
if (state->document != thumbnailed) {
|
||||
state->document = thumbnailed;
|
||||
state->media = thumbnailed
|
||||
? thumbnailed->createMediaView()
|
||||
: nullptr;
|
||||
state->media->thumbnailWanted(single->item->fullId());
|
||||
state->thumbnail = QImage();
|
||||
resolveThumbnail();
|
||||
}
|
||||
content.singleName = Ui::Text::FormatDownloadsName(
|
||||
document);
|
||||
content.singleThumbnail = state->thumbnail;
|
||||
}
|
||||
consumer.put_next(std::move(content));
|
||||
};
|
||||
|
||||
manager.loadingListChanges(
|
||||
) | rpl::start_with_next(state->push, lifetime);
|
||||
|
||||
state->push();
|
||||
return lifetime;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -1910,6 +1910,9 @@ void Widget::onDialogMoved(int movedFrom, int movedTo) {
|
|||
|
||||
Widget::~Widget() {
|
||||
cancelSearchRequest();
|
||||
|
||||
// Destructor may hide the bar and attempt to double-destroy it.
|
||||
base::take(_downloadBar);
|
||||
}
|
||||
|
||||
} // namespace Dialogs
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/text/format_values.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/image/image_prepare.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
|
||||
|
@ -18,6 +19,17 @@ namespace {
|
|||
|
||||
constexpr auto kFullArcLength = 360 * 16;
|
||||
|
||||
[[nodiscard]] QImage Make(const QImage &image, int size) {
|
||||
if (image.isNull()) {
|
||||
return QImage();
|
||||
}
|
||||
auto result = image.scaledToWidth(
|
||||
size * style::DevicePixelRatio(),
|
||||
Qt::SmoothTransformation);
|
||||
result.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
DownloadBar::DownloadBar(
|
||||
|
@ -71,6 +83,7 @@ void DownloadBar::show(DownloadBarContent &&content) {
|
|||
_finished ? 1. : 0.,
|
||||
st::widgetFadeDuration);
|
||||
}
|
||||
refreshThumbnail();
|
||||
_title.setMarkedText(
|
||||
st::defaultTextStyle,
|
||||
(content.count > 1
|
||||
|
@ -80,19 +93,47 @@ void DownloadBar::show(DownloadBarContent &&content) {
|
|||
refreshInfo(_progress.current());
|
||||
}
|
||||
|
||||
void DownloadBar::refreshThumbnail() {
|
||||
if (_content.singleThumbnail.isNull()) {
|
||||
_thumbnail = _thumbnailDone = QImage();
|
||||
_thumbnailCacheKey = 0;
|
||||
return;
|
||||
}
|
||||
const auto cacheKey = _content.singleThumbnail.cacheKey();
|
||||
if (_thumbnailCacheKey == cacheKey) {
|
||||
return;
|
||||
}
|
||||
_thumbnailCacheKey = cacheKey;
|
||||
_thumbnailLarge = _content.singleThumbnail;
|
||||
_thumbnailLarge.detach();
|
||||
const auto width = _thumbnailLarge.width();
|
||||
const auto height = _thumbnailLarge.height();
|
||||
if (width != height) {
|
||||
const auto size = std::min(width, height);
|
||||
_thumbnailLarge = _thumbnailLarge.copy(
|
||||
(width - size) / 2,
|
||||
(height - size) / 2,
|
||||
size,
|
||||
size);
|
||||
}
|
||||
const auto size = st::downloadLoadingSize;
|
||||
const auto added = 3 * st::downloadLoadingLine;
|
||||
const auto loadingsize = size;
|
||||
const auto donesize = size + (added - st::downloadLoadingLine) * 2;
|
||||
const auto make = [&](int size) {
|
||||
return Images::Circle(Make(_thumbnailLarge, size));
|
||||
};
|
||||
_thumbnail = make(loadingsize);
|
||||
_thumbnailDone = make(donesize);
|
||||
_thumbnailLarge = Images::Circle(std::move(_thumbnailLarge));
|
||||
}
|
||||
|
||||
void DownloadBar::refreshIcon() {
|
||||
_documentIconOriginal = st::downloadIconDocument.instance(
|
||||
_documentIconLarge = st::downloadIconDocument.instance(
|
||||
st::windowFgActive->c,
|
||||
style::kScaleMax / style::DevicePixelRatio());
|
||||
const auto make = [&](int size) {
|
||||
auto result = _documentIconOriginal.scaledToWidth(
|
||||
size * style::DevicePixelRatio(),
|
||||
Qt::SmoothTransformation);
|
||||
result.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
return result;
|
||||
};
|
||||
_documentIcon = make(st::downloadIconSize);
|
||||
_documentIconDone = make(st::downloadIconSizeDone);
|
||||
_documentIcon = Make(_documentIconLarge, st::downloadIconSize);
|
||||
_documentIconDone = Make(_documentIconLarge, st::downloadIconSizeDone);
|
||||
}
|
||||
|
||||
void DownloadBar::refreshInfo(const DownloadBarProgress &progress) {
|
||||
|
@ -156,17 +197,10 @@ void DownloadBar::paint(Painter &p, QRect clip) {
|
|||
size + added * 2,
|
||||
size + added * 2);
|
||||
if (full.intersects(clip)) {
|
||||
const auto done = (finished == 1.);
|
||||
const auto loading = _radial.computeState();
|
||||
{
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::windowBgActive);
|
||||
const auto shift = st::downloadLoadingLine
|
||||
+ (1. - finished) * (added - st::downloadLoadingLine);
|
||||
p.drawEllipse(QRectF(full).marginsRemoved(
|
||||
{ shift, shift, shift, shift }));
|
||||
|
||||
if (loading.shown > 0) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setOpacity(loading.shown);
|
||||
auto pen = st::windowBgActive->p;
|
||||
pen.setWidth(st::downloadLoadingLine);
|
||||
|
@ -181,16 +215,25 @@ void DownloadBar::paint(Painter &p, QRect clip) {
|
|||
}
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
}
|
||||
const auto shift = st::downloadLoadingLine
|
||||
+ (1. - finished) * (added - st::downloadLoadingLine);
|
||||
const auto ellipse = QRectF(full).marginsRemoved(
|
||||
{ shift, shift, shift, shift });
|
||||
if (_thumbnail.isNull()) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::windowBgActive);
|
||||
p.drawEllipse(ellipse);
|
||||
const auto sizeLoading = st::downloadIconSize;
|
||||
if (finished == 0. || finished == 1.) {
|
||||
const auto size = (finished == 1.)
|
||||
if (finished == 0. || done) {
|
||||
const auto size = done
|
||||
? st::downloadIconSizeDone
|
||||
: sizeLoading;
|
||||
const auto image = done ? _documentIconDone : _documentIcon;
|
||||
p.drawImage(
|
||||
full.x() + (full.width() - size) / 2,
|
||||
full.y() + (full.height() - size) / 2,
|
||||
(finished == 1.) ? _documentIconDone : _documentIcon);
|
||||
image);
|
||||
} else {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
const auto size = sizeLoading
|
||||
|
@ -201,7 +244,16 @@ void DownloadBar::paint(Painter &p, QRect clip) {
|
|||
full.y() + (full.height() - size) / 2.,
|
||||
size,
|
||||
size),
|
||||
_documentIconOriginal);
|
||||
_documentIconLarge);
|
||||
}
|
||||
} else if (finished == 0. || done) {
|
||||
p.drawImage(
|
||||
base::SafeRound(ellipse.x()),
|
||||
base::SafeRound(ellipse.y()),
|
||||
done ? _thumbnailDone : _thumbnail);
|
||||
} else {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.drawImage(ellipse, _thumbnailLarge);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
private:
|
||||
void paint(Painter &p, QRect clip);
|
||||
void refreshIcon();
|
||||
void refreshThumbnail();
|
||||
void refreshInfo(const DownloadBarProgress &progress);
|
||||
void radialAnimationCallback(crl::time now);
|
||||
[[nodiscard]] float64 computeProgress() const;
|
||||
|
@ -60,9 +61,13 @@ private:
|
|||
rpl::variable<DownloadBarProgress> _progress;
|
||||
Ui::Animations::Simple _finishedAnimation;
|
||||
bool _finished = false;
|
||||
QImage _documentIconOriginal;
|
||||
QImage _documentIconLarge;
|
||||
QImage _documentIcon;
|
||||
QImage _documentIconDone;
|
||||
qint64 _thumbnailCacheKey = 0;
|
||||
QImage _thumbnailLarge;
|
||||
QImage _thumbnail;
|
||||
QImage _thumbnailDone;
|
||||
Text::String _title;
|
||||
Text::String _info;
|
||||
RadialAnimation _radial;
|
||||
|
|
Loading…
Add table
Reference in a new issue