| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #include "ui/chat/attach/attach_single_media_preview.h"
- #include "editor/photo_editor_common.h"
- #include "ui/chat/attach/attach_prepare.h"
- #include "core/mime_type.h"
- #include "lottie/lottie_single_player.h"
- namespace Ui {
- SingleMediaPreview *SingleMediaPreview::Create(
- QWidget *parent,
- const style::ComposeControls &st,
- Fn<bool()> gifPaused,
- const PreparedFile &file,
- Fn<bool(AttachActionType)> actionAllowed,
- AttachControls::Type type) {
- auto preview = QImage();
- auto animated = false;
- auto animationPreview = false;
- auto hasModifications = false;
- if (const auto image = std::get_if<PreparedFileInformation::Image>(
- &file.information->media)) {
- preview = Editor::ImageModified(image->data, image->modifications);
- animated = animationPreview = image->animated;
- hasModifications = !image->modifications.empty();
- } else if (const auto video = std::get_if<PreparedFileInformation::Video>(
- &file.information->media)) {
- preview = file.videoCover
- ? file.videoCover->preview
- : video->thumbnail;
- animated = true;
- animationPreview = video->isGifv;
- }
- if (preview.isNull()) {
- return nullptr;
- } else if (!animated
- && !ValidateThumbDimensions(preview.width(), preview.height())
- && !hasModifications) {
- return nullptr;
- }
- return CreateChild<SingleMediaPreview>(
- parent,
- st,
- std::move(gifPaused),
- preview,
- animated,
- Core::IsMimeSticker(file.information->filemime),
- file.spoiler,
- animationPreview ? file.path : QString(),
- type,
- std::move(actionAllowed));
- }
- SingleMediaPreview::SingleMediaPreview(
- QWidget *parent,
- const style::ComposeControls &st,
- Fn<bool()> gifPaused,
- QImage preview,
- bool animated,
- bool sticker,
- bool spoiler,
- const QString &animatedPreviewPath,
- AttachControls::Type type,
- Fn<bool(AttachActionType)> actionAllowed)
- : AbstractSingleMediaPreview(parent, st, type, std::move(actionAllowed))
- , _gifPaused(std::move(gifPaused))
- , _sticker(sticker) {
- Expects(!preview.isNull());
- setAnimated(animated);
- preparePreview(preview);
- prepareAnimatedPreview(animatedPreviewPath, animated);
- setSpoiler(spoiler);
- }
- bool SingleMediaPreview::supportsSpoilers() const {
- return !_sticker || sendWay().sendImagesAsPhotos();
- }
- bool SingleMediaPreview::drawBackground() const {
- return !_sticker;
- }
- bool SingleMediaPreview::tryPaintAnimation(QPainter &p) {
- if (_gifPreview && _gifPreview->started()) {
- const auto paused = _gifPaused();
- const auto frame = _gifPreview->current({
- .frame = QSize(previewWidth(), previewHeight()),
- }, paused ? 0 : crl::now());
- p.drawImage(previewLeft(), previewTop(), frame);
- return true;
- } else if (_lottiePreview && _lottiePreview->ready()) {
- const auto frame = _lottiePreview->frame();
- const auto size = frame.size() / style::DevicePixelRatio();
- p.drawImage(
- QRect(
- previewLeft() + (previewWidth() - size.width()) / 2,
- (previewHeight() - size.height()) / 2,
- size.width(),
- size.height()),
- frame);
- _lottiePreview->markFrameShown();
- return true;
- }
- return false;
- }
- bool SingleMediaPreview::isAnimatedPreviewReady() const {
- return _gifPreview || _lottiePreview;
- }
- void SingleMediaPreview::prepareAnimatedPreview(
- const QString &animatedPreviewPath,
- bool animated) {
- if (_sticker && animated) {
- const auto box = QSize(previewWidth(), previewHeight())
- * style::DevicePixelRatio();
- _lottiePreview = std::make_unique<Lottie::SinglePlayer>(
- Lottie::ReadContent(QByteArray(), animatedPreviewPath),
- Lottie::FrameRequest{ box });
- _lottiePreview->updates(
- ) | rpl::start_with_next([=] {
- update();
- }, lifetime());
- } else if (!animatedPreviewPath.isEmpty()) {
- auto callback = [=](Media::Clip::Notification notification) {
- clipCallback(notification);
- };
- _gifPreview = Media::Clip::MakeReader(
- animatedPreviewPath,
- std::move(callback));
- }
- }
- void SingleMediaPreview::clipCallback(
- Media::Clip::Notification notification) {
- using namespace Media::Clip;
- switch (notification) {
- case Notification::Reinit: {
- if (_gifPreview && _gifPreview->state() == State::Error) {
- _gifPreview.setBad();
- }
- if (_gifPreview && _gifPreview->ready() && !_gifPreview->started()) {
- _gifPreview->start({
- .frame = QSize(previewWidth(), previewHeight()),
- });
- }
- update();
- } break;
- case Notification::Repaint: {
- if (_gifPreview && !_gifPreview->currentDisplayed()) {
- update();
- }
- } break;
- }
- }
- } // namespace Ui
|