Show spoilers in shared media overview.

This commit is contained in:
John Preston 2022-12-27 13:10:38 +04:00
parent 2cbd2725e5
commit b4571b80d6
5 changed files with 95 additions and 22 deletions

View file

@ -761,8 +761,11 @@ void ListWidget::paintEvent(QPaintEvent *e) {
auto tillSectionIt = findSectionAfterBottom( auto tillSectionIt = findSectionAfterBottom(
fromSectionIt, fromSectionIt,
clip.y() + clip.height()); clip.y() + clip.height());
auto context = ListContext { const auto window = _controller->parentController();
Overview::Layout::PaintContext(ms, hasSelectedItems()), const auto paused = window->isGifPausedAtLeastFor(
Window::GifPauseReason::Layer);
auto context = ListContext{
Overview::Layout::PaintContext(ms, hasSelectedItems(), paused),
&_selected, &_selected,
&_dragSelected, &_dragSelected,
_dragSelectAction _dragSelectAction

View file

@ -416,18 +416,24 @@ std::unique_ptr<BaseLayout> Provider::createLayout(
return nullptr; return nullptr;
}; };
const auto getFile = [&]() -> DocumentData* { const auto getFile = [&]() -> DocumentData* {
if (auto media = item->media()) { if (const auto media = item->media()) {
return media->document(); return media->document();
} }
return nullptr; return nullptr;
}; };
const auto spoiler = [&] {
if (const auto media = item->media()) {
return media->hasSpoiler();
}
return false;
};
const auto &songSt = st::overviewFileLayout; const auto &songSt = st::overviewFileLayout;
using namespace Overview::Layout; using namespace Overview::Layout;
switch (type) { switch (type) {
case Type::Photo: case Type::Photo:
if (const auto photo = getPhoto()) { if (const auto photo = getPhoto()) {
return std::make_unique<Photo>(delegate, item, photo); return std::make_unique<Photo>(delegate, item, photo, spoiler());
} }
return nullptr; return nullptr;
case Type::GIF: case Type::GIF:
@ -437,7 +443,7 @@ std::unique_ptr<BaseLayout> Provider::createLayout(
return nullptr; return nullptr;
case Type::Video: case Type::Video:
if (const auto file = getFile()) { if (const auto file = getFile()) {
return std::make_unique<Video>(delegate, item, file); return std::make_unique<Video>(delegate, item, file, spoiler());
} }
return nullptr; return nullptr;
case Type::File: case Type::File:

View file

@ -16,8 +16,8 @@ public:
: ms(ms) : ms(ms)
, selecting(selecting) { , selecting(selecting) {
} }
crl::time ms; crl::time ms = 0;
bool selecting; bool selecting = false;
}; };

View file

@ -40,6 +40,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/media/history_view_document.h" // DrawThumbnailAsSongCover #include "history/view/media/history_view_document.h" // DrawThumbnailAsSongCover
#include "base/unixtime.h" #include "base/unixtime.h"
#include "ui/effects/round_checkbox.h" #include "ui/effects/round_checkbox.h"
#include "ui/effects/spoiler_mess.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "ui/text/format_song_document_name.h" #include "ui/text/format_song_document_name.h"
#include "ui/text/format_values.h" #include "ui/text/format_values.h"
@ -201,6 +202,7 @@ void RadialProgressItem::setDocumentLinks(
std::make_shared<DocumentOpenClickHandler>( std::make_shared<DocumentOpenClickHandler>(
document, document,
crl::guard(this, [=](FullMsgId id) { crl::guard(this, [=](FullMsgId id) {
clearSpoiler();
delegate()->openDocument(document, id, forceOpen); delegate()->openDocument(document, id, forceOpen);
}), }),
context), context),
@ -294,13 +296,20 @@ void StatusText::setSize(int64 newSize) {
Photo::Photo( Photo::Photo(
not_null<Delegate*> delegate, not_null<Delegate*> delegate,
not_null<HistoryItem*> parent, not_null<HistoryItem*> parent,
not_null<PhotoData*> photo) not_null<PhotoData*> photo,
bool spoiler)
: ItemBase(delegate, parent) : ItemBase(delegate, parent)
, _data(photo) , _data(photo)
, _link(std::make_shared<PhotoOpenClickHandler>( , _link(std::make_shared<PhotoOpenClickHandler>(
photo, photo,
crl::guard(this, [=](FullMsgId id) { delegate->openPhoto(photo, id); }), crl::guard(this, [=](FullMsgId id) {
parent->fullId())) { clearSpoiler();
delegate->openPhoto(photo, id);
}),
parent->fullId()))
, _spoiler(spoiler ? std::make_unique<Ui::SpoilerAnimation>([=] {
delegate->repaintItem(this);
}) : nullptr) {
if (_data->inlineThumbnailBytes().isEmpty() if (_data->inlineThumbnailBytes().isEmpty()
&& (_data->hasExact(Data::PhotoSize::Small) && (_data->hasExact(Data::PhotoSize::Small)
|| _data->hasExact(Data::PhotoSize::Thumbnail))) { || _data->hasExact(Data::PhotoSize::Thumbnail))) {
@ -327,8 +336,9 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
const auto widthChanged = _pix.width() != _width * cIntRetinaFactor(); const auto widthChanged = _pix.width() != _width * cIntRetinaFactor();
if (!_goodLoaded || widthChanged) { if (!_goodLoaded || widthChanged) {
ensureDataMediaCreated(); ensureDataMediaCreated();
const auto good = _dataMedia->loaded() const auto good = !_spoiler
|| (_dataMedia->image(Data::PhotoSize::Thumbnail) != nullptr); && (_dataMedia->loaded()
|| _dataMedia->image(Data::PhotoSize::Thumbnail));
if ((good && !_goodLoaded) || widthChanged) { if ((good && !_goodLoaded) || widthChanged) {
_goodLoaded = good; _goodLoaded = good;
_pix = QPixmap(); _pix = QPixmap();
@ -336,8 +346,9 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
setPixFrom(_dataMedia->image(Data::PhotoSize::Large) setPixFrom(_dataMedia->image(Data::PhotoSize::Large)
? _dataMedia->image(Data::PhotoSize::Large) ? _dataMedia->image(Data::PhotoSize::Large)
: _dataMedia->image(Data::PhotoSize::Thumbnail)); : _dataMedia->image(Data::PhotoSize::Thumbnail));
} else if (const auto small = _dataMedia->image( } else if (const auto small = _spoiler
Data::PhotoSize::Small)) { ? nullptr
: _dataMedia->image(Data::PhotoSize::Small)) {
setPixFrom(small); setPixFrom(small);
} else if (const auto blurred = _dataMedia->thumbnailInline()) { } else if (const auto blurred = _dataMedia->thumbnailInline()) {
setPixFrom(blurred); setPixFrom(blurred);
@ -351,6 +362,14 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
p.drawPixmap(0, 0, _pix); p.drawPixmap(0, 0, _pix);
} }
if (_spoiler) {
Ui::FillSpoilerRect(
p,
QRect(0, 0, _width, _height),
Ui::DefaultImageSpoiler().frame(
_spoiler->index(context->ms, context->paused)));
}
if (selected) { if (selected) {
p.fillRect(0, 0, _width, _height, st::overviewPhotoSelectOverlay); p.fillRect(0, 0, _width, _height, st::overviewPhotoSelectOverlay);
} }
@ -399,6 +418,14 @@ void Photo::ensureDataMediaCreated() const {
delegate()->registerHeavyItem(this); delegate()->registerHeavyItem(this);
} }
void Photo::clearSpoiler() {
if (_spoiler) {
_spoiler = nullptr;
_pix = QPixmap();
delegate()->repaintItem(this);
}
}
void Photo::clearHeavyPart() { void Photo::clearHeavyPart() {
_dataMedia = nullptr; _dataMedia = nullptr;
} }
@ -415,10 +442,14 @@ TextState Photo::getState(
Video::Video( Video::Video(
not_null<Delegate*> delegate, not_null<Delegate*> delegate,
not_null<HistoryItem*> parent, not_null<HistoryItem*> parent,
not_null<DocumentData*> video) not_null<DocumentData*> video,
bool spoiler)
: RadialProgressItem(delegate, parent) : RadialProgressItem(delegate, parent)
, _data(video) , _data(video)
, _duration(Ui::FormatDurationText(_data->getDuration())) { , _duration(Ui::FormatDurationText(_data->getDuration()))
, _spoiler(spoiler ? std::make_unique<Ui::SpoilerAnimation>([=] {
delegate->repaintItem(this);
}) : nullptr) {
setDocumentLinks(_data); setDocumentLinks(_data);
_data->loadThumbnail(parent->fullId()); _data->loadThumbnail(parent->fullId());
} }
@ -441,8 +472,8 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
const auto selected = (selection == FullSelection); const auto selected = (selection == FullSelection);
const auto blurred = _dataMedia->thumbnailInline(); const auto blurred = _dataMedia->thumbnailInline();
const auto thumbnail = _dataMedia->thumbnail(); const auto thumbnail = _spoiler ? nullptr : _dataMedia->thumbnail();
const auto good = _dataMedia->goodThumbnail(); const auto good = _spoiler ? nullptr : _dataMedia->goodThumbnail();
bool loaded = dataLoaded(), displayLoading = _data->displayLoading(); bool loaded = dataLoaded(), displayLoading = _data->displayLoading();
if (displayLoading) { if (displayLoading) {
@ -485,6 +516,14 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
p.drawPixmap(0, 0, _pix); p.drawPixmap(0, 0, _pix);
} }
if (_spoiler) {
Ui::FillSpoilerRect(
p,
QRect(0, 0, _width, _height),
Ui::DefaultImageSpoiler().frame(
_spoiler->index(context->ms, context->paused)));
}
if (selected) { if (selected) {
p.fillRect(QRect(0, 0, _width, _height), st::overviewPhotoSelectOverlay); p.fillRect(QRect(0, 0, _width, _height), st::overviewPhotoSelectOverlay);
} }
@ -554,6 +593,14 @@ void Video::ensureDataMediaCreated() const {
delegate()->registerHeavyItem(this); delegate()->registerHeavyItem(this);
} }
void Video::clearSpoiler() {
if (_spoiler) {
_spoiler = nullptr;
_pix = QPixmap();
delegate()->repaintItem(this);
}
}
void Video::clearHeavyPart() { void Video::clearHeavyPart() {
_dataMedia = nullptr; _dataMedia = nullptr;
} }
@ -2060,7 +2107,7 @@ void Gif::paint(
const auto pixmap = _gif->current({ const auto pixmap = _gif->current({
.frame = frame, .frame = frame,
.outer = r.size(), .outer = r.size(),
}, /*context->paused ? 0 : */context->ms); }, context->paused ? 0 : context->ms);
if (_thumb.isNull()) { if (_thumb.isNull()) {
_thumb = pixmap; _thumb = pixmap;
_thumbGood = true; _thumbGood = true;

View file

@ -27,6 +27,10 @@ class PhotoMedia;
class DocumentMedia; class DocumentMedia;
} // namespace Data } // namespace Data
namespace Ui {
class SpoilerAnimation;
} // namespace Ui
namespace Overview { namespace Overview {
namespace Layout { namespace Layout {
@ -36,9 +40,12 @@ class Delegate;
class PaintContext : public PaintContextBase { class PaintContext : public PaintContextBase {
public: public:
PaintContext(crl::time ms, bool selecting) : PaintContextBase(ms, selecting) { PaintContext(crl::time ms, bool selecting, bool paused)
: PaintContextBase(ms, selecting)
, paused(paused) {
} }
bool skipBorder = false; bool skipBorder = false;
bool paused = false;
}; };
@ -102,6 +109,9 @@ public:
void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override; void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
virtual void clearSpoiler() {
}
~RadialProgressItem(); ~RadialProgressItem();
protected: protected:
@ -178,7 +188,8 @@ public:
Photo( Photo(
not_null<Delegate*> delegate, not_null<Delegate*> delegate,
not_null<HistoryItem*> parent, not_null<HistoryItem*> parent,
not_null<PhotoData*> photo); not_null<PhotoData*> photo,
bool spoiler);
void initDimensions() override; void initDimensions() override;
int32 resizeGetHeight(int32 width) override; int32 resizeGetHeight(int32 width) override;
@ -192,10 +203,12 @@ public:
private: private:
void ensureDataMediaCreated() const; void ensureDataMediaCreated() const;
void setPixFrom(not_null<Image*> image); void setPixFrom(not_null<Image*> image);
void clearSpoiler();
const not_null<PhotoData*> _data; const not_null<PhotoData*> _data;
mutable std::shared_ptr<Data::PhotoMedia> _dataMedia; mutable std::shared_ptr<Data::PhotoMedia> _dataMedia;
ClickHandlerPtr _link; ClickHandlerPtr _link;
std::unique_ptr<Ui::SpoilerAnimation> _spoiler;
QPixmap _pix; QPixmap _pix;
bool _goodLoaded = false; bool _goodLoaded = false;
@ -265,7 +278,8 @@ public:
Video( Video(
not_null<Delegate*> delegate, not_null<Delegate*> delegate,
not_null<HistoryItem*> parent, not_null<HistoryItem*> parent,
not_null<DocumentData*> video); not_null<DocumentData*> video,
bool spoiler);
~Video(); ~Video();
void initDimensions() override; void initDimensions() override;
@ -276,6 +290,7 @@ public:
StateRequest request) const override; StateRequest request) const override;
void clearHeavyPart() override; void clearHeavyPart() override;
void clearSpoiler() override;
protected: protected:
float64 dataProgress() const override; float64 dataProgress() const override;
@ -292,6 +307,8 @@ private:
StatusText _status; StatusText _status;
QString _duration; QString _duration;
std::unique_ptr<Ui::SpoilerAnimation> _spoiler;
QPixmap _pix; QPixmap _pix;
bool _pixBlurred = true; bool _pixBlurred = true;