mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/telegramdesktop/tdesktop
synced 2026-09-20 08:03:45 +08:00
Replaced preview image of message bar with dynamic image.
This commit is contained in:
@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_poll.h"
|
||||
#include "data/data_web_page.h"
|
||||
#include "history/view/history_view_pinned_tracker.h"
|
||||
#include "history/view/history_view_reply.h"
|
||||
#include "history/history_item.h"
|
||||
#include "history/history_item_components.h"
|
||||
#include "history/history.h"
|
||||
@@ -22,6 +23,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "core/ui_integration.h"
|
||||
#include "base/weak_ptr.h"
|
||||
#include "apiwrap.h"
|
||||
#include "ui/dynamic_image.h"
|
||||
#include "ui/effects/spoiler_mess.h"
|
||||
#include "ui/power_saving.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/basic_click_handlers.h"
|
||||
@@ -42,31 +46,79 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
class PreviewImage final : public Ui::DynamicImage {
|
||||
public:
|
||||
PreviewImage(QImage source, bool spoiler);
|
||||
|
||||
std::shared_ptr<Ui::DynamicImage> clone() override;
|
||||
QImage image(int size) override;
|
||||
void subscribeToUpdates(Fn<void()> callback) override;
|
||||
|
||||
private:
|
||||
QImage _source;
|
||||
QPixmap _pixmap;
|
||||
QImage _frame;
|
||||
QImage _spoilerCache;
|
||||
std::unique_ptr<Ui::SpoilerAnimation> _spoiler;
|
||||
bool _spoilered = false;
|
||||
|
||||
};
|
||||
|
||||
PreviewImage::PreviewImage(QImage source, bool spoiler)
|
||||
: _source(std::move(source))
|
||||
, _pixmap(QPixmap::fromImage(_source, Qt::ColorOnly))
|
||||
, _spoilered(spoiler) {
|
||||
}
|
||||
|
||||
std::shared_ptr<Ui::DynamicImage> PreviewImage::clone() {
|
||||
return std::make_shared<PreviewImage>(_source, _spoilered);
|
||||
}
|
||||
|
||||
void PreviewImage::subscribeToUpdates(Fn<void()> callback) {
|
||||
if (!callback || !_spoilered) {
|
||||
_spoiler = nullptr;
|
||||
} else {
|
||||
_spoiler = std::make_unique<Ui::SpoilerAnimation>(
|
||||
std::move(callback));
|
||||
}
|
||||
}
|
||||
|
||||
QImage PreviewImage::image(int size) {
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
const auto full = QSize(size, size) * ratio;
|
||||
const auto to = QRect(0, 0, size, size);
|
||||
if (_frame.size() != full) {
|
||||
_frame = QImage(full, QImage::Format_ARGB32_Premultiplied);
|
||||
_frame.setDevicePixelRatio(ratio);
|
||||
}
|
||||
_frame.fill(Qt::transparent);
|
||||
auto p = QPainter(&_frame);
|
||||
p.drawPixmap(to, _pixmap);
|
||||
if (_spoiler) {
|
||||
FillPreviewSpoiler(
|
||||
p,
|
||||
to,
|
||||
_pixmap,
|
||||
Ui::DefaultImageSpoiler().frame(_spoiler->index(
|
||||
crl::now(),
|
||||
On(PowerSaving::kChatSpoiler))),
|
||||
_spoilerCache);
|
||||
}
|
||||
p.end();
|
||||
return _frame;
|
||||
}
|
||||
|
||||
[[nodiscard]] Ui::MessageBarContent ContentWithPreview(
|
||||
not_null<HistoryItem*> item,
|
||||
Image *preview,
|
||||
bool spoiler,
|
||||
Fn<void()> repaint) {
|
||||
auto result = ContentWithoutPreview(item, repaint);
|
||||
if (!preview) {
|
||||
static const auto kEmpty = [&] {
|
||||
const auto size = st::historyReplyHeight
|
||||
* style::DevicePixelRatio();
|
||||
auto result = QImage(
|
||||
QSize(size, size),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
result.fill(Qt::transparent);
|
||||
result.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
return result;
|
||||
}();
|
||||
result.preview = kEmpty;
|
||||
result.spoilerRepaint = nullptr;
|
||||
} else {
|
||||
result.preview = Images::Round(
|
||||
preview->original(),
|
||||
ImageRoundRadius::Small);
|
||||
result.spoilerRepaint = spoiler ? repaint : nullptr;
|
||||
}
|
||||
result.preview = std::make_shared<PreviewImage>(
|
||||
(preview
|
||||
? Images::Round(preview->original(), ImageRoundRadius::Small)
|
||||
: QImage()),
|
||||
preview && spoiler);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "ui/chat/message_bar.h"
|
||||
|
||||
#include "ui/effects/spoiler_mess.h"
|
||||
#include "ui/dynamic_image.h"
|
||||
#include "ui/image/image_prepare.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/power_saving.h"
|
||||
@@ -123,13 +123,13 @@ void MessageBar::tweenTo(MessageBarContent &&content) {
|
||||
updateFromContent(std::move(content));
|
||||
return;
|
||||
}
|
||||
const auto hasImageChanged = (_content.preview.isNull()
|
||||
!= content.preview.isNull());
|
||||
const auto hasImageChanged = ((_content.preview != nullptr)
|
||||
!= (content.preview != nullptr));
|
||||
const auto bodyChanged = (_content.index != content.index
|
||||
|| _content.count != content.count
|
||||
|| _content.title != content.title
|
||||
|| _content.text != content.text
|
||||
|| _content.preview.constBits() != content.preview.constBits());
|
||||
|| _content.preview != content.preview);
|
||||
const auto barCountChanged = (_content.count != content.count);
|
||||
const auto barFrom = _content.index;
|
||||
const auto barTo = content.index;
|
||||
@@ -144,7 +144,6 @@ void MessageBar::tweenTo(MessageBarContent &&content) {
|
||||
? RectPart::Bottom
|
||||
: RectPart::None;
|
||||
animation.imageFrom = grabImagePart();
|
||||
animation.spoilerFrom = std::move(_spoiler);
|
||||
animation.bodyOrTextFrom = grabBodyOrTextPart(animation.bodyAnimation);
|
||||
const auto sameLength = SameFirstPartLength(
|
||||
_content.title,
|
||||
@@ -205,6 +204,9 @@ void MessageBar::tweenTo(MessageBarContent &&content) {
|
||||
}
|
||||
|
||||
void MessageBar::updateFromContent(MessageBarContent &&content) {
|
||||
if (_content.preview && _content.preview != content.preview) {
|
||||
_content.preview->subscribeToUpdates(nullptr);
|
||||
}
|
||||
_content = std::move(content);
|
||||
_title.setText(_st.title, _content.title);
|
||||
_text.setMarkedText(
|
||||
@@ -212,13 +214,21 @@ void MessageBar::updateFromContent(MessageBarContent &&content) {
|
||||
_content.text,
|
||||
Ui::DialogTextOptions(),
|
||||
_content.context);
|
||||
_image = prepareImage(_content.preview);
|
||||
if (!_content.spoilerRepaint) {
|
||||
_spoiler = nullptr;
|
||||
} else if (!_spoiler) {
|
||||
_spoiler = std::make_unique<SpoilerAnimation>(
|
||||
_content.spoilerRepaint);
|
||||
if (_content.preview) {
|
||||
_content.preview->subscribeToUpdates(crl::guard(&_widget, [=] {
|
||||
refreshImage();
|
||||
_widget.update();
|
||||
}));
|
||||
}
|
||||
refreshImage();
|
||||
}
|
||||
|
||||
void MessageBar::refreshImage() {
|
||||
_image = _content.preview
|
||||
? QPixmap::fromImage(
|
||||
_content.preview->image(st::historyReplyPreview),
|
||||
Qt::ColorOnly)
|
||||
: QPixmap();
|
||||
}
|
||||
|
||||
QRect MessageBar::imageRect() const {
|
||||
@@ -266,21 +276,10 @@ auto MessageBar::makeGrabGuard() {
|
||||
auto imageShown = _animation
|
||||
? std::move(_animation->imageShown)
|
||||
: Ui::Animations::Simple();
|
||||
auto spoiler = std::move(_spoiler);
|
||||
auto fromSpoiler = _animation
|
||||
? std::move(_animation->spoilerFrom)
|
||||
: nullptr;
|
||||
return gsl::finally([
|
||||
&,
|
||||
shown = std::move(imageShown),
|
||||
spoiler = std::move(spoiler),
|
||||
fromSpoiler = std::move(fromSpoiler)
|
||||
]() mutable {
|
||||
return gsl::finally([&, shown = std::move(imageShown)]() mutable {
|
||||
if (_animation) {
|
||||
_animation->imageShown = std::move(shown);
|
||||
_animation->spoilerFrom = std::move(fromSpoiler);
|
||||
}
|
||||
_spoiler = std::move(spoiler);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -336,10 +335,6 @@ void MessageBar::finishAnimating() {
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap MessageBar::prepareImage(const QImage &preview) {
|
||||
return QPixmap::fromImage(preview, Qt::ColorOnly);
|
||||
}
|
||||
|
||||
void MessageBar::paint(Painter &p) {
|
||||
const auto progress = _animation ? _animation->bodyMoved.value(1.) : 1.;
|
||||
const auto imageFinal = _image.isNull() ? 0. : 1.;
|
||||
@@ -385,13 +380,7 @@ void MessageBar::paint(Painter &p) {
|
||||
|
||||
if (!_animation) {
|
||||
if (!_image.isNull()) {
|
||||
paintImageWithSpoiler(
|
||||
p,
|
||||
image,
|
||||
_image,
|
||||
_spoiler.get(),
|
||||
now,
|
||||
pausedSpoiler);
|
||||
p.drawPixmap(image, _image);
|
||||
}
|
||||
} else if (!_animation->imageTo.isNull()
|
||||
|| (!_animation->imageFrom.isNull()
|
||||
@@ -409,30 +398,12 @@ void MessageBar::paint(Painter &p) {
|
||||
}();
|
||||
if (_animation->bodyMoved.animating()) {
|
||||
p.setOpacity(1. - progress);
|
||||
paintImageWithSpoiler(
|
||||
p,
|
||||
rect.translated(0, shiftFrom),
|
||||
_animation->imageFrom,
|
||||
_animation->spoilerFrom.get(),
|
||||
now,
|
||||
pausedSpoiler);
|
||||
p.drawPixmap(rect.translated(0, shiftFrom), _animation->imageFrom);
|
||||
p.setOpacity(progress);
|
||||
paintImageWithSpoiler(
|
||||
p,
|
||||
rect.translated(0, shiftTo),
|
||||
_animation->imageTo,
|
||||
_spoiler.get(),
|
||||
now,
|
||||
pausedSpoiler);
|
||||
p.drawPixmap(rect.translated(0, shiftTo), _animation->imageTo);
|
||||
p.setOpacity(1.);
|
||||
} else {
|
||||
paintImageWithSpoiler(
|
||||
p,
|
||||
rect,
|
||||
_image,
|
||||
_spoiler.get(),
|
||||
now,
|
||||
pausedSpoiler);
|
||||
p.drawPixmap(rect, _image);
|
||||
}
|
||||
}
|
||||
if (!_animation || _animation->bodyAnimation == BodyAnimation::None) {
|
||||
@@ -558,21 +529,6 @@ void MessageBar::ensureGradientsCreated(int size) {
|
||||
_topBarGradient = Images::PixmapFast(std::move(top));
|
||||
}
|
||||
|
||||
void MessageBar::paintImageWithSpoiler(
|
||||
QPainter &p,
|
||||
QRect rect,
|
||||
const QPixmap &image,
|
||||
SpoilerAnimation *spoiler,
|
||||
crl::time now,
|
||||
bool paused) const {
|
||||
p.drawPixmap(rect, image);
|
||||
if (spoiler) {
|
||||
const auto frame = DefaultImageSpoiler().frame(
|
||||
spoiler->index(now, paused));
|
||||
FillSpoilerRect(p, rect, frame);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageBar::paintLeftBar(Painter &p) {
|
||||
const auto state = countBarState();
|
||||
const auto gradientSize = int(std::ceil(state.size * 2.5));
|
||||
|
||||
@@ -19,7 +19,7 @@ struct MessageBar;
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class SpoilerAnimation;
|
||||
class DynamicImage;
|
||||
|
||||
struct MessageBarContent {
|
||||
int index = 0;
|
||||
@@ -27,8 +27,7 @@ struct MessageBarContent {
|
||||
QString title;
|
||||
TextWithEntities text;
|
||||
Text::MarkedContext context;
|
||||
QImage preview;
|
||||
Fn<void()> spoilerRepaint;
|
||||
std::shared_ptr<DynamicImage> preview;
|
||||
style::margins margins;
|
||||
};
|
||||
|
||||
@@ -67,7 +66,6 @@ private:
|
||||
QPixmap titleTo;
|
||||
QPixmap imageFrom;
|
||||
QPixmap imageTo;
|
||||
std::unique_ptr<SpoilerAnimation> spoilerFrom;
|
||||
BodyAnimation bodyAnimation = BodyAnimation::None;
|
||||
RectPart movingTo = RectPart::None;
|
||||
};
|
||||
@@ -78,11 +76,11 @@ private:
|
||||
float64 offset = 0.;
|
||||
};
|
||||
void setup();
|
||||
void refreshImage();
|
||||
void paint(Painter &p);
|
||||
void paintLeftBar(Painter &p);
|
||||
void tweenTo(MessageBarContent &&content);
|
||||
void updateFromContent(MessageBarContent &&content);
|
||||
[[nodiscard]] QPixmap prepareImage(const QImage &preview);
|
||||
|
||||
[[nodiscard]] QRect imageRect() const;
|
||||
[[nodiscard]] QRect titleRangeRect(int from, int till) const;
|
||||
@@ -103,14 +101,6 @@ private:
|
||||
[[nodiscard]] BarState countBarState() const;
|
||||
void ensureGradientsCreated(int size);
|
||||
|
||||
void paintImageWithSpoiler(
|
||||
QPainter &p,
|
||||
QRect rect,
|
||||
const QPixmap &image,
|
||||
SpoilerAnimation *spoiler,
|
||||
crl::time now,
|
||||
bool paused) const;
|
||||
|
||||
[[nodiscard]] static BodyAnimation DetectBodyAnimationType(
|
||||
Animation *currentAnimation,
|
||||
const MessageBarContent ¤tContent,
|
||||
@@ -124,7 +114,6 @@ private:
|
||||
Text::String _title, _text;
|
||||
QPixmap _image, _topBarGradient, _bottomBarGradient;
|
||||
std::unique_ptr<Animation> _animation;
|
||||
std::unique_ptr<SpoilerAnimation> _spoiler;
|
||||
bool _customEmojiRepaintScheduled = false;
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user