mirror of
https://github.com/vale981/tdesktop
synced 2025-03-05 09:41:41 -05:00
Generate previews for cloud theme links.
This commit is contained in:
parent
6d29dc3b36
commit
ee5423762a
20 changed files with 193 additions and 80 deletions
|
@ -1149,6 +1149,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_media_size_limit" = "Limit by size";
|
||||
"lng_media_size_up_to" = "up to {size}";
|
||||
"lng_media_chat_background" = "Chat background";
|
||||
"lng_media_color_theme" = "Color theme";
|
||||
|
||||
"lng_emoji_category1" = "People";
|
||||
"lng_emoji_category2" = "Nature";
|
||||
|
|
|
@ -650,6 +650,7 @@ void DocumentData::validateGoodThumbnail() {
|
|||
if (!isVideoFile()
|
||||
&& !isAnimation()
|
||||
&& !isWallPaper()
|
||||
&& !isTheme()
|
||||
&& (!sticker() || !sticker()->animated)) {
|
||||
_goodThumbnail = nullptr;
|
||||
} else if (!_goodThumbnail && hasRemoteLocation()) {
|
||||
|
@ -1470,7 +1471,8 @@ bool DocumentData::isGifv() const {
|
|||
|
||||
bool DocumentData::isTheme() const {
|
||||
return
|
||||
_filename.endsWith(
|
||||
_mimeString == qstr("application/x-tgtheme-tdesktop")
|
||||
|| _filename.endsWith(
|
||||
qstr(".tdesktop-theme"),
|
||||
Qt::CaseInsensitive)
|
||||
|| _filename.endsWith(
|
||||
|
|
|
@ -10,8 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_session.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_cloud_themes.h"
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "lottie/lottie_animation.h"
|
||||
#include "window/themes/window_theme_preview.h"
|
||||
#include "main/main_session.h"
|
||||
|
||||
#include <QtCore/QBuffer>
|
||||
|
@ -27,6 +29,7 @@ enum class FileType {
|
|||
Video,
|
||||
AnimatedSticker,
|
||||
WallPaper,
|
||||
Theme,
|
||||
};
|
||||
|
||||
QImage Prepare(
|
||||
|
@ -37,6 +40,8 @@ QImage Prepare(
|
|||
return ::Media::Clip::PrepareForSending(path, data).thumbnail;
|
||||
} else if (type == FileType::AnimatedSticker) {
|
||||
return Lottie::ReadThumbnail(Lottie::ReadContent(data, path));
|
||||
} else if (type == FileType::Theme) {
|
||||
return Window::Theme::GeneratePreview(data, path);
|
||||
}
|
||||
const auto validateSize = [](QSize size) {
|
||||
return (size.width() + size.height()) < 10'000;
|
||||
|
@ -78,6 +83,8 @@ void GoodThumbSource::generate(base::binary_guard &&guard) {
|
|||
const auto data = _document->data();
|
||||
const auto type = _document->isWallPaper()
|
||||
? FileType::WallPaper
|
||||
: _document->isTheme()
|
||||
? FileType::Theme
|
||||
: _document->sticker()
|
||||
? FileType::AnimatedSticker
|
||||
: FileType::Video;
|
||||
|
@ -143,13 +150,13 @@ void GoodThumbSource::ready(
|
|||
_document->goodThumbnailCacheKey(),
|
||||
Storage::Cache::Database::TaggedValue{
|
||||
std::move(bytes),
|
||||
Data::kImageCacheTag });
|
||||
kImageCacheTag });
|
||||
}
|
||||
Auth().downloaderTaskFinished().notify();
|
||||
});
|
||||
}
|
||||
|
||||
void GoodThumbSource::load(Data::FileOrigin origin) {
|
||||
void GoodThumbSource::load(FileOrigin origin) {
|
||||
if (loading() || _empty) {
|
||||
return;
|
||||
}
|
||||
|
@ -178,7 +185,7 @@ void GoodThumbSource::load(Data::FileOrigin origin) {
|
|||
std::move(callback));
|
||||
}
|
||||
|
||||
void GoodThumbSource::loadEvenCancelled(Data::FileOrigin origin) {
|
||||
void GoodThumbSource::loadEvenCancelled(FileOrigin origin) {
|
||||
_empty = false;
|
||||
load(origin);
|
||||
}
|
||||
|
@ -193,7 +200,7 @@ void GoodThumbSource::unload() {
|
|||
}
|
||||
|
||||
void GoodThumbSource::automaticLoad(
|
||||
Data::FileOrigin origin,
|
||||
FileOrigin origin,
|
||||
const HistoryItem *item) {
|
||||
}
|
||||
|
||||
|
@ -235,7 +242,7 @@ void GoodThumbSource::setDelayedStorageLocation(
|
|||
const StorageImageLocation &location) {
|
||||
}
|
||||
|
||||
void GoodThumbSource::performDelayedLoad(Data::FileOrigin origin) {
|
||||
void GoodThumbSource::performDelayedLoad(FileOrigin origin) {
|
||||
}
|
||||
|
||||
bool GoodThumbSource::isDelayedStorageImage() const {
|
||||
|
|
|
@ -17,13 +17,13 @@ class GoodThumbSource : public Images::Source {
|
|||
public:
|
||||
explicit GoodThumbSource(not_null<DocumentData*> document);
|
||||
|
||||
void load(Data::FileOrigin origin) override;
|
||||
void loadEvenCancelled(Data::FileOrigin origin) override;
|
||||
void load(FileOrigin origin) override;
|
||||
void loadEvenCancelled(FileOrigin origin) override;
|
||||
QImage takeLoaded() override;
|
||||
void unload() override;
|
||||
|
||||
void automaticLoad(
|
||||
Data::FileOrigin origin,
|
||||
FileOrigin origin,
|
||||
const HistoryItem *item) override;
|
||||
void automaticLoadSettingsChanged() override;
|
||||
|
||||
|
@ -38,7 +38,7 @@ public:
|
|||
std::optional<Storage::Cache::Key> cacheKey() override;
|
||||
void setDelayedStorageLocation(
|
||||
const StorageImageLocation &location) override;
|
||||
void performDelayedLoad(Data::FileOrigin origin) override;
|
||||
void performDelayedLoad(FileOrigin origin) override;
|
||||
bool isDelayedStorageImage() const override;
|
||||
void setImageBytes(const QByteArray &bytes) override;
|
||||
|
||||
|
|
|
@ -51,6 +51,9 @@ struct FileReferenceAccumulator {
|
|||
if (const auto document = data.vdocument()) {
|
||||
push(*document);
|
||||
}
|
||||
if (const auto documents = data.vdocuments()) {
|
||||
push(*documents);
|
||||
}
|
||||
if (const auto photo = data.vphoto()) {
|
||||
push(*photo);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/view/media/history_view_call.h"
|
||||
#include "history/view/media/history_view_web_page.h"
|
||||
#include "history/view/media/history_view_poll.h"
|
||||
#include "history/view/media/history_view_theme_document.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/image/image_source.h"
|
||||
#include "ui/text_options.h"
|
||||
|
@ -779,6 +780,10 @@ std::unique_ptr<HistoryView::Media> MediaFile::createView(
|
|||
message,
|
||||
realParent,
|
||||
_document);
|
||||
} else if (_document->isTheme() && _document->hasThumbnail()) {
|
||||
return std::make_unique<HistoryView::ThemeDocument>(
|
||||
message,
|
||||
_document);
|
||||
}
|
||||
return std::make_unique<HistoryView::Document>(message, _document);
|
||||
}
|
||||
|
|
|
@ -2762,6 +2762,17 @@ void Session::webpageApplyFields(
|
|||
const auto pendingTill = TimeId(0);
|
||||
const auto photo = data.vphoto();
|
||||
const auto document = data.vdocument();
|
||||
const auto lookupThemeDocument = [&]() -> DocumentData* {
|
||||
if (const auto documents = data.vdocuments()) {
|
||||
for (const auto &document : documents->v) {
|
||||
const auto processed = processDocument(document);
|
||||
if (processed->isTheme()) {
|
||||
return processed;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
webpageApplyFields(
|
||||
page,
|
||||
ParseWebPageType(data),
|
||||
|
@ -2771,7 +2782,7 @@ void Session::webpageApplyFields(
|
|||
qs(data.vtitle().value_or_empty()),
|
||||
description,
|
||||
photo ? processPhoto(*photo).get() : nullptr,
|
||||
document ? processDocument(*document).get() : nullptr,
|
||||
document ? processDocument(*document).get() : lookupThemeDocument(),
|
||||
WebPageCollage(data),
|
||||
data.vduration().value_or_empty(),
|
||||
qs(data.vauthor().value_or_empty()),
|
||||
|
|
|
@ -139,6 +139,8 @@ WebPageType ParseWebPageType(const MTPDwebPage &page) {
|
|||
return WebPageType::Profile;
|
||||
} else if (type == qstr("telegram_background")) {
|
||||
return WebPageType::WallPaper;
|
||||
} else if (type == qstr("telegram_theme")) {
|
||||
return WebPageType::Theme;
|
||||
} else if (page.vcached_page()) {
|
||||
return WebPageType::ArticleWithIV;
|
||||
} else {
|
||||
|
|
|
@ -15,6 +15,7 @@ enum class WebPageType {
|
|||
Video,
|
||||
Profile,
|
||||
WallPaper,
|
||||
Theme,
|
||||
Article,
|
||||
ArticleWithIV,
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@ maxVideoMessageSize: 240px;
|
|||
maxSignatureSize: 144px;
|
||||
maxWallPaperWidth: 160px;
|
||||
maxWallPaperHeight: 240px;
|
||||
historyThemeSize: size(309px, 200px);
|
||||
|
||||
historyMinimalWidth: 380px;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/view/media/history_view_document.h"
|
||||
#include "history/view/media/history_view_sticker.h"
|
||||
#include "history/view/media/history_view_video.h"
|
||||
#include "history/view/media/history_view_wall_paper.h"
|
||||
#include "history/view/media/history_view_theme_document.h"
|
||||
#include "styles/style_history.h"
|
||||
|
||||
namespace HistoryView {
|
||||
|
@ -80,8 +80,8 @@ std::unique_ptr<Media> CreateAttach(
|
|||
parent,
|
||||
parent->data(),
|
||||
document);
|
||||
} else if (document->isWallPaper()) {
|
||||
return std::make_unique<WallPaper>(
|
||||
} else if (document->isWallPaper() || document->isTheme()) {
|
||||
return std::make_unique<ThemeDocument>(
|
||||
parent,
|
||||
document,
|
||||
webpageUrl);
|
||||
|
|
|
@ -5,7 +5,7 @@ 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 "history/view/media/history_view_wall_paper.h"
|
||||
#include "history/view/media/history_view_theme_document.h"
|
||||
|
||||
#include "layout.h"
|
||||
#include "history/history_item.h"
|
||||
|
@ -19,22 +19,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace HistoryView {
|
||||
|
||||
WallPaper::WallPaper(
|
||||
ThemeDocument::ThemeDocument(
|
||||
not_null<Element*> parent,
|
||||
not_null<DocumentData*> document,
|
||||
const QString &url)
|
||||
: File(parent, parent->data())
|
||||
, _data(document) {
|
||||
Expects(_data->hasThumbnail());
|
||||
Expects(_data->hasThumbnail() || _data->isTheme());
|
||||
|
||||
fillPatternFieldsFrom(url);
|
||||
if (_data->isWallPaper()) {
|
||||
fillPatternFieldsFrom(url);
|
||||
}
|
||||
|
||||
_data->thumbnail()->load(parent->data()->fullId());
|
||||
_data->loadThumbnail(_parent->data()->fullId());
|
||||
setDocumentLinks(_data, parent->data());
|
||||
setStatusSize(FileStatusSizeReady, _data->size, -1, 0);
|
||||
}
|
||||
|
||||
void WallPaper::fillPatternFieldsFrom(const QString &url) {
|
||||
void ThemeDocument::fillPatternFieldsFrom(const QString &url) {
|
||||
const auto paramsPosition = url.indexOf('?');
|
||||
if (paramsPosition < 0) {
|
||||
return;
|
||||
|
@ -49,7 +51,10 @@ void WallPaper::fillPatternFieldsFrom(const QString &url) {
|
|||
_background = paper.backgroundColor().value_or(kDefaultBackground);
|
||||
}
|
||||
|
||||
QSize WallPaper::countOptimalSize() {
|
||||
QSize ThemeDocument::countOptimalSize() {
|
||||
if (_data->isTheme()) {
|
||||
return st::historyThemeSize;
|
||||
}
|
||||
auto tw = ConvertScale(_data->thumbnail()->width());
|
||||
auto th = ConvertScale(_data->thumbnail()->height());
|
||||
if (!tw || !th) {
|
||||
|
@ -66,7 +71,12 @@ QSize WallPaper::countOptimalSize() {
|
|||
return { maxWidth, minHeight };
|
||||
}
|
||||
|
||||
QSize WallPaper::countCurrentSize(int newWidth) {
|
||||
QSize ThemeDocument::countCurrentSize(int newWidth) {
|
||||
if (_data->isTheme()) {
|
||||
_pixw = st::historyThemeSize.width();
|
||||
_pixh = st::historyThemeSize.height();
|
||||
return st::historyThemeSize;
|
||||
}
|
||||
auto tw = ConvertScale(_data->thumbnail()->width());
|
||||
auto th = ConvertScale(_data->thumbnail()->height());
|
||||
if (!tw || !th) {
|
||||
|
@ -86,7 +96,7 @@ QSize WallPaper::countCurrentSize(int newWidth) {
|
|||
return { newWidth, newHeight };
|
||||
}
|
||||
|
||||
void WallPaper::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
||||
void ThemeDocument::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||
|
||||
_data->automaticLoad(_realParent->fullId(), _parent->data());
|
||||
|
@ -166,7 +176,7 @@ void WallPaper::draw(Painter &p, const QRect &r, TextSelection selection, crl::t
|
|||
}
|
||||
}
|
||||
|
||||
void WallPaper::validateThumbnail() const {
|
||||
void ThemeDocument::validateThumbnail() const {
|
||||
if (_thumbnailGood > 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -179,7 +189,7 @@ void WallPaper::validateThumbnail() const {
|
|||
good->load({});
|
||||
}
|
||||
}
|
||||
if (_thumbnailGood >= 0) {
|
||||
if (_thumbnailGood >= 0 || !_data->thumbnail()) {
|
||||
return;
|
||||
}
|
||||
if (_data->thumbnail()->loaded()) {
|
||||
|
@ -191,11 +201,12 @@ void WallPaper::validateThumbnail() const {
|
|||
}
|
||||
}
|
||||
|
||||
void WallPaper::prepareThumbnailFrom(
|
||||
void ThemeDocument::prepareThumbnailFrom(
|
||||
not_null<Image*> image,
|
||||
int good) const {
|
||||
Expects(_thumbnailGood <= good);
|
||||
|
||||
const auto isTheme = _data->isTheme();
|
||||
const auto isPattern = _data->isPatternWallPaper();
|
||||
auto options = Images::Option::Smooth
|
||||
| (good >= 0 ? Images::Option(0) : Images::Option::Blurred)
|
||||
|
@ -203,8 +214,8 @@ void WallPaper::prepareThumbnailFrom(
|
|||
? Images::Option::TransparentBackground
|
||||
: Images::Option(0));
|
||||
auto original = image->original();
|
||||
auto tw = ConvertScale(_data->thumbnail()->width());
|
||||
auto th = ConvertScale(_data->thumbnail()->height());
|
||||
auto tw = isTheme ? _pixw : ConvertScale(_data->thumbnail()->width());
|
||||
auto th = isTheme ? _pixh : ConvertScale(_data->thumbnail()->height());
|
||||
if (!tw || !th) {
|
||||
tw = th = 1;
|
||||
}
|
||||
|
@ -226,7 +237,7 @@ void WallPaper::prepareThumbnailFrom(
|
|||
_thumbnailGood = good;
|
||||
}
|
||||
|
||||
TextState WallPaper::textState(QPoint point, StateRequest request) const {
|
||||
TextState ThemeDocument::textState(QPoint point, StateRequest request) const {
|
||||
auto result = TextState(_parent);
|
||||
|
||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) {
|
||||
|
@ -248,24 +259,24 @@ TextState WallPaper::textState(QPoint point, StateRequest request) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
float64 WallPaper::dataProgress() const {
|
||||
float64 ThemeDocument::dataProgress() const {
|
||||
return _data->progress();
|
||||
}
|
||||
|
||||
bool WallPaper::dataFinished() const {
|
||||
bool ThemeDocument::dataFinished() const {
|
||||
return !_data->loading()
|
||||
&& (!_data->uploading() || _data->waitingForAlbum());
|
||||
}
|
||||
|
||||
bool WallPaper::dataLoaded() const {
|
||||
bool ThemeDocument::dataLoaded() const {
|
||||
return _data->loaded();
|
||||
}
|
||||
|
||||
bool WallPaper::isReadyForOpen() const {
|
||||
bool ThemeDocument::isReadyForOpen() const {
|
||||
return _data->loaded();
|
||||
}
|
||||
|
||||
QString WallPaper::additionalInfoString() const {
|
||||
QString ThemeDocument::additionalInfoString() const {
|
||||
// This will force message info (time) to be displayed below
|
||||
// this attachment in WebPage media.
|
||||
static auto result = QString(" ");
|
|
@ -11,9 +11,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace HistoryView {
|
||||
|
||||
class WallPaper : public File {
|
||||
class ThemeDocument : public File {
|
||||
public:
|
||||
WallPaper(
|
||||
ThemeDocument(
|
||||
not_null<Element*> parent,
|
||||
not_null<DocumentData*> document,
|
||||
const QString &url = QString());
|
||||
|
@ -59,6 +59,8 @@ private:
|
|||
int _pixh = 1;
|
||||
mutable QPixmap _thumbnail;
|
||||
mutable int _thumbnailGood = -1; // -1 inline, 0 thumbnail, 1 good
|
||||
|
||||
// For wallpaper documents.
|
||||
QColor _background;
|
||||
int _intensity = 0;
|
||||
|
|
@ -129,7 +129,9 @@ QSize WebPage::countOptimalSize() {
|
|||
_openl = previewOfHiddenUrl
|
||||
? std::make_shared<HiddenUrlClickHandler>(_data->url)
|
||||
: std::make_shared<UrlClickHandler>(_data->url, true);
|
||||
if (_data->document && _data->document->isWallPaper()) {
|
||||
if (_data->document
|
||||
&& (_data->document->isWallPaper()
|
||||
|| _data->document->isTheme())) {
|
||||
_openl = std::make_shared<DocumentWrappedClickHandler>(
|
||||
std::move(_openl),
|
||||
_data->document,
|
||||
|
@ -652,7 +654,7 @@ ClickHandlerPtr WebPage::replaceAttachLink(
|
|||
return link;
|
||||
}
|
||||
if (_data->document) {
|
||||
if (_data->document->isWallPaper()) {
|
||||
if (_data->document->isWallPaper() || _data->document->isTheme()) {
|
||||
return _openl;
|
||||
}
|
||||
} else if (_data->photo) {
|
||||
|
@ -674,7 +676,7 @@ TextSelection WebPage::adjustSelection(TextSelection selection, TextSelectType t
|
|||
if ((!_titleLines && !_descriptionLines) || selection.to <= _siteName.length()) {
|
||||
return _siteName.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
|
||||
auto titleSelection = _title.adjustSelection(toTitleSelection(selection), type);
|
||||
if ((!_siteNameLines && !_descriptionLines) || (selection.from >= _siteName.length() && selection.to <= _description.length())) {
|
||||
return fromTitleSelection(titleSelection);
|
||||
|
@ -708,7 +710,7 @@ void WebPage::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed)
|
|||
bool WebPage::enforceBubbleWidth() const {
|
||||
return (_attach != nullptr)
|
||||
&& (_data->document != nullptr)
|
||||
&& _data->document->isWallPaper();
|
||||
&& (_data->document->isWallPaper() || _data->document->isTheme());
|
||||
}
|
||||
|
||||
void WebPage::playAnimation(bool autoplay) {
|
||||
|
@ -779,6 +781,8 @@ int WebPage::bottomInfoPadding() const {
|
|||
QString WebPage::displayedSiteName() const {
|
||||
return (_data->document && _data->document->isWallPaper())
|
||||
? tr::lng_media_chat_background(tr::now)
|
||||
: (_data->document && _data->document->isWallPaper())
|
||||
? tr::lng_media_color_theme(tr::now)
|
||||
: _data->siteName;
|
||||
}
|
||||
|
||||
|
|
|
@ -2251,7 +2251,12 @@ void OverlayWidget::initThemePreview() {
|
|||
const auto id = _themePreviewId = rand_value<uint64>();
|
||||
const auto weak = make_weak(this);
|
||||
crl::async([=, data = std::move(current)]() mutable {
|
||||
auto preview = GeneratePreview(bytes, path, fields, std::move(data));
|
||||
auto preview = GeneratePreview(
|
||||
bytes,
|
||||
path,
|
||||
fields,
|
||||
std::move(data),
|
||||
Window::Theme::PreviewType::Extended);
|
||||
crl::on_main(weak, [=, result = std::move(preview)]() mutable {
|
||||
if (id != _themePreviewId) {
|
||||
return;
|
||||
|
|
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "lang/lang_keys.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "window/themes/window_theme_preview.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -78,13 +79,6 @@ PreparedFileThumbnail PrepareFileThumbnail(QImage &&original) {
|
|||
return result;
|
||||
}
|
||||
|
||||
PreparedFileThumbnail PrepareAnimatedStickerThumbnail(
|
||||
const QString &file,
|
||||
const QByteArray &bytes) {
|
||||
return PrepareFileThumbnail(
|
||||
Lottie::ReadThumbnail(Lottie::ReadContent(bytes, file)));
|
||||
}
|
||||
|
||||
bool FileThumbnailUploadRequired(const QString &filemime, int32 filesize) {
|
||||
constexpr auto kThumbnailUploadBySize = 5 * 1024 * 1024;
|
||||
const auto kThumbnailKnownMimes = {
|
||||
|
@ -818,6 +812,15 @@ void FileLoadTask::process() {
|
|||
}
|
||||
|
||||
thumbnail = PrepareFileThumbnail(std::move(video->thumbnail));
|
||||
} else if (filemime == qstr("application/x-tdesktop-theme")
|
||||
|| filemime == qstr("application/x-tgtheme-tdesktop")) {
|
||||
goodThumbnail = Window::Theme::GeneratePreview(_content, _filepath);
|
||||
if (!goodThumbnail.isNull()) {
|
||||
QBuffer buffer(&goodThumbnailBytes);
|
||||
goodThumbnail.save(&buffer, "JPG", kThumbnailQuality);
|
||||
|
||||
thumbnail = PrepareFileThumbnail(base::duplicate(goodThumbnail));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -465,15 +465,26 @@ SendMediaReady PrepareThemeMedia(
|
|||
PreparedPhotoThumbs thumbnails;
|
||||
QVector<MTPPhotoSize> sizes;
|
||||
|
||||
//const auto push = [&](const char *type, QImage &&image) {
|
||||
// sizes.push_back(MTP_photoSize(
|
||||
// MTP_string(type),
|
||||
// MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)),
|
||||
// MTP_int(image.width()),
|
||||
// MTP_int(image.height()), MTP_int(0)));
|
||||
// thumbnails.emplace(type[0], std::move(image));
|
||||
//};
|
||||
//push("s", scaled(320));
|
||||
auto thumbnail = GeneratePreview(content, QString()).scaled(
|
||||
320,
|
||||
320,
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
auto thumbnailBytes = QByteArray();
|
||||
{
|
||||
QBuffer buffer(&thumbnailBytes);
|
||||
thumbnail.save(&buffer, "JPG", 87);
|
||||
}
|
||||
|
||||
const auto push = [&](const char *type, QImage &&image) {
|
||||
sizes.push_back(MTP_photoSize(
|
||||
MTP_string(type),
|
||||
MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)),
|
||||
MTP_int(image.width()),
|
||||
MTP_int(image.height()), MTP_int(0)));
|
||||
thumbnails.emplace(type[0], std::move(image));
|
||||
};
|
||||
push("s", std::move(thumbnail));
|
||||
|
||||
const auto filename = File::NameFromUserString(name)
|
||||
+ qsl(".tdesktop-theme");
|
||||
|
@ -506,7 +517,7 @@ SendMediaReady PrepareThemeMedia(
|
|||
MTP_photoEmpty(MTP_long(0)),
|
||||
thumbnails,
|
||||
document,
|
||||
QByteArray(),
|
||||
thumbnailBytes,
|
||||
0);
|
||||
}
|
||||
|
||||
|
@ -520,7 +531,7 @@ Fn<void()> SavePreparedTheme(
|
|||
Fn<void(SaveErrorType,QString)> fail) {
|
||||
Expects(window->account().sessionExists());
|
||||
|
||||
using Storage::UploadedDocument;
|
||||
using Storage::UploadedThumbDocument;
|
||||
struct State {
|
||||
FullMsgId id;
|
||||
bool generating = false;
|
||||
|
@ -539,6 +550,7 @@ Fn<void()> SavePreparedTheme(
|
|||
|
||||
const auto creating = !fields.id
|
||||
|| (fields.createdBy != session->userId());
|
||||
const auto oldDocumentId = creating ? 0 : fields.documentId;
|
||||
const auto changed = (parsed.background != originalParsed.background)
|
||||
|| (parsed.tiled != originalParsed.tiled)
|
||||
|| PaletteChanged(parsed.palette, originalParsed.palette, fields);
|
||||
|
@ -602,11 +614,11 @@ Fn<void()> SavePreparedTheme(
|
|||
}).send();
|
||||
};
|
||||
|
||||
const auto uploadTheme = [=](const UploadedDocument &data) {
|
||||
const auto uploadTheme = [=](const UploadedThumbDocument &data) {
|
||||
state->requestId = api->request(MTPaccount_UploadTheme(
|
||||
MTP_flags(0),
|
||||
MTP_flags(MTPaccount_UploadTheme::Flag::f_thumb),
|
||||
data.file,
|
||||
MTPInputFile(), // thumb
|
||||
data.thumb,
|
||||
MTP_string(state->filename),
|
||||
MTP_string("application/x-tgtheme-tdesktop")
|
||||
)).done([=](const MTPDocument &result) {
|
||||
|
@ -625,10 +637,10 @@ Fn<void()> SavePreparedTheme(
|
|||
state->filename = media.filename;
|
||||
state->themeContent = theme;
|
||||
|
||||
session->uploader().documentReady(
|
||||
) | rpl::filter([=](const UploadedDocument &data) {
|
||||
session->uploader().thumbDocumentReady(
|
||||
) | rpl::filter([=](const UploadedThumbDocument &data) {
|
||||
return data.fullId == state->id;
|
||||
}) | rpl::start_with_next([=](const UploadedDocument &data) {
|
||||
}) | rpl::start_with_next([=](const UploadedThumbDocument &data) {
|
||||
uploadTheme(data);
|
||||
}, state->lifetime);
|
||||
|
||||
|
|
|
@ -83,9 +83,12 @@ QString fillLetters(const QString &name) {
|
|||
|
||||
class Generator {
|
||||
public:
|
||||
Generator(const Instance &theme, CurrentData &¤t);
|
||||
Generator(
|
||||
const Instance &theme,
|
||||
CurrentData &¤t,
|
||||
PreviewType type);
|
||||
|
||||
QImage generate();
|
||||
[[nodiscard]] QImage generate();
|
||||
|
||||
private:
|
||||
enum class Status {
|
||||
|
@ -131,6 +134,7 @@ private:
|
|||
Ui::Text::String replyText = { st::msgMinWidth };
|
||||
};
|
||||
|
||||
[[nodiscard]] bool extended() const;
|
||||
void prepare();
|
||||
|
||||
void addRow(QString name, int peerIndex, QString date, QString text);
|
||||
|
@ -162,7 +166,8 @@ private:
|
|||
|
||||
const Instance &_theme;
|
||||
const style::palette &_palette;
|
||||
CurrentData _current;
|
||||
const CurrentData _current;
|
||||
const PreviewType _type;
|
||||
Painter *_p = nullptr;
|
||||
|
||||
QRect _rect;
|
||||
|
@ -188,10 +193,19 @@ private:
|
|||
|
||||
};
|
||||
|
||||
bool Generator::extended() const {
|
||||
return (_type == PreviewType::Extended);
|
||||
}
|
||||
|
||||
void Generator::prepare() {
|
||||
_rect = QRect(0, 0, st::themePreviewMargin.left() + st::themePreviewSize.width() + st::themePreviewMargin.right(), st::themePreviewMargin.top() + st::themePreviewSize.height() + st::themePreviewMargin.bottom());
|
||||
_inner = _rect.marginsRemoved(st::themePreviewMargin);
|
||||
_body = _inner.marginsRemoved(QMargins(0, Platform::PreviewTitleHeight(), 0, 0));
|
||||
const auto size = extended()
|
||||
? QRect(
|
||||
QPoint(),
|
||||
st::themePreviewSize).marginsAdded(st::themePreviewMargin).size()
|
||||
: st::themePreviewSize;
|
||||
_rect = QRect(QPoint(), size);
|
||||
_inner = extended() ? _rect.marginsRemoved(st::themePreviewMargin) : _rect;
|
||||
_body = extended() ? _inner.marginsRemoved(QMargins(0, Platform::PreviewTitleHeight(), 0, 0)) : _inner;
|
||||
_dialogs = QRect(_body.x(), _body.y(), st::themePreviewDialogsWidth, _body.height());
|
||||
_dialogsList = _dialogs.marginsRemoved(QMargins(0, st::dialogsFilterPadding.y() + st::dialogsMenuToggle.height + st::dialogsFilterPadding.y(), 0, st::dialogsPadding.y()));
|
||||
_topBar = QRect(_dialogs.x() + _dialogs.width(), _dialogs.y(), _body.width() - _dialogs.width(), st::topBarHeight);
|
||||
|
@ -339,10 +353,14 @@ void Generator::generateData() {
|
|||
_bubbles.back().replyText.setText(st::messageTextStyle, "Mark Twain said that " + QString() + QChar(9757) + QChar(55356) + QChar(57339), Ui::DialogTextOptions());
|
||||
}
|
||||
|
||||
Generator::Generator(const Instance &theme, CurrentData &¤t)
|
||||
Generator::Generator(
|
||||
const Instance &theme,
|
||||
CurrentData &¤t,
|
||||
PreviewType type)
|
||||
: _theme(theme)
|
||||
, _palette(_theme.palette)
|
||||
, _current(std::move(current)) {
|
||||
, _current(std::move(current))
|
||||
, _type(type) {
|
||||
}
|
||||
|
||||
QImage Generator::generate() {
|
||||
|
@ -368,7 +386,9 @@ QImage Generator::generate() {
|
|||
paintDialogs();
|
||||
paintHistoryShadows();
|
||||
}
|
||||
Platform::PreviewWindowFramePaint(result, _palette, _body, _rect.width());
|
||||
if (extended()) {
|
||||
Platform::PreviewWindowFramePaint(result, _palette, _body, _rect.width());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -944,18 +964,32 @@ std::unique_ptr<Preview> GeneratePreview(
|
|||
const QByteArray &bytes,
|
||||
const QString &filepath,
|
||||
const Data::CloudTheme &cloud,
|
||||
CurrentData &&data) {
|
||||
CurrentData &&data,
|
||||
PreviewType type) {
|
||||
auto result = PreviewFromFile(bytes, filepath, cloud);
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
result->preview = Generator(
|
||||
result->instance,
|
||||
std::move(data)
|
||||
std::move(data),
|
||||
type
|
||||
).generate();
|
||||
return result;
|
||||
}
|
||||
|
||||
QImage GeneratePreview(
|
||||
const QByteArray &bytes,
|
||||
const QString &filepath) {
|
||||
const auto preview = GeneratePreview(
|
||||
bytes,
|
||||
filepath,
|
||||
Data::CloudTheme(),
|
||||
CurrentData{ Data::ThemeWallPaper().id() },
|
||||
PreviewType::Normal);
|
||||
return preview ? preview->preview : QImage();
|
||||
}
|
||||
|
||||
int DefaultPreviewTitleHeight() {
|
||||
return st::titleHeight;
|
||||
}
|
||||
|
|
|
@ -17,11 +17,16 @@ namespace Window {
|
|||
namespace Theme {
|
||||
|
||||
struct CurrentData {
|
||||
int32 backgroundId = 0;
|
||||
WallPaperId backgroundId = 0;
|
||||
QImage backgroundImage;
|
||||
bool backgroundTiled = false;
|
||||
};
|
||||
|
||||
enum class PreviewType {
|
||||
Normal,
|
||||
Extended,
|
||||
};
|
||||
|
||||
[[nodiscard]] QString CachedThemePath(uint64 documentId);
|
||||
|
||||
std::unique_ptr<Preview> PreviewFromFile(
|
||||
|
@ -32,7 +37,11 @@ std::unique_ptr<Preview> GeneratePreview(
|
|||
const QByteArray &bytes,
|
||||
const QString &filepath,
|
||||
const Data::CloudTheme &cloud,
|
||||
CurrentData &&data);
|
||||
CurrentData &&data,
|
||||
PreviewType type);
|
||||
QImage GeneratePreview(
|
||||
const QByteArray &bytes,
|
||||
const QString &filepath);
|
||||
|
||||
int DefaultPreviewTitleHeight();
|
||||
void DefaultPreviewWindowFramePaint(
|
||||
|
|
|
@ -316,10 +316,10 @@
|
|||
<(src_loc)/history/view/media/history_view_poll.cpp
|
||||
<(src_loc)/history/view/media/history_view_sticker.h
|
||||
<(src_loc)/history/view/media/history_view_sticker.cpp
|
||||
<(src_loc)/history/view/media/history_view_theme_document.h
|
||||
<(src_loc)/history/view/media/history_view_theme_document.cpp
|
||||
<(src_loc)/history/view/media/history_view_video.h
|
||||
<(src_loc)/history/view/media/history_view_video.cpp
|
||||
<(src_loc)/history/view/media/history_view_wall_paper.h
|
||||
<(src_loc)/history/view/media/history_view_wall_paper.cpp
|
||||
<(src_loc)/history/view/media/history_view_web_page.h
|
||||
<(src_loc)/history/view/media/history_view_web_page.cpp
|
||||
<(src_loc)/history/view/history_view_compose_controls.cpp
|
||||
|
|
Loading…
Add table
Reference in a new issue