diff --git a/Telegram/SourceFiles/api/api_peer_photo.cpp b/Telegram/SourceFiles/api/api_peer_photo.cpp index 9c8a470fa..c70ef4491 100644 --- a/Telegram/SourceFiles/api/api_peer_photo.cpp +++ b/Telegram/SourceFiles/api/api_peer_photo.cpp @@ -34,7 +34,7 @@ namespace { constexpr auto kSharedMediaLimit = 100; -[[nodiscard]] std::shared_ptr PreparePeerPhoto( +[[nodiscard]] SendMediaReady PreparePeerPhoto( MTP::DcId dcId, PeerId peerId, QImage &&image) { @@ -80,17 +80,24 @@ constexpr auto kSharedMediaLimit = 100; MTPVector(), MTP_int(dcId)); - auto result = MakePreparedFile({ - .id = id, - .type = SendMediaType::Photo, - }); - result->type = SendMediaType::Photo; - result->setFileData(jpeg); - result->thumbId = id; - result->thumbname = "thumb.jpg"; - result->photo = photo; - result->photoThumbs = photoThumbs; - return result; + QString file, filename; + int64 filesize = 0; + QByteArray data; + + return SendMediaReady( + SendMediaType::Photo, + file, + filename, + filesize, + data, + id, + id, + u"jpg"_q, + peerId, + photo, + photoThumbs, + MTP_documentEmpty(MTP_long(0)), + jpeg); } [[nodiscard]] std::optional PrepareMtpMarkup( @@ -232,7 +239,7 @@ void PeerPhoto::upload( _api.instance().mainDcId(), peer->id, base::take(photo.image)); - _session->uploader().upload(fakeId, ready); + _session->uploader().uploadMedia(fakeId, ready); } } diff --git a/Telegram/SourceFiles/api/api_ringtones.cpp b/Telegram/SourceFiles/api/api_ringtones.cpp index 307ba580a..87522bf58 100644 --- a/Telegram/SourceFiles/api/api_ringtones.cpp +++ b/Telegram/SourceFiles/api/api_ringtones.cpp @@ -24,25 +24,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Api { namespace { -std::shared_ptr PrepareRingtoneDocument( +SendMediaReady PrepareRingtoneDocument( MTP::DcId dcId, const QString &filename, const QString &filemime, const QByteArray &content) { - const auto id = base::RandomValue(); auto attributes = QVector( 1, MTP_documentAttributeFilename(MTP_string(filename))); - - auto result = MakePreparedFile({ - .id = id, - .type = SendMediaType::File, - }); - result->filename = filename; - result->content = content; - result->filesize = content.size(); - result->setFileData(content); - result->document = MTP_document( + const auto id = base::RandomValue(); + const auto document = MTP_document( MTP_flags(0), MTP_long(id), MTP_long(0), @@ -54,7 +45,21 @@ std::shared_ptr PrepareRingtoneDocument( MTPVector(), MTP_int(dcId), MTP_vector(std::move(attributes))); - return result; + + return SendMediaReady( + SendMediaType::File, + QString(), // filepath + filename, + content.size(), + content, + id, + 0, + QString(), + PeerId(), + MTP_photoEmpty(MTP_long(0)), + PreparedPhotoThumbs(), + document, + QByteArray()); } } // namespace @@ -97,7 +102,7 @@ void Ringtones::upload( _uploads.erase(already); } _uploads.emplace(fakeId, uploadedData); - _session->uploader().upload(fakeId, ready); + _session->uploader().uploadMedia(fakeId, ready); } void Ringtones::ready(const FullMsgId &msgId, const MTPInputFile &file) { diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index d91943fe0..72bd06b3d 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -353,7 +353,7 @@ void FillMessagePostFlags( void SendConfirmedFile( not_null session, - const std::shared_ptr &file) { + const std::shared_ptr &file) { const auto isEditing = (file->type != SendMediaType::Audio) && (file->to.replaceMediaOf != 0); const auto newId = FullMsgId( diff --git a/Telegram/SourceFiles/api/api_sending.h b/Telegram/SourceFiles/api/api_sending.h index 2fdbad843..e17c66f3e 100644 --- a/Telegram/SourceFiles/api/api_sending.h +++ b/Telegram/SourceFiles/api/api_sending.h @@ -14,7 +14,7 @@ class Session; class History; class PhotoData; class DocumentData; -struct FilePrepareResult; +struct FileLoadResult; namespace Api { @@ -40,6 +40,6 @@ void FillMessagePostFlags( void SendConfirmedFile( not_null session, - const std::shared_ptr &file); + const std::shared_ptr &file); } // namespace Api diff --git a/Telegram/SourceFiles/boxes/background_preview_box.cpp b/Telegram/SourceFiles/boxes/background_preview_box.cpp index a112c478a..3a9917719 100644 --- a/Telegram/SourceFiles/boxes/background_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/background_preview_box.cpp @@ -593,11 +593,11 @@ void BackgroundPreviewBox::uploadForPeer(bool both) { const auto ready = Window::Theme::PrepareWallPaper( session->mainDcId(), _paper.localThumbnail()->original()); - const auto documentId = ready->id; + const auto documentId = ready.id; _uploadId = FullMsgId( session->userPeerId(), session->data().nextLocalMessageId()); - session->uploader().upload(_uploadId, ready); + session->uploader().uploadMedia(_uploadId, ready); if (_uploadLifetime) { return; } diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index b4d8bb49c..43966331e 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/fields/input_field.h" #include "mtproto/sender.h" +struct FileLoadResult; enum class SendMediaType; class MessageLinksParser; struct InlineBotQuery; diff --git a/Telegram/SourceFiles/iv/iv_data.cpp b/Telegram/SourceFiles/iv/iv_data.cpp index 5258e6c9f..bbcca0b2c 100644 --- a/Telegram/SourceFiles/iv/iv_data.cpp +++ b/Telegram/SourceFiles/iv/iv_data.cpp @@ -25,7 +25,7 @@ QByteArray GeoPointId(Geo point) { const auto lon = int(point.lon * 1000000); const auto combined = (std::uint64_t(std::uint32_t(lat)) << 32) | std::uint64_t(std::uint32_t(lon)); - return QByteArray::number(quint64(combined)) + return QByteArray::number(combined) + ',' + QByteArray::number(point.access); } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 809086765..10bea63d4 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -16,6 +16,7 @@ struct HistoryMessageMarkupButton; class MainWindow; class HistoryWidget; class StackItem; +struct FileLoadResult; class History; class Image; diff --git a/Telegram/SourceFiles/passport/passport_form_controller.cpp b/Telegram/SourceFiles/passport/passport_form_controller.cpp index 980888ffb..684163163 100644 --- a/Telegram/SourceFiles/passport/passport_form_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_form_controller.cpp @@ -1581,10 +1581,14 @@ void FormController::uploadEncryptedFile( &session(), std::make_unique(std::move(data))); - auto prepared = MakePreparedFile({ - .id = file.uploadData->fileId, - .type = SendMediaType::Secure, - }); + auto prepared = std::make_shared( + TaskId(), + file.uploadData->fileId, + FileLoadTo(PeerId(), Api::SendOptions(), FullReplyTo(), MsgId()), + TextWithTags(), + false, + std::shared_ptr(nullptr)); + prepared->type = SendMediaType::Secure; prepared->content = QByteArray::fromRawData( reinterpret_cast(file.uploadData->bytes.data()), file.uploadData->bytes.size()); diff --git a/Telegram/SourceFiles/storage/file_upload.cpp b/Telegram/SourceFiles/storage/file_upload.cpp index e0c7f8b57..c40396955 100644 --- a/Telegram/SourceFiles/storage/file_upload.cpp +++ b/Telegram/SourceFiles/storage/file_upload.cpp @@ -59,15 +59,22 @@ constexpr auto kKillSessionTimeout = 15 * crl::time(1000); } // namespace struct Uploader::File { - explicit File(const std::shared_ptr &file); + File(const SendMediaReady &media); + File(const std::shared_ptr &file); void setDocSize(int64 size); bool setPartSize(uint32 partSize); - std::shared_ptr file; + std::shared_ptr file; + SendMediaReady media; int32 partsCount = 0; mutable int64 fileSentSize = 0; + uint64 id() const; + SendMediaType type() const; + uint64 thumbId() const; + const QString &filename() const; + HashMd5 md5Hash; std::unique_ptr docFile; @@ -78,15 +85,27 @@ struct Uploader::File { }; -Uploader::File::File(const std::shared_ptr &file) +Uploader::File::File(const SendMediaReady &media) : media(media) { + partsCount = media.parts.size(); + if (type() == SendMediaType::File + || type() == SendMediaType::ThemeFile + || type() == SendMediaType::Audio) { + setDocSize(media.file.isEmpty() + ? media.data.size() + : media.filesize); + } else { + docSize = docPartSize = docPartsCount = 0; + } +} +Uploader::File::File(const std::shared_ptr &file) : file(file) { - partsCount = (file->type == SendMediaType::Photo - || file->type == SendMediaType::Secure) + partsCount = (type() == SendMediaType::Photo + || type() == SendMediaType::Secure) ? file->fileparts.size() : file->thumbparts.size(); - if (file->type == SendMediaType::File - || file->type == SendMediaType::ThemeFile - || file->type == SendMediaType::Audio) { + if (type() == SendMediaType::File + || type() == SendMediaType::ThemeFile + || type() == SendMediaType::Audio) { setDocSize(file->filesize); } else { docSize = docPartSize = docPartsCount = 0; @@ -115,6 +134,22 @@ bool Uploader::File::setPartSize(uint32 partSize) { return (docPartsCount <= kDocumentMaxPartsCountDefault); } +uint64 Uploader::File::id() const { + return file ? file->id : media.id; +} + +SendMediaType Uploader::File::type() const { + return file ? file->type : media.type; +} + +uint64 Uploader::File::thumbId() const { + return file ? file->thumbId : media.thumbId; +} + +const QString &Uploader::File::filename() const { + return file ? file->filename : media.filename; +} + Uploader::Uploader(not_null api) : _api(api) , _nextTimer([=] { sendNext(); }) @@ -247,9 +282,39 @@ Main::Session &Uploader::session() const { return _api->session(); } +void Uploader::uploadMedia( + const FullMsgId &msgId, + const SendMediaReady &media) { + if (media.type == SendMediaType::Photo) { + session().data().processPhoto(media.photo, media.photoThumbs); + } else if (media.type == SendMediaType::File + || media.type == SendMediaType::ThemeFile + || media.type == SendMediaType::Audio) { + const auto document = media.photoThumbs.empty() + ? session().data().processDocument(media.document) + : session().data().processDocument( + media.document, + Images::FromImageInMemory( + media.photoThumbs.front().second.image, + "JPG", + media.photoThumbs.front().second.bytes)); + if (!media.data.isEmpty()) { + document->setDataAndCache(media.data); + if (media.type == SendMediaType::ThemeFile) { + document->checkWallPaperProperties(); + } + } + if (!media.file.isEmpty()) { + document->setLocation(Core::FileLocation(media.file)); + } + } + queue.emplace(msgId, File(media)); + sendNext(); +} + void Uploader::upload( const FullMsgId &msgId, - const std::shared_ptr &file) { + const std::shared_ptr &file) { if (file->type == SendMediaType::Photo) { const auto photo = session().data().processPhoto( file->photo, @@ -318,13 +383,13 @@ void Uploader::currentFailed() { } void Uploader::notifyFailed(FullMsgId id, const File &file) { - const auto type = file.file->type; + const auto type = file.type(); if (type == SendMediaType::Photo) { _photoFailed.fire_copy(id); } else if (type == SendMediaType::File || type == SendMediaType::ThemeFile || type == SendMediaType::Audio) { - const auto document = session().data().document(file.file->id); + const auto document = session().data().document(file.id()); if (document->uploading()) { document->status = FileUploadFailed; } @@ -374,14 +439,18 @@ void Uploader::sendNext() { } } - auto &parts = (uploadingData.file->type == SendMediaType::Photo - || uploadingData.file->type == SendMediaType::Secure) - ? uploadingData.file->fileparts - : uploadingData.file->thumbparts; - const auto partsOfId = (uploadingData.file->type == SendMediaType::Photo - || uploadingData.file->type == SendMediaType::Secure) - ? uploadingData.file->id - : uploadingData.file->thumbId; + auto &parts = uploadingData.file + ? ((uploadingData.type() == SendMediaType::Photo + || uploadingData.type() == SendMediaType::Secure) + ? uploadingData.file->fileparts + : uploadingData.file->thumbparts) + : uploadingData.media.parts; + const auto partsOfId = uploadingData.file + ? ((uploadingData.type() == SendMediaType::Photo + || uploadingData.type() == SendMediaType::Secure) + ? uploadingData.file->id + : uploadingData.file->thumbId) + : uploadingData.media.thumbId; if (parts.isEmpty()) { if (uploadingData.docSentParts >= uploadingData.docPartsCount) { if (requestsSent.empty() && docRequestsSent.empty()) { @@ -393,17 +462,19 @@ void Uploader::sendNext() { const auto attachedStickers = uploadingData.file ? uploadingData.file->attachedStickers : std::vector(); - if (uploadingData.file->type == SendMediaType::Photo) { - auto photoFilename = uploadingData.file->filename; + if (uploadingData.type() == SendMediaType::Photo) { + auto photoFilename = uploadingData.filename(); if (!photoFilename.endsWith(u".jpg"_q, Qt::CaseInsensitive)) { // Server has some extensions checking for inputMediaUploadedPhoto, // so force the extension to be .jpg anyway. It doesn't matter, // because the filename from inputFile is not used anywhere. photoFilename += u".jpg"_q; } - const auto md5 = uploadingData.file->filemd5; + const auto md5 = uploadingData.file + ? uploadingData.file->filemd5 + : uploadingData.media.jpeg_md5; const auto file = MTP_inputFile( - MTP_long(uploadingData.file->id), + MTP_long(uploadingData.id()), MTP_int(uploadingData.partsCount), MTP_string(photoFilename), MTP_bytes(md5)); @@ -416,30 +487,34 @@ void Uploader::sendNext() { .options = options, .edit = edit, }); - } else if (uploadingData.file->type == SendMediaType::File - || uploadingData.file->type == SendMediaType::ThemeFile - || uploadingData.file->type == SendMediaType::Audio) { + } else if (uploadingData.type() == SendMediaType::File + || uploadingData.type() == SendMediaType::ThemeFile + || uploadingData.type() == SendMediaType::Audio) { QByteArray docMd5(32, Qt::Uninitialized); hashMd5Hex(uploadingData.md5Hash.result(), docMd5.data()); const auto file = (uploadingData.docSize > kUseBigFilesFrom) ? MTP_inputFileBig( - MTP_long(uploadingData.file->id), + MTP_long(uploadingData.id()), MTP_int(uploadingData.docPartsCount), - MTP_string(uploadingData.file->filename)) + MTP_string(uploadingData.filename())) : MTP_inputFile( - MTP_long(uploadingData.file->id), + MTP_long(uploadingData.id()), MTP_int(uploadingData.docPartsCount), - MTP_string(uploadingData.file->filename), + MTP_string(uploadingData.filename()), MTP_bytes(docMd5)); const auto thumb = [&]() -> std::optional { if (!uploadingData.partsCount) { return std::nullopt; } - const auto thumbFilename = uploadingData.file->thumbname; - const auto thumbMd5 = uploadingData.file->thumbmd5; + const auto thumbFilename = uploadingData.file + ? uploadingData.file->thumbname + : (u"thumb."_q + uploadingData.media.thumbExt); + const auto thumbMd5 = uploadingData.file + ? uploadingData.file->thumbmd5 + : uploadingData.media.jpeg_md5; return MTP_inputFile( - MTP_long(uploadingData.file->thumbId), + MTP_long(uploadingData.thumbId()), MTP_int(uploadingData.partsCount), MTP_string(thumbFilename), MTP_bytes(thumbMd5)); @@ -454,10 +529,10 @@ void Uploader::sendNext() { .options = options, .edit = edit, }); - } else if (uploadingData.file->type == SendMediaType::Secure) { + } else if (uploadingData.type() == SendMediaType::Secure) { _secureReady.fire({ uploadingId, - uploadingData.file->id, + uploadingData.id(), uploadingData.partsCount }); } queue.erase(uploadingId); @@ -467,11 +542,15 @@ void Uploader::sendNext() { return; } - auto &content = uploadingData.file->content; + auto &content = uploadingData.file + ? uploadingData.file->content + : uploadingData.media.data; QByteArray toSend; if (content.isEmpty()) { if (!uploadingData.docFile) { - const auto filepath = uploadingData.file->filepath; + const auto filepath = uploadingData.file + ? uploadingData.file->filepath + : uploadingData.media.file; uploadingData.docFile = std::make_unique(filepath); if (!uploadingData.docFile->open(QIODevice::ReadOnly)) { currentFailed(); @@ -486,9 +565,9 @@ void Uploader::sendNext() { const auto offset = uploadingData.docSentParts * uploadingData.docPartSize; toSend = content.mid(offset, uploadingData.docPartSize); - if ((uploadingData.file->type == SendMediaType::File - || uploadingData.file->type == SendMediaType::ThemeFile - || uploadingData.file->type == SendMediaType::Audio) + if ((uploadingData.type() == SendMediaType::File + || uploadingData.type() == SendMediaType::ThemeFile + || uploadingData.type() == SendMediaType::Audio) && uploadingData.docSentParts <= kUseBigFilesFrom) { uploadingData.md5Hash.feed(toSend.constData(), toSend.size()); } @@ -502,7 +581,7 @@ void Uploader::sendNext() { mtpRequestId requestId; if (uploadingData.docSize > kUseBigFilesFrom) { requestId = _api->request(MTPupload_SaveBigFilePart( - MTP_long(uploadingData.file->id), + MTP_long(uploadingData.id()), MTP_int(uploadingData.docSentParts), MTP_int(uploadingData.docPartsCount), MTP_bytes(toSend) @@ -513,7 +592,7 @@ void Uploader::sendNext() { }).toDC(MTP::uploadDcId(todc)).send(); } else { requestId = _api->request(MTPupload_SaveFilePart( - MTP_long(uploadingData.file->id), + MTP_long(uploadingData.id()), MTP_int(uploadingData.docSentParts), MTP_bytes(toSend) )).done([=](const MTPBool &result, mtpRequestId requestId) { @@ -644,18 +723,18 @@ void Uploader::partLoaded(const MTPBool &result, mtpRequestId requestId) { } sentSize -= sentPartSize; sentSizes[dc] -= sentPartSize; - if (file.file->type == SendMediaType::Photo) { + if (file.type() == SendMediaType::Photo) { file.fileSentSize += sentPartSize; - const auto photo = session().data().photo(file.file->id); + const auto photo = session().data().photo(file.id()); if (photo->uploading() && file.file) { photo->uploadingData->size = file.file->partssize; photo->uploadingData->offset = file.fileSentSize; } _photoProgress.fire_copy(fullId); - } else if (file.file->type == SendMediaType::File - || file.file->type == SendMediaType::ThemeFile - || file.file->type == SendMediaType::Audio) { - const auto document = session().data().document(file.file->id); + } else if (file.type() == SendMediaType::File + || file.type() == SendMediaType::ThemeFile + || file.type() == SendMediaType::Audio) { + const auto document = session().data().document(file.id()); if (document->uploading()) { const auto doneParts = file.docSentParts - int(docRequestsSent.size()); @@ -664,7 +743,7 @@ void Uploader::partLoaded(const MTPBool &result, mtpRequestId requestId) { doneParts * file.docPartSize); } _documentProgress.fire_copy(fullId); - } else if (file.file->type == SendMediaType::Secure) { + } else if (file.type() == SendMediaType::Secure) { file.fileSentSize += sentPartSize; _secureProgress.fire_copy({ fullId, diff --git a/Telegram/SourceFiles/storage/file_upload.h b/Telegram/SourceFiles/storage/file_upload.h index 4347e5c03..2e68307b9 100644 --- a/Telegram/SourceFiles/storage/file_upload.h +++ b/Telegram/SourceFiles/storage/file_upload.h @@ -12,7 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/facade.h" class ApiWrap; -struct FilePrepareResult; +struct FileLoadResult; +struct SendMediaReady; namespace Api { enum class SendProgressType; @@ -57,9 +58,10 @@ public: return uploadingId; } + void uploadMedia(const FullMsgId &msgId, const SendMediaReady &image); void upload( const FullMsgId &msgId, - const std::shared_ptr &file); + const std::shared_ptr &file); void cancel(const FullMsgId &msgId); void pause(const FullMsgId &msgId); diff --git a/Telegram/SourceFiles/storage/localimageloader.cpp b/Telegram/SourceFiles/storage/localimageloader.cpp index 192c7c112..c26b68458 100644 --- a/Telegram/SourceFiles/storage/localimageloader.cpp +++ b/Telegram/SourceFiles/storage/localimageloader.cpp @@ -222,6 +222,42 @@ int PhotoSideLimit() { return PhotoSideLimit(SendLargePhotos.value()); } +SendMediaReady::SendMediaReady( + SendMediaType type, + const QString &file, + const QString &filename, + int64 filesize, + const QByteArray &data, + const uint64 &id, + const uint64 &thumbId, + const QString &thumbExt, + const PeerId &peer, + const MTPPhoto &photo, + const PreparedPhotoThumbs &photoThumbs, + const MTPDocument &document, + const QByteArray &jpeg) +: type(type) +, file(file) +, filename(filename) +, filesize(filesize) +, data(data) +, thumbExt(thumbExt) +, id(id) +, thumbId(thumbId) +, peer(peer) +, photo(photo) +, document(document) +, photoThumbs(photoThumbs) { + if (!jpeg.isEmpty()) { + int32 size = jpeg.size(); + for (int32 i = 0, part = 0; i < size; i += kPhotoUploadPartSize, ++part) { + parts.insert(part, jpeg.mid(i, kPhotoUploadPartSize)); + } + jpeg_md5.resize(32); + hashMd5Hex(jpeg.constData(), jpeg.size(), jpeg_md5.data()); + } +} + TaskQueue::TaskQueue(crl::time stopTimeoutMs) { if (stopTimeoutMs > 0) { _stopTimer = new QTimer(this); @@ -419,17 +455,22 @@ SendingAlbum::Item::Item(TaskId taskId) : taskId(taskId) { } -FilePrepareResult::FilePrepareResult(FilePrepareDescriptor &&descriptor) -: taskId(descriptor.taskId) -, id(descriptor.id) -, to(std::move(descriptor.to)) -, album(std::move(descriptor.album)) -, type(descriptor.type) -, caption(std::move(descriptor.caption)) -, spoiler(descriptor.spoiler) { +FileLoadResult::FileLoadResult( + TaskId taskId, + uint64 id, + const FileLoadTo &to, + const TextWithTags &caption, + bool spoiler, + std::shared_ptr album) +: taskId(taskId) +, id(id) +, to(to) +, album(std::move(album)) +, caption(caption) +, spoiler(spoiler) { } -void FilePrepareResult::setFileData(const QByteArray &filedata) { +void FileLoadResult::setFileData(const QByteArray &filedata) { if (filedata.isEmpty()) { partssize = 0; } else { @@ -442,7 +483,7 @@ void FilePrepareResult::setFileData(const QByteArray &filedata) { } } -void FilePrepareResult::setThumbData(const QByteArray &thumbdata) { +void FileLoadResult::setThumbData(const QByteArray &thumbdata) { if (!thumbdata.isEmpty()) { thumbbytes = thumbdata; int32 size = thumbdata.size(); @@ -454,11 +495,6 @@ void FilePrepareResult::setThumbData(const QByteArray &thumbdata) { } } -std::shared_ptr MakePreparedFile( - FilePrepareDescriptor &&descriptor) { - return std::make_shared(std::move(descriptor)); -} - FileLoadTask::FileLoadTask( not_null session, const QString &filepath, @@ -674,14 +710,13 @@ bool FileLoadTask::FillImageInformation( } void FileLoadTask::process(Args &&args) { - _result = MakePreparedFile({ - .taskId = id(), - .id = _id, - .to = _to, - .caption = _caption, - .spoiler = _spoiler, - .album = _album, - }); + _result = std::make_shared( + id(), + _id, + _to, + _caption, + _spoiler, + _album); QString filename, filemime; qint64 filesize = 0; @@ -1027,7 +1062,7 @@ void FileLoadTask::finish() { } } -FilePrepareResult *FileLoadTask::peekResult() const { +FileLoadResult *FileLoadTask::peekResult() const { return _result.get(); } diff --git a/Telegram/SourceFiles/storage/localimageloader.h b/Telegram/SourceFiles/storage/localimageloader.h index 8b3b7bca7..d2e64b536 100644 --- a/Telegram/SourceFiles/storage/localimageloader.h +++ b/Telegram/SourceFiles/storage/localimageloader.h @@ -36,8 +36,43 @@ enum class SendMediaType { Secure, }; +using UploadFileParts = QMap; +struct SendMediaReady { + SendMediaReady() = default; // temp + SendMediaReady( + SendMediaType type, + const QString &file, + const QString &filename, + int64 filesize, + const QByteArray &data, + const uint64 &id, + const uint64 &thumbId, + const QString &thumbExt, + const PeerId &peer, + const MTPPhoto &photo, + const PreparedPhotoThumbs &photoThumbs, + const MTPDocument &document, + const QByteArray &jpeg); + + SendMediaType type; + QString file, filename; + int64 filesize = 0; + QByteArray data; + QString thumbExt; + uint64 id, thumbId; // id always file-id of media, thumbId is file-id of thumb ( == id for photos) + PeerId peer; + + MTPPhoto photo; + MTPDocument document; + PreparedPhotoThumbs photoThumbs; + UploadFileParts parts; + QByteArray jpeg_md5; + + QString caption; + +}; + using TaskId = void*; // no interface, just id -inline constexpr auto kEmptyTaskId = TaskId(); class Task { public: @@ -109,7 +144,7 @@ struct SendingAlbum { struct Item { explicit Item(TaskId taskId); - TaskId taskId = kEmptyTaskId; + TaskId taskId; uint64 randomId = 0; FullMsgId msgId; std::optional media; @@ -147,21 +182,17 @@ struct FileLoadTo { MsgId replaceMediaOf; }; -using UploadFileParts = QMap; -struct FilePrepareDescriptor { - TaskId taskId = kEmptyTaskId; - base::required id; - SendMediaType type = SendMediaType::File; - FileLoadTo to = { PeerId(), Api::SendOptions(), FullReplyTo(), MsgId() }; - TextWithTags caption; - bool spoiler = false; - std::shared_ptr album; -}; -struct FilePrepareResult { - explicit FilePrepareResult(FilePrepareDescriptor &&descriptor); +struct FileLoadResult { + FileLoadResult( + TaskId taskId, + uint64 id, + const FileLoadTo &to, + const TextWithTags &caption, + bool spoiler, + std::shared_ptr album); - TaskId taskId = kEmptyTaskId; - uint64 id = 0; + TaskId taskId; + uint64 id; FileLoadTo to; std::shared_ptr album; SendMediaType type = SendMediaType::File; @@ -185,8 +216,8 @@ struct FilePrepareResult { QImage goodThumbnail; QByteArray goodThumbnailBytes; - MTPPhoto photo = MTP_photoEmpty(MTP_long(0)); - MTPDocument document = MTP_documentEmpty(MTP_long(0)); + MTPPhoto photo; + MTPDocument document; PreparedPhotoThumbs photoThumbs; TextWithTags caption; @@ -199,9 +230,6 @@ struct FilePrepareResult { }; -[[nodiscard]] std::shared_ptr MakePreparedFile( - FilePrepareDescriptor &&descriptor); - class FileLoadTask final : public Task { public: static std::unique_ptr ReadMediaInformation( @@ -248,7 +276,7 @@ public: } void finish() override; - FilePrepareResult *peekResult() const; + FileLoadResult *peekResult() const; private: static bool CheckForSong( @@ -284,6 +312,6 @@ private: TextWithTags _caption; bool _spoiler = false; - std::shared_ptr _result; + std::shared_ptr _result; }; diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index b225b321e..7409a95ee 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -585,11 +585,11 @@ void ChatBackground::checkUploadWallPaper() { } const auto ready = PrepareWallPaper(_session->mainDcId(), _original); - const auto documentId = ready->id; + const auto documentId = ready.id; _wallPaperUploadId = FullMsgId( _session->userPeerId(), _session->data().nextLocalMessageId()); - _session->uploader().upload(_wallPaperUploadId, ready); + _session->uploader().uploadMedia(_wallPaperUploadId, ready); if (_wallPaperUploadLifetime) { return; } @@ -1529,9 +1529,7 @@ bool ReadPaletteValues(const QByteArray &content, Fn PrepareWallPaper( - MTP::DcId dcId, - const QImage &image) { +SendMediaReady PrepareWallPaper(MTP::DcId dcId, const QImage &image) { PreparedPhotoThumbs thumbnails; QVector sizes; @@ -1557,7 +1555,6 @@ std::shared_ptr PrepareWallPaper( }; push("s", scaled(320)); - const auto id = base::RandomValue(); const auto filename = u"wallpaper.jpg"_q; auto attributes = QVector( 1, @@ -1565,20 +1562,8 @@ std::shared_ptr PrepareWallPaper( attributes.push_back(MTP_documentAttributeImageSize( MTP_int(image.width()), MTP_int(image.height()))); - - auto result = MakePreparedFile({ - .id = id, - .type = SendMediaType::ThemeFile, - }); - result->filename = filename; - result->content = jpeg; - result->filesize = jpeg.size(); - result->setFileData(jpeg); - if (thumbnails.empty()) { - result->thumb = thumbnails.front().second.image; - result->thumbbytes = thumbnails.front().second.bytes; - } - result->document = MTP_document( + const auto id = base::RandomValue(); + const auto document = MTP_document( MTP_flags(0), MTP_long(id), MTP_long(0), @@ -1590,7 +1575,21 @@ std::shared_ptr PrepareWallPaper( MTPVector(), MTP_int(dcId), MTP_vector(attributes)); - return result; + + return SendMediaReady( + SendMediaType::ThemeFile, + QString(), // filepath + filename, + jpeg.size(), + jpeg, + id, + 0, + QString(), + PeerId(), + MTP_photoEmpty(MTP_long(0)), + thumbnails, + document, + QByteArray()); } std::unique_ptr DefaultChatThemeOn(rpl::lifetime &lifetime) { diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index b0497fb0c..1425e4d07 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/style/style_core_palette.h" class QFileSystemWatcher; -struct FilePrepareResult; +struct SendMediaReady; namespace style { struct colorizer; @@ -298,7 +298,7 @@ private: }; -[[nodiscard]] std::shared_ptr PrepareWallPaper( +[[nodiscard]] SendMediaReady PrepareWallPaper( MTP::DcId dcId, const QImage &image); diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp index c430b3e28..d448ca185 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp @@ -385,7 +385,7 @@ bool CopyColorsToPalette( }); } -std::shared_ptr PrepareThemeMedia( +SendMediaReady PrepareThemeMedia( MTP::DcId dcId, const QString &name, const QByteArray &content) { @@ -403,29 +403,28 @@ std::shared_ptr PrepareThemeMedia( thumbnail.save(&buffer, "JPG", 87); } - sizes.push_back(MTP_photoSize( - MTP_string("s"), - MTP_int(thumbnail.width()), - MTP_int(thumbnail.height()), MTP_int(0))); + const auto push = [&]( + const char *type, + QImage &&image, + QByteArray bytes = QByteArray()) { + sizes.push_back(MTP_photoSize( + MTP_string(type), + MTP_int(image.width()), + MTP_int(image.height()), MTP_int(0))); + thumbnails.emplace(type[0], PreparedPhotoThumb{ + .image = std::move(image), + .bytes = std::move(bytes) + }); + }; + push("s", std::move(thumbnail), thumbnailBytes); - const auto id = base::RandomValue(); const auto filename = base::FileNameFromUserString(name) + u".tdesktop-theme"_q; auto attributes = QVector( 1, MTP_documentAttributeFilename(MTP_string(filename))); - - auto result = MakePreparedFile({ - .id = id, - .type = SendMediaType::ThemeFile, - }); - result->filename = filename; - result->content = content; - result->filesize = content.size(); - result->thumb = thumbnail; - result->thumbname = "thumb.jpg"; - result->setThumbData(thumbnailBytes); - result->document = MTP_document( + const auto id = base::RandomValue(); + const auto document = MTP_document( MTP_flags(0), MTP_long(id), MTP_long(0), @@ -437,7 +436,21 @@ std::shared_ptr PrepareThemeMedia( MTPVector(), MTP_int(dcId), MTP_vector(attributes)); - return result; + + return SendMediaReady( + SendMediaType::ThemeFile, + QString(), // filepath + filename, + content.size(), + content, + id, + 0, + QString(), + PeerId(), + MTP_photoEmpty(MTP_long(0)), + thumbnails, + document, + thumbnailBytes); } Fn SavePreparedTheme( @@ -557,7 +570,7 @@ Fn SavePreparedTheme( session->mainDcId(), fields.title, theme); - state->filename = media->filename; + state->filename = media.filename; state->themeContent = theme; session->uploader().documentReady( @@ -567,7 +580,7 @@ Fn SavePreparedTheme( uploadTheme(data); }, state->lifetime); - session->uploader().upload(state->id, media); + session->uploader().uploadMedia(state->id, media); }; const auto save = [=] { @@ -986,15 +999,12 @@ ParsedTheme ParseTheme( [[nodiscard]] QString GenerateSlug() { const auto letters = uint8('Z' + 1 - 'A'); const auto digits = uint8('9' + 1 - '0'); - const auto firstValues = uint8(2 * letters); const auto values = uint8(2 * letters + digits); auto result = QString(); result.reserve(kRandomSlugSize); for (auto i = 0; i != kRandomSlugSize; ++i) { - const auto value = i - ? (base::RandomValue() % values) - : (base::RandomValue() % firstValues); + const auto value = base::RandomValue() % values; if (value < letters) { result.append(char('A' + value)); } else if (value < 2 * letters) {