mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-11 08:48:14 +00:00
new image / file confirm / send codepath made by Task / TaskQueue, sending single file paste and image paste / drop with that new code
This commit is contained in:
parent
c606d6b459
commit
31b1ecb11c
@ -676,6 +676,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
"lng_really_send_file" = "Do you want to send this file?";
|
||||
"lng_really_share_contact" = "Do you want to share this contact?";
|
||||
"lng_send_image_compressed" = "Send compressed image";
|
||||
"lng_send_image_empty" = "Could not send an empty file :(";
|
||||
"lng_send_image_too_large" = "Could not send a file, because it is larger than 1.5 GB :(";
|
||||
|
||||
"lng_forward_choose" = "Choose recipient..";
|
||||
"lng_forward_cant" = "Sorry, no way to forward here :(";
|
||||
|
@ -515,7 +515,7 @@ void Application::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId)
|
||||
int32 filesize = 0;
|
||||
QByteArray data;
|
||||
|
||||
ReadyLocalMedia ready(ToPreparePhoto, file, filename, filesize, data, id, id, qsl("jpg"), peerId, photo, MTP_audioEmpty(MTP_long(0)), photoThumbs, MTP_documentEmpty(MTP_long(0)), jpeg, false, false, 0);
|
||||
ReadyLocalMedia ready(PreparePhoto, file, filename, filesize, data, id, id, qsl("jpg"), peerId, photo, MTP_audioEmpty(MTP_long(0)), photoThumbs, MTP_documentEmpty(MTP_long(0)), jpeg, false, false, 0);
|
||||
|
||||
connect(App::uploader(), SIGNAL(photoReady(const FullMsgId&, const MTPInputFile&)), App::app(), SLOT(photoUpdated(const FullMsgId&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
|
||||
|
@ -27,6 +27,92 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
#include "mainwidget.h"
|
||||
#include "photosendbox.h"
|
||||
|
||||
PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxWideWidth)
|
||||
, _file(file)
|
||||
, _img(0)
|
||||
, _thumbx(0)
|
||||
, _thumby(0)
|
||||
, _thumbw(0)
|
||||
, _thumbh(0)
|
||||
, _namew(0)
|
||||
, _textw(0)
|
||||
, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption))
|
||||
, _compressed(this, lang(lng_send_image_compressed), cCompressPastedImage())
|
||||
, _send(this, lang(lng_send_button), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _replyTo(_file->to.replyTo) {
|
||||
connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
if (_file->photo.type() != mtpc_photoEmpty) {
|
||||
_file->type = PreparePhoto;
|
||||
}
|
||||
if (_file->type == PreparePhoto) {
|
||||
int32 maxW = 0, maxH = 0;
|
||||
for (PreparedPhotoThumbs::const_iterator i = _file->photoThumbs.cbegin(), e = _file->photoThumbs.cend(); i != e; ++i) {
|
||||
if (i->width() >= maxW && i->height() >= maxH) {
|
||||
_thumb = *i;
|
||||
maxW = _thumb.width();
|
||||
maxH = _thumb.height();
|
||||
}
|
||||
}
|
||||
int32 tw = _thumb.width(), th = _thumb.height();
|
||||
if (!tw || !th) {
|
||||
tw = th = 1;
|
||||
}
|
||||
_thumbw = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
if (_thumb.width() < _thumbw) {
|
||||
_thumbw = (_thumb.width() > 20) ? _thumb.width() : 20;
|
||||
}
|
||||
int32 maxthumbh = qMin(qRound(1.5 * _thumbw), int(st::confirmMaxHeight));
|
||||
_thumbh = qRound(th * float64(_thumbw) / tw);
|
||||
if (_thumbh > maxthumbh) {
|
||||
_thumbw = qRound(_thumbw * float64(maxthumbh) / _thumbh);
|
||||
_thumbh = maxthumbh;
|
||||
if (_thumbw < 10) {
|
||||
_thumbw = 10;
|
||||
}
|
||||
}
|
||||
_thumbx = (width() - _thumbw) / 2;
|
||||
|
||||
_thumb = QPixmap::fromImage(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
|
||||
_thumb.setDevicePixelRatio(cRetinaFactor());
|
||||
} else {
|
||||
_compressed.hide();
|
||||
if (!_file->thumb.isNull()) {
|
||||
_thumb = _file->thumb;
|
||||
int32 tw = _thumb.width(), th = _thumb.height();
|
||||
if (_thumb.isNull() || !tw || !th) {
|
||||
_thumbw = _thumbx = _thumby = 0;
|
||||
} else if (tw > th) {
|
||||
_thumbw = (tw * st::mediaThumbSize) / th;
|
||||
_thumbx = (_thumbw - st::mediaThumbSize) / 2;
|
||||
_thumby = 0;
|
||||
} else {
|
||||
_thumbw = st::mediaThumbSize;
|
||||
_thumbx = 0;
|
||||
_thumby = ((th * _thumbw) / tw - st::mediaThumbSize) / 2;
|
||||
}
|
||||
}
|
||||
if (_thumbw) {
|
||||
_thumb = QPixmap::fromImage(_thumb.toImage().scaledToWidth(_thumbw * cIntRetinaFactor(), Qt::SmoothTransformation), Qt::ColorOnly);
|
||||
_thumb.setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
|
||||
_name = _file->filename;
|
||||
_namew = st::mediaFont->width(_name);
|
||||
_size = formatSizeText(_file->filesize);
|
||||
_textw = qMax(_namew, st::mediaFont->width(_size));
|
||||
}
|
||||
updateBoxSize();
|
||||
_caption.setMaxLength(MaxPhotoCaption);
|
||||
_caption.setCtrlEnterSubmit(CtrlEnterSubmitBoth);
|
||||
connect(&_compressed, SIGNAL(changed()), this, SLOT(onCompressedChange()));
|
||||
connect(&_caption, SIGNAL(resized()), this, SLOT(onCaptionResized()));
|
||||
connect(&_caption, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
|
||||
connect(&_caption, SIGNAL(cancelled()), this, SLOT(onClose()));
|
||||
prepare();
|
||||
}
|
||||
|
||||
PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : AbstractBox(st::boxWideWidth)
|
||||
, _img(new ReadyLocalMedia(img))
|
||||
, _thumbx(0)
|
||||
@ -43,7 +129,7 @@ PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : AbstractBox(st::boxWide
|
||||
connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
|
||||
if (_img->type == ToPreparePhoto) {
|
||||
if (_img->type == PreparePhoto) {
|
||||
int32 maxW = 0, maxH = 0;
|
||||
for (PreparedPhotoThumbs::const_iterator i = _img->photoThumbs.cbegin(), e = _img->photoThumbs.cend(); i != e; ++i) {
|
||||
if (i->width() >= maxW && i->height() >= maxH) {
|
||||
@ -156,7 +242,7 @@ void PhotoSendBox::onCaptionResized() {
|
||||
}
|
||||
|
||||
void PhotoSendBox::updateBoxSize() {
|
||||
if (_img && _img->type == ToPreparePhoto) {
|
||||
if ((_file && _file->type == PreparePhoto) || (_img && _img->type == PreparePhoto)) {
|
||||
setMaxHeight(st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + st::boxPhotoCompressedPadding.top() + _compressed.height() + (_compressed.checked() ? (st::boxPhotoCompressedPadding.bottom() + _caption.height()) : 0) + st::boxButtonPadding.top() + _send.height() + st::boxButtonPadding.bottom());
|
||||
} else {
|
||||
setMaxHeight(st::boxPhotoPadding.top() + st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom() + st::boxPhotoPadding.bottom() + st::boxButtonPadding.top() + _send.height() + st::boxButtonPadding.bottom());
|
||||
@ -175,7 +261,7 @@ void PhotoSendBox::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
if (paint(p)) return;
|
||||
|
||||
if (_img && _img->type == ToPreparePhoto) {
|
||||
if ((_file && _file->type == PreparePhoto) || (_img && _img->type == PreparePhoto)) {
|
||||
if (_thumbx > st::boxPhotoPadding.left()) {
|
||||
p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg->b);
|
||||
}
|
||||
@ -197,7 +283,7 @@ void PhotoSendBox::paintEvent(QPaintEvent *e) {
|
||||
if (_thumbw) {
|
||||
int32 rf(cIntRetinaFactor());
|
||||
p.drawPixmap(QPoint(x + st::mediaPadding.left(), y + st::mediaPadding.top()), _thumb, QRect(_thumbx * rf, _thumby * rf, st::mediaThumbSize * rf, st::mediaThumbSize * rf));
|
||||
} else if (_img) {
|
||||
} else if (_file || _img) {
|
||||
p.drawPixmap(QPoint(x + st::mediaPadding.left(), y + st::mediaPadding.top()), App::sprite(), st::mediaDocOutImg);
|
||||
} else {
|
||||
p.drawPixmap(x + st::mediaPadding.left(), y + st::mediaPadding.top(), userDefPhoto(1)->pix(st::mediaThumbSize));
|
||||
@ -225,7 +311,13 @@ void PhotoSendBox::resizeEvent(QResizeEvent *e) {
|
||||
}
|
||||
|
||||
void PhotoSendBox::closePressed() {
|
||||
if (App::main()) App::main()->cancelSendImage();
|
||||
if (App::main()) {
|
||||
if (_file) {
|
||||
App::main()->onSendFileCancel(_file);
|
||||
} else {
|
||||
App::main()->cancelSendImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhotoSendBox::hideAll() {
|
||||
@ -238,7 +330,7 @@ void PhotoSendBox::hideAll() {
|
||||
void PhotoSendBox::showAll() {
|
||||
_send.show();
|
||||
_cancel.show();
|
||||
if (_img && _img->type == ToPreparePhoto) {
|
||||
if ((_file && _file->type == PreparePhoto) || (_img && _img->type == PreparePhoto)) {
|
||||
_compressed.show();
|
||||
if (_compressed.checked()) {
|
||||
_caption.show();
|
||||
@ -256,6 +348,30 @@ void PhotoSendBox::showDone() {
|
||||
}
|
||||
|
||||
void PhotoSendBox::onSend(bool ctrlShiftEnter) {
|
||||
if (_file) {
|
||||
if (_compressed.isHidden()) {
|
||||
if (_file->type == PrepareAuto) {
|
||||
_file->type = PrepareDocument;
|
||||
}
|
||||
} else {
|
||||
if (_compressed.checked() != cCompressPastedImage()) {
|
||||
cSetCompressPastedImage(_compressed.checked());
|
||||
Local::writeUserSettings();
|
||||
}
|
||||
if (_compressed.checked()) {
|
||||
_file->type = PreparePhoto;
|
||||
} else {
|
||||
_file->type = PrepareDocument;
|
||||
}
|
||||
}
|
||||
if (!_caption.isHidden()) {
|
||||
_file->photoCaption = prepareText(_caption.getLastText(), true);
|
||||
}
|
||||
if (App::main()) App::main()->onSendFileConfirm(_file, ctrlShiftEnter);
|
||||
onClose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_img) {
|
||||
if (App::main()) App::main()->confirmShareContact(ctrlShiftEnter, _phone, _fname, _lname, _replyTo);
|
||||
} else {
|
||||
|
@ -28,6 +28,7 @@ class PhotoSendBox : public AbstractBox {
|
||||
|
||||
public:
|
||||
|
||||
PhotoSendBox(const FileLoadResultPtr &file);
|
||||
PhotoSendBox(const ReadyLocalMedia &img);
|
||||
PhotoSendBox(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
@ -47,6 +48,7 @@ public:
|
||||
signals:
|
||||
|
||||
void confirmed();
|
||||
void cancelled();
|
||||
|
||||
public slots:
|
||||
|
||||
@ -65,6 +67,7 @@ private:
|
||||
|
||||
void updateBoxSize();
|
||||
|
||||
FileLoadResultPtr _file;
|
||||
ReadyLocalMedia *_img;
|
||||
int32 _thumbx, _thumby, _thumbw, _thumbh;
|
||||
QString _name, _size;
|
||||
|
@ -312,9 +312,11 @@ enum {
|
||||
MessagesFirstLoad = 30, // first history part size requested
|
||||
MessagesPerPage = 50, // next history part size
|
||||
|
||||
FileLoaderQueueStopTimeout = 5000,
|
||||
|
||||
DownloadPartSize = 64 * 1024, // 64kb for photo
|
||||
DocumentDownloadPartSize = 128 * 1024, // 128kb for document
|
||||
MaxUploadPhotoSize = 32 * 1024 * 1024, // 32mb photos max
|
||||
MaxUploadPhotoSize = 256 * 1024 * 1024, // 256mb photos max
|
||||
MaxUploadDocumentSize = 1500 * 1024 * 1024, // 1500mb documents max
|
||||
UseBigFilesFrom = 10 * 1024 * 1024, // mtp big files methods used for files greater than 10mb
|
||||
MaxFileQueries = 16, // max 16 file parts downloaded at the same time
|
||||
|
@ -30,9 +30,9 @@ FileUploader::FileUploader() : sentSize(0) {
|
||||
}
|
||||
|
||||
void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &media) {
|
||||
if (media.type == ToPreparePhoto) {
|
||||
if (media.type == PreparePhoto) {
|
||||
App::feedPhoto(media.photo, media.photoThumbs);
|
||||
} else if (media.type == ToPrepareDocument) {
|
||||
} else if (media.type == PrepareDocument) {
|
||||
DocumentData *document;
|
||||
if (media.photoThumbs.isEmpty()) {
|
||||
document = App::feedDocument(media.document);
|
||||
@ -43,7 +43,7 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
|
||||
if (!media.file.isEmpty()) {
|
||||
document->location = FileLocation(StorageFilePartial, media.file);
|
||||
}
|
||||
} else if (media.type == ToPrepareAudio) {
|
||||
} else if (media.type == PrepareAudio) {
|
||||
AudioData *audio = App::feedAudio(media.audio);
|
||||
audio->status = FileUploading;
|
||||
audio->data = media.data;
|
||||
@ -52,19 +52,42 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
|
||||
sendNext();
|
||||
}
|
||||
|
||||
void FileUploader::uploadFile(const FullMsgId &msgId, const FileLoadResultPtr &file) {
|
||||
if (file->type == PreparePhoto) {
|
||||
App::feedPhoto(file->photo, file->photoThumbs);
|
||||
} else if (file->type == PrepareDocument) {
|
||||
DocumentData *document;
|
||||
if (file->thumb.isNull()) {
|
||||
document = App::feedDocument(file->document);
|
||||
} else {
|
||||
document = App::feedDocument(file->document, file->thumb);
|
||||
}
|
||||
document->status = FileUploading;
|
||||
if (!file->filepath.isEmpty()) {
|
||||
document->location = FileLocation(StorageFilePartial, file->filepath);
|
||||
}
|
||||
} else if (file->type == PrepareAudio) {
|
||||
AudioData *audio = App::feedAudio(file->audio);
|
||||
audio->status = FileUploading;
|
||||
audio->data = file->content;
|
||||
}
|
||||
queue.insert(msgId, File(file));
|
||||
sendNext();
|
||||
}
|
||||
|
||||
void FileUploader::currentFailed() {
|
||||
Queue::iterator j = queue.find(uploading);
|
||||
if (j != queue.end()) {
|
||||
if (j->media.type == ToPreparePhoto) {
|
||||
if (j->type() == PreparePhoto) {
|
||||
emit photoFailed(j.key());
|
||||
} else if (j->media.type == ToPrepareDocument) {
|
||||
DocumentData *doc = App::document(j->media.id);
|
||||
} else if (j->type() == PrepareDocument) {
|
||||
DocumentData *doc = App::document(j->id());
|
||||
if (doc->status == FileUploading) {
|
||||
doc->status = FileFailed;
|
||||
}
|
||||
emit documentFailed(j.key());
|
||||
} else if (j->media.type == ToPrepareAudio) {
|
||||
AudioData *audio = App::audio(j->media.id);
|
||||
} else if (j->type() == PrepareAudio) {
|
||||
AudioData *audio = App::audio(j->id());
|
||||
if (audio->status == FileUploading) {
|
||||
audio->status = FileFailed;
|
||||
}
|
||||
@ -118,26 +141,29 @@ void FileUploader::sendNext() {
|
||||
todc = dc;
|
||||
}
|
||||
}
|
||||
if (i->media.parts.isEmpty()) {
|
||||
|
||||
UploadFileParts &parts(i->file ? (i->type() == PreparePhoto ? i->file->fileparts : i->file->thumbparts) : i->media.parts);
|
||||
uint64 partsOfId(i->file ? (i->type() == PreparePhoto ? i->file->id : i->file->thumbId) : i->media.thumbId);
|
||||
if (parts.isEmpty()) {
|
||||
if (i->docSentParts >= i->docPartsCount) {
|
||||
if (requestsSent.isEmpty() && docRequestsSent.isEmpty()) {
|
||||
if (i->media.type == ToPreparePhoto) {
|
||||
emit photoReady(uploading, MTP_inputFile(MTP_long(i->media.id), MTP_int(i->partsCount), MTP_string(i->media.filename), MTP_string(i->media.jpeg_md5)));
|
||||
} else if (i->media.type == ToPrepareDocument) {
|
||||
if (i->type() == PreparePhoto) {
|
||||
emit photoReady(uploading, MTP_inputFile(MTP_long(i->id()), MTP_int(i->partsCount), MTP_string(i->filename()), MTP_string(i->file ? i->file->filemd5 : i->media.jpeg_md5)));
|
||||
} else if (i->type() == PrepareDocument) {
|
||||
QByteArray docMd5(32, Qt::Uninitialized);
|
||||
hashMd5Hex(i->md5Hash.result(), docMd5.data());
|
||||
|
||||
MTPInputFile doc = (i->docSize > UseBigFilesFrom) ? MTP_inputFileBig(MTP_long(i->media.id), MTP_int(i->docPartsCount), MTP_string(i->media.filename)) : MTP_inputFile(MTP_long(i->media.id), MTP_int(i->docPartsCount), MTP_string(i->media.filename), MTP_string(docMd5));
|
||||
MTPInputFile doc = (i->docSize > UseBigFilesFrom) ? MTP_inputFileBig(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename())) : MTP_inputFile(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename()), MTP_string(docMd5));
|
||||
if (i->partsCount) {
|
||||
emit thumbDocumentReady(uploading, doc, MTP_inputFile(MTP_long(i->media.thumbId), MTP_int(i->partsCount), MTP_string(qsl("thumb.") + i->media.thumbExt), MTP_string(i->media.jpeg_md5)));
|
||||
emit thumbDocumentReady(uploading, doc, MTP_inputFile(MTP_long(i->thumbId()), MTP_int(i->partsCount), MTP_string(i->file ? i->file->thumbname : (qsl("thumb.") + i->media.thumbExt)), MTP_string(i->file ? i->file->thumbmd5 : i->media.jpeg_md5)));
|
||||
} else {
|
||||
emit documentReady(uploading, doc);
|
||||
}
|
||||
} else if (i->media.type == ToPrepareAudio) {
|
||||
} else if (i->type() == PrepareAudio) {
|
||||
QByteArray audioMd5(32, Qt::Uninitialized);
|
||||
hashMd5Hex(i->md5Hash.result(), audioMd5.data());
|
||||
|
||||
MTPInputFile audio = (i->docSize > UseBigFilesFrom) ? MTP_inputFileBig(MTP_long(i->media.id), MTP_int(i->docPartsCount), MTP_string(i->media.filename)) : MTP_inputFile(MTP_long(i->media.id), MTP_int(i->docPartsCount), MTP_string(i->media.filename), MTP_string(audioMd5));
|
||||
MTPInputFile audio = (i->docSize > UseBigFilesFrom) ? MTP_inputFileBig(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename())) : MTP_inputFile(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename()), MTP_string(audioMd5));
|
||||
emit audioReady(uploading, audio);
|
||||
}
|
||||
queue.remove(uploading);
|
||||
@ -147,10 +173,11 @@ void FileUploader::sendNext() {
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray &content(i->file ? i->file->content : i->media.data);
|
||||
QByteArray toSend;
|
||||
if (i->media.data.isEmpty()) {
|
||||
if (content.isEmpty()) {
|
||||
if (!i->docFile) {
|
||||
i->docFile.reset(new QFile(i->media.file));
|
||||
i->docFile.reset(new QFile(i->file ? i->file->filepath : i->media.file));
|
||||
if (!i->docFile->open(QIODevice::ReadOnly)) {
|
||||
currentFailed();
|
||||
return;
|
||||
@ -161,8 +188,8 @@ void FileUploader::sendNext() {
|
||||
i->md5Hash.feed(toSend.constData(), toSend.size());
|
||||
}
|
||||
} else {
|
||||
toSend = i->media.data.mid(i->docSentParts * i->docPartSize, i->docPartSize);
|
||||
if ((i->media.type == ToPrepareDocument || i->media.type == ToPrepareAudio) && i->docSentParts <= UseBigFilesFrom) {
|
||||
toSend = content.mid(i->docSentParts * i->docPartSize, i->docPartSize);
|
||||
if ((i->type() == PrepareDocument || i->type() == PrepareAudio) && i->docSentParts <= UseBigFilesFrom) {
|
||||
i->md5Hash.feed(toSend.constData(), toSend.size());
|
||||
}
|
||||
}
|
||||
@ -172,9 +199,9 @@ void FileUploader::sendNext() {
|
||||
}
|
||||
mtpRequestId requestId;
|
||||
if (i->docSize > UseBigFilesFrom) {
|
||||
requestId = MTP::send(MTPupload_SaveBigFilePart(MTP_long(i->media.id), MTP_int(i->docSentParts), MTP_int(i->docPartsCount), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
requestId = MTP::send(MTPupload_SaveBigFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_int(i->docPartsCount), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
} else {
|
||||
requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->media.id), MTP_int(i->docSentParts), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
}
|
||||
docRequestsSent.insert(requestId, i->docSentParts);
|
||||
dcMap.insert(requestId, todc);
|
||||
@ -183,15 +210,15 @@ void FileUploader::sendNext() {
|
||||
|
||||
i->docSentParts++;
|
||||
} else {
|
||||
LocalFileParts::iterator part = i->media.parts.begin();
|
||||
UploadFileParts::iterator part = parts.begin();
|
||||
|
||||
mtpRequestId requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->media.thumbId), MTP_int(part.key()), MTP_string(part.value())), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
mtpRequestId requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(partsOfId), MTP_int(part.key()), MTP_string(part.value())), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
requestsSent.insert(requestId, part.value());
|
||||
dcMap.insert(requestId, todc);
|
||||
sentSize += part.value().size();
|
||||
sentSizes[todc] += part.value().size();
|
||||
|
||||
i->media.parts.erase(part);
|
||||
parts.erase(part);
|
||||
}
|
||||
nextTimer.start(UploadRequestInterval);
|
||||
}
|
||||
@ -257,10 +284,10 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
||||
sentSizes[dc] -= k->docPartSize;
|
||||
docRequestsSent.erase(j);
|
||||
}
|
||||
if (k->media.type == ToPreparePhoto) {
|
||||
if (k->type() == PreparePhoto) {
|
||||
emit photoProgress(k.key());
|
||||
} else if (k->media.type == ToPrepareDocument) {
|
||||
DocumentData *doc = App::document(k->media.id);
|
||||
} else if (k->type() == PrepareDocument) {
|
||||
DocumentData *doc = App::document(k->id());
|
||||
if (doc->status == FileUploading) {
|
||||
doc->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
||||
if (doc->uploadOffset > doc->size) {
|
||||
@ -268,8 +295,8 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
||||
}
|
||||
}
|
||||
emit documentProgress(k.key());
|
||||
} else if (k->media.type == ToPrepareAudio) {
|
||||
AudioData *audio = App::audio(k->media.id);
|
||||
} else if (k->type() == PrepareAudio) {
|
||||
AudioData *audio = App::audio(k->id());
|
||||
if (audio->status == FileUploading) {
|
||||
audio->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
||||
if (audio->uploadOffset > audio->size) {
|
||||
|
@ -29,6 +29,7 @@ public:
|
||||
|
||||
FileUploader();
|
||||
void uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &image);
|
||||
void uploadFile(const FullMsgId &msgId, const FileLoadResultPtr &file);
|
||||
|
||||
int32 currentOffset(const FullMsgId &msgId) const; // -1 means file not found
|
||||
int32 fullSize(const FullMsgId &msgId) const;
|
||||
@ -63,21 +64,32 @@ private:
|
||||
struct File {
|
||||
File(const ReadyLocalMedia &media) : media(media), docSentParts(0) {
|
||||
partsCount = media.parts.size();
|
||||
if (media.type == ToPrepareDocument || media.type == ToPrepareAudio) {
|
||||
docSize = media.file.isEmpty() ? media.data.size() : media.filesize;
|
||||
if (docSize >= 1024 * 1024 || !setPartSize(DocumentUploadPartSize0)) {
|
||||
if (docSize > 32 * 1024 * 1024 || !setPartSize(DocumentUploadPartSize1)) {
|
||||
if (!setPartSize(DocumentUploadPartSize2)) {
|
||||
if (!setPartSize(DocumentUploadPartSize3)) {
|
||||
if (!setPartSize(DocumentUploadPartSize4)) {
|
||||
LOG(("Upload Error: bad doc size: %1").arg(docSize));
|
||||
}
|
||||
if (type() == PrepareDocument || type() == PrepareAudio) {
|
||||
setDocSize(media.file.isEmpty() ? media.data.size() : media.filesize);
|
||||
} else {
|
||||
docSize = docPartSize = docPartsCount = 0;
|
||||
}
|
||||
}
|
||||
File(const FileLoadResultPtr &file) : file(file), docSentParts(0) {
|
||||
partsCount = (type() == PreparePhoto) ? file->fileparts.size() : file->thumbparts.size();
|
||||
if (type() == PrepareDocument || type() == PrepareAudio) {
|
||||
setDocSize(file->filesize);
|
||||
} else {
|
||||
docSize = docPartSize = docPartsCount = 0;
|
||||
}
|
||||
}
|
||||
void setDocSize(int32 size) {
|
||||
docSize = size;
|
||||
if (docSize >= 1024 * 1024 || !setPartSize(DocumentUploadPartSize0)) {
|
||||
if (docSize > 32 * 1024 * 1024 || !setPartSize(DocumentUploadPartSize1)) {
|
||||
if (!setPartSize(DocumentUploadPartSize2)) {
|
||||
if (!setPartSize(DocumentUploadPartSize3)) {
|
||||
if (!setPartSize(DocumentUploadPartSize4)) {
|
||||
LOG(("Upload Error: bad doc size: %1").arg(docSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
docSize = docPartSize = docPartsCount = 0;
|
||||
}
|
||||
}
|
||||
bool setPartSize(uint32 partSize) {
|
||||
@ -86,9 +98,23 @@ private:
|
||||
return (docPartsCount <= DocumentMaxPartsCount);
|
||||
}
|
||||
|
||||
FileLoadResultPtr file;
|
||||
ReadyLocalMedia media;
|
||||
int32 partsCount;
|
||||
|
||||
const uint64 &id() const {
|
||||
return file ? file->id : media.id;
|
||||
}
|
||||
PrepareMediaType type() const {
|
||||
return file ? file->type : media.type;
|
||||
}
|
||||
const uint64 &thumbId() const {
|
||||
return file ? file->thumbId : media.thumbId;
|
||||
}
|
||||
const QString &filename() const {
|
||||
return file ? file->filename : media.filename;
|
||||
}
|
||||
|
||||
HashMd5 md5Hash;
|
||||
|
||||
QSharedPointer<QFile> docFile;
|
||||
|
@ -1696,7 +1696,7 @@ void MessageField::insertFromMimeData(const QMimeData *source) {
|
||||
if (source->hasImage()) {
|
||||
QImage img = qvariant_cast<QImage>(source->imageData());
|
||||
if (!img.isNull()) {
|
||||
history->uploadImage(img, false, source->text());
|
||||
history->uploadImage(img, FileLoadAlwaysConfirm, source->text());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2402,11 +2402,13 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
||||
, _attachDrag(DragStateNone)
|
||||
, _attachDragDocument(this)
|
||||
, _attachDragPhoto(this)
|
||||
, _fileLoader(this, FileLoaderQueueStopTimeout)
|
||||
, _imageLoader(this)
|
||||
, _synthedTextUpdate(false)
|
||||
, _serviceImageCacheSize(0)
|
||||
, _confirmImageId(0)
|
||||
, _confirmWithText(false)
|
||||
, _confirmWithTextId(0)
|
||||
, _titlePeerTextWidth(0)
|
||||
, _a_show(animFunc(this, &HistoryWidget::animStep_show))
|
||||
, _scrollDelta(0)
|
||||
@ -2709,7 +2711,7 @@ void HistoryWidget::onRecordDone(QByteArray result, qint32 samples) {
|
||||
|
||||
App::wnd()->activateWindow();
|
||||
int32 duration = samples / AudioVoiceMsgFrequency;
|
||||
_imageLoader.append(result, duration, _peer->id, _broadcast.checked(), replyToId(), ToPrepareAudio);
|
||||
_imageLoader.append(result, duration, _peer->id, _broadcast.checked(), replyToId(), PrepareAudio);
|
||||
cancelReply(lastForceReplyReplied());
|
||||
}
|
||||
|
||||
@ -3989,7 +3991,7 @@ void HistoryWidget::onSendPaths(const PeerId &peer) {
|
||||
App::main()->showPeerHistory(peer, ShowAtTheEndMsgId);
|
||||
if (!_history) return;
|
||||
|
||||
uploadMedias(cSendPaths(), ToPrepareDocument);
|
||||
uploadMedias(cSendPaths(), PrepareDocument);
|
||||
}
|
||||
|
||||
History *HistoryWidget::history() const {
|
||||
@ -4167,11 +4169,11 @@ void HistoryWidget::onPhotoSelect() {
|
||||
QByteArray file;
|
||||
if (filedialogGetOpenFiles(files, file, lang(lng_choose_images), filter)) {
|
||||
if (!file.isEmpty()) {
|
||||
uploadMedia(file, ToPreparePhoto);
|
||||
uploadMedia(file, PreparePhoto);
|
||||
//} else if (files.size() == 1) {
|
||||
// uploadWithConfirm(files.at(0), false, true);
|
||||
} else if (!files.isEmpty()) {
|
||||
uploadMedias(files, ToPreparePhoto);
|
||||
uploadMedias(files, PreparePhoto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4197,11 +4199,11 @@ void HistoryWidget::onDocumentSelect() {
|
||||
QByteArray file;
|
||||
if (filedialogGetOpenFiles(files, file, lang(lng_choose_images), filter)) {
|
||||
if (!file.isEmpty()) {
|
||||
uploadMedia(file, ToPrepareDocument);
|
||||
uploadMedia(file, PrepareDocument);
|
||||
//} else if (files.size() == 1) {
|
||||
// uploadWithConfirm(files.at(0), false, false);
|
||||
} else if (!files.isEmpty()) {
|
||||
uploadMedias(files, ToPrepareDocument);
|
||||
uploadMedias(files, PrepareDocument);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4502,7 +4504,7 @@ void HistoryWidget::onPhotoDrop(const QMimeData *data) {
|
||||
QImage image = qvariant_cast<QImage>(data->imageData());
|
||||
if (image.isNull()) return;
|
||||
|
||||
uploadImage(image, false, data->text());
|
||||
uploadImage(image, FileLoadNoForceConfirm, data->text());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -4510,7 +4512,7 @@ void HistoryWidget::onPhotoDrop(const QMimeData *data) {
|
||||
//if (files.size() == 1) {
|
||||
// uploadWithConfirm(files.at(0), false, true);
|
||||
//} else {
|
||||
uploadMedias(files, ToPreparePhoto);
|
||||
uploadMedias(files, PreparePhoto);
|
||||
//}
|
||||
}
|
||||
|
||||
@ -4523,7 +4525,7 @@ void HistoryWidget::onDocumentDrop(const QMimeData *data) {
|
||||
//if (files.size() == 1) {
|
||||
// uploadWithConfirm(files.at(0), false, false);
|
||||
//} else {
|
||||
uploadMedias(files, ToPrepareDocument);
|
||||
uploadMedias(files, PrepareDocument);
|
||||
//}
|
||||
}
|
||||
|
||||
@ -4534,7 +4536,7 @@ void HistoryWidget::onFilesDrop(const QMimeData *data) {
|
||||
QImage image = qvariant_cast<QImage>(data->imageData());
|
||||
if (image.isNull()) return;
|
||||
|
||||
uploadImage(image, false, data->text());
|
||||
uploadImage(image, FileLoadNoForceConfirm, data->text());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -4542,7 +4544,7 @@ void HistoryWidget::onFilesDrop(const QMimeData *data) {
|
||||
//if (files.size() == 1) {
|
||||
// uploadWithConfirm(files.at(0), false, true);
|
||||
//} else {
|
||||
uploadMedias(files, ToPrepareAuto);
|
||||
uploadMedias(files, PrepareAuto);
|
||||
//}
|
||||
}
|
||||
|
||||
@ -4804,22 +4806,26 @@ void HistoryWidget::onFieldCursorChanged() {
|
||||
onDraftSaveDelayed();
|
||||
}
|
||||
|
||||
void HistoryWidget::uploadImage(const QImage &img, bool withText, const QString &source) {
|
||||
if (!_history || _confirmImageId) return;
|
||||
void HistoryWidget::uploadImage(const QImage &img, FileLoadForceConfirmType confirm, const QString &source, bool withText) {
|
||||
if (!_history) return;
|
||||
|
||||
App::wnd()->activateWindow();
|
||||
_confirmImage = img;
|
||||
_confirmWithText = withText;
|
||||
_confirmSource = source;
|
||||
_confirmImageId = _imageLoader.append(img, _peer->id, _broadcast.checked(), replyToId(), ToPreparePhoto);
|
||||
FileLoadTask *task = new FileLoadTask(img, FileLoadTo(_peer->id, _broadcast.checked(), replyToId()), confirm, source);
|
||||
if (withText) {
|
||||
_confirmWithTextId = task->fileid();
|
||||
}
|
||||
_fileLoader.addTask(task);
|
||||
}
|
||||
|
||||
void HistoryWidget::uploadFile(const QString &file, bool withText) {
|
||||
if (!_history || _confirmImageId) return;
|
||||
void HistoryWidget::uploadFile(const QString &file, FileLoadForceConfirmType confirm, bool withText) {
|
||||
if (!_history) return;
|
||||
|
||||
App::wnd()->activateWindow();
|
||||
_confirmWithText = withText;
|
||||
_confirmImageId = _imageLoader.append(file, _peer->id, _broadcast.checked(), replyToId(), ToPrepareDocument);
|
||||
FileLoadTask *task = new FileLoadTask(file, PrepareAuto, FileLoadTo(_peer->id, _broadcast.checked(), replyToId()), confirm);
|
||||
if (withText) {
|
||||
_confirmWithTextId = task->fileid();
|
||||
}
|
||||
_fileLoader.addTask(task);
|
||||
}
|
||||
|
||||
void HistoryWidget::shareContactConfirmation(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, bool withText) {
|
||||
@ -4840,14 +4846,14 @@ void HistoryWidget::uploadConfirmImageUncompressed(bool ctrlShiftEnter, MsgId re
|
||||
onSend(ctrlShiftEnter, replyTo);
|
||||
}
|
||||
bool lastKeyboardUsed = lastForceReplyReplied(FullMsgId(_channel, replyTo));
|
||||
_imageLoader.append(_confirmImage, peerId, _broadcast.checked(), replyTo, ToPrepareDocument, ctrlShiftEnter);
|
||||
_imageLoader.append(_confirmImage, peerId, _broadcast.checked(), replyTo, PrepareDocument, ctrlShiftEnter);
|
||||
_confirmImageId = 0;
|
||||
_confirmWithText = false;
|
||||
_confirmImage = QImage();
|
||||
cancelReply(lastKeyboardUsed);
|
||||
}
|
||||
|
||||
void HistoryWidget::uploadMedias(const QStringList &files, ToPrepareMediaType type) {
|
||||
void HistoryWidget::uploadMedias(const QStringList &files, PrepareMediaType type) {
|
||||
if (!_history) return;
|
||||
|
||||
App::wnd()->activateWindow();
|
||||
@ -4855,7 +4861,7 @@ void HistoryWidget::uploadMedias(const QStringList &files, ToPrepareMediaType ty
|
||||
cancelReply(lastForceReplyReplied());
|
||||
}
|
||||
|
||||
void HistoryWidget::uploadMedia(const QByteArray &fileContent, ToPrepareMediaType type, PeerId peer) {
|
||||
void HistoryWidget::uploadMedia(const QByteArray &fileContent, PrepareMediaType type, PeerId peer) {
|
||||
if (!peer && !_history) return;
|
||||
|
||||
App::wnd()->activateWindow();
|
||||
@ -4945,11 +4951,11 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
|
||||
} else {
|
||||
flags |= MTPDmessage::flag_from_id;
|
||||
}
|
||||
if (img.type == ToPreparePhoto) {
|
||||
if (img.type == PreparePhoto) {
|
||||
h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(img.peer), MTPPeer(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(img.photo, MTP_string(img.caption)), MTPnullMarkup, MTPnullEntities, MTP_int(1)), NewMessageUnread);
|
||||
} else if (img.type == ToPrepareDocument) {
|
||||
} else if (img.type == PrepareDocument) {
|
||||
h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(img.peer), MTPPeer(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup, MTPnullEntities, MTP_int(1)), NewMessageUnread);
|
||||
} else if (img.type == ToPrepareAudio) {
|
||||
} else if (img.type == PrepareAudio) {
|
||||
if (!h->peer->isChannel()) {
|
||||
flags |= MTPDmessage_flag_media_unread;
|
||||
}
|
||||
@ -4970,6 +4976,67 @@ void HistoryWidget::cancelSendImage() {
|
||||
_confirmImage = QImage();
|
||||
}
|
||||
|
||||
void HistoryWidget::confirmSendFile(const FileLoadResultPtr &file, bool ctrlShiftEnter) {
|
||||
if (_confirmWithTextId && _confirmWithTextId == file->id) {
|
||||
onSend(ctrlShiftEnter, file->to.replyTo);
|
||||
_confirmWithTextId = 0;
|
||||
}
|
||||
|
||||
FullMsgId newId(peerToChannel(file->to.peer), clientMsgId());
|
||||
|
||||
connect(App::uploader(), SIGNAL(photoReady(const FullMsgId&, const MTPInputFile&)), this, SLOT(onPhotoUploaded(const FullMsgId&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(documentReady(const FullMsgId&, const MTPInputFile&)), this, SLOT(onDocumentUploaded(const FullMsgId&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(thumbDocumentReady(const FullMsgId&, const MTPInputFile&, const MTPInputFile&)), this, SLOT(onThumbDocumentUploaded(const FullMsgId&, const MTPInputFile&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(audioReady(const FullMsgId&, const MTPInputFile&)), this, SLOT(onAudioUploaded(const FullMsgId&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(photoProgress(const FullMsgId&)), this, SLOT(onPhotoProgress(const FullMsgId&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(documentProgress(const FullMsgId&)), this, SLOT(onDocumentProgress(const FullMsgId&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(audioProgress(const FullMsgId&)), this, SLOT(onAudioProgress(const FullMsgId&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(photoFailed(const FullMsgId&)), this, SLOT(onPhotoFailed(const FullMsgId&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(documentFailed(const FullMsgId&)), this, SLOT(onDocumentFailed(const FullMsgId&)), Qt::UniqueConnection);
|
||||
connect(App::uploader(), SIGNAL(audioFailed(const FullMsgId&)), this, SLOT(onAudioFailed(const FullMsgId&)), Qt::UniqueConnection);
|
||||
|
||||
App::uploader()->uploadFile(newId, file);
|
||||
|
||||
History *h = App::history(file->to.peer);
|
||||
|
||||
fastShowAtEnd(h);
|
||||
|
||||
int32 flags = newMessageFlags(h->peer) | MTPDmessage::flag_media; // unread, out
|
||||
if (file->to.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id;
|
||||
bool fromChannelName = h->peer->isChannel() && h->peer->asChannel()->canPublish() && (h->peer->asChannel()->isBroadcast() || file->to.broadcast);
|
||||
if (fromChannelName) {
|
||||
flags |= MTPDmessage::flag_views;
|
||||
} else {
|
||||
flags |= MTPDmessage::flag_from_id;
|
||||
}
|
||||
if (file->type == PreparePhoto) {
|
||||
h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(file->to.peer), MTPPeer(), MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(file->photo, MTP_string(file->photoCaption)), MTPnullMarkup, MTPnullEntities, MTP_int(1)), NewMessageUnread);
|
||||
} else if (file->type == PrepareDocument) {
|
||||
h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(file->to.peer), MTPPeer(), MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(file->document), MTPnullMarkup, MTPnullEntities, MTP_int(1)), NewMessageUnread);
|
||||
} else if (file->type == PrepareAudio) {
|
||||
if (!h->peer->isChannel()) {
|
||||
flags |= MTPDmessage_flag_media_unread;
|
||||
}
|
||||
h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(file->to.peer), MTPPeer(), MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(file->audio), MTPnullMarkup, MTPnullEntities, MTP_int(1)), NewMessageUnread);
|
||||
}
|
||||
|
||||
if (_peer && file->to.peer == _peer->id) {
|
||||
App::main()->historyToDown(_history);
|
||||
}
|
||||
App::main()->dialogsToUp();
|
||||
peerMessagesUpdated(file->to.peer);
|
||||
}
|
||||
|
||||
void HistoryWidget::cancelSendFile(const FileLoadResultPtr &file) {
|
||||
if (_confirmWithTextId && file->id == _confirmWithTextId) {
|
||||
setFieldText(QString());
|
||||
_confirmWithTextId = 0;
|
||||
}
|
||||
if (!file->originalText.isEmpty()) {
|
||||
_field.textCursor().insertText(file->originalText);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onPhotoUploaded(const FullMsgId &newId, const MTPInputFile &file) {
|
||||
if (!MTP::authedId()) return;
|
||||
HistoryItem *item = App::histItemById(newId);
|
||||
|
@ -430,16 +430,19 @@ public:
|
||||
void sendActionDone(const MTPBool &result, mtpRequestId req);
|
||||
|
||||
void destroyData();
|
||||
void uploadImage(const QImage &img, bool withText = false, const QString &source = QString());
|
||||
void uploadFile(const QString &file, bool withText = false); // with confirmation
|
||||
void uploadImage(const QImage &img, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm, const QString &source = QString(), bool withText = false);
|
||||
void uploadFile(const QString &file, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm, bool withText = false); // with confirmation
|
||||
void shareContactConfirmation(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, bool withText = false);
|
||||
void uploadConfirmImageUncompressed(bool ctrlShiftEnter, MsgId replyTo);
|
||||
void uploadMedias(const QStringList &files, ToPrepareMediaType type);
|
||||
void uploadMedia(const QByteArray &fileContent, ToPrepareMediaType type, PeerId peer = 0);
|
||||
void uploadMedias(const QStringList &files, PrepareMediaType type);
|
||||
void uploadMedia(const QByteArray &fileContent, PrepareMediaType type, PeerId peer = 0);
|
||||
void confirmShareContact(bool ctrlShiftEnter, const QString &phone, const QString &fname, const QString &lname, MsgId replyTo);
|
||||
void confirmSendImage(const ReadyLocalMedia &img);
|
||||
void cancelSendImage();
|
||||
|
||||
void confirmSendFile(const FileLoadResultPtr &file, bool ctrlShiftEnter);
|
||||
void cancelSendFile(const FileLoadResultPtr &file);
|
||||
|
||||
void updateControlsVisibility();
|
||||
void updateOnlineDisplay(int32 x, int32 w);
|
||||
void updateOnlineDisplayTimer();
|
||||
@ -767,6 +770,7 @@ private:
|
||||
|
||||
int32 _selCount; // < 0 - text selected, focus list, not _field
|
||||
|
||||
TaskQueue _fileLoader;
|
||||
LocalImageLoader _imageLoader;
|
||||
bool _synthedTextUpdate;
|
||||
|
||||
@ -776,6 +780,8 @@ private:
|
||||
bool _confirmWithText;
|
||||
QString _confirmSource;
|
||||
|
||||
uint64 _confirmWithTextId;
|
||||
|
||||
QString _titlePeerText;
|
||||
int32 _titlePeerTextWidth;
|
||||
|
||||
|
@ -138,6 +138,18 @@ void BackgroundWidget::replaceInner(LayeredWidget *n) {
|
||||
update();
|
||||
}
|
||||
|
||||
void BackgroundWidget::showLayerLast(LayeredWidget *n) {
|
||||
_hidden.push_front(n);
|
||||
n->setParent(this);
|
||||
connect(n, SIGNAL(closed()), this, SLOT(onInnerClose()));
|
||||
connect(n, SIGNAL(resized()), this, SLOT(update()));
|
||||
connect(n, SIGNAL(destroyed(QObject*)), this, SLOT(boxDestroyed(QObject*)));
|
||||
n->parentResized();
|
||||
n->animStep(1);
|
||||
n->hide();
|
||||
update();
|
||||
}
|
||||
|
||||
bool BackgroundWidget::animStep(float64 ms) {
|
||||
float64 dt = ms / (hiding ? st::layerHideDuration : st::layerSlideDuration);
|
||||
w->animStep(dt);
|
||||
|
@ -74,6 +74,7 @@ public:
|
||||
void updateWideMode();
|
||||
|
||||
void replaceInner(LayeredWidget *n);
|
||||
void showLayerLast(LayeredWidget *n);
|
||||
|
||||
bool animStep(float64 ms);
|
||||
|
||||
|
@ -22,7 +22,12 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
#include "localimageloader.h"
|
||||
#include "gui/filedialog.h"
|
||||
#include "audio.h"
|
||||
#include <libexif/exif-data.h>
|
||||
|
||||
#include "boxes/photosendbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "lang.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
|
||||
LocalImageLoaderPrivate::LocalImageLoaderPrivate(LocalImageLoader *loader, QThread *thread) : QObject(0)
|
||||
, loader(loader)
|
||||
@ -42,7 +47,7 @@ void LocalImageLoaderPrivate::prepareImages() {
|
||||
uint64 id, thumbId = 0;
|
||||
int32 duration = 0;
|
||||
QString thumbExt = "jpg";
|
||||
ToPrepareMediaType type;
|
||||
PrepareMediaType type;
|
||||
bool animated = false;
|
||||
bool broadcast = false;
|
||||
bool ctrlShiftEnter = false;
|
||||
@ -67,53 +72,53 @@ void LocalImageLoaderPrivate::prepareImages() {
|
||||
if (img.isNull()) {
|
||||
if (!file.isEmpty()) {
|
||||
QFileInfo info(file);
|
||||
if (type == ToPrepareAuto) {
|
||||
if (type == PrepareAuto) {
|
||||
QString lower(file.toLower());
|
||||
const QStringList &photoExtensions(cPhotoExtensions());
|
||||
for (QStringList::const_iterator i = photoExtensions.cbegin(), e = photoExtensions.cend(); i != e; ++i) {
|
||||
if (lower.lastIndexOf(*i) == lower.size() - i->size()) {
|
||||
if (info.size() < MaxUploadPhotoSize) {
|
||||
type = ToPreparePhoto;
|
||||
type = PreparePhoto;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == ToPrepareAuto && info.size() < MaxUploadDocumentSize) {
|
||||
type = ToPrepareDocument;
|
||||
if (type == PrepareAuto && info.size() < MaxUploadDocumentSize) {
|
||||
type = PrepareDocument;
|
||||
}
|
||||
}
|
||||
if (type != ToPrepareAuto && info.size() < MaxUploadPhotoSize) {
|
||||
if (type != PrepareAuto && info.size() < MaxUploadPhotoSize) {
|
||||
bool opaque = (mime != stickerMime);
|
||||
img = App::readImage(file, 0, opaque, &animated);
|
||||
if (animated) {
|
||||
type = ToPrepareDocument;
|
||||
type = PrepareDocument;
|
||||
}
|
||||
}
|
||||
if (type == ToPrepareDocument) {
|
||||
if (type == PrepareDocument) {
|
||||
mime = mimeTypeForFile(info).name();
|
||||
}
|
||||
filename = info.fileName();
|
||||
filesize = info.size();
|
||||
} else if (!data.isEmpty()) {
|
||||
if (type != ToPrepareAudio) {
|
||||
if (type != PrepareAudio) {
|
||||
img = App::readImage(data, 0, true, &animated);
|
||||
if (type == ToPrepareAuto) {
|
||||
if (type == PrepareAuto) {
|
||||
if (!img.isNull() && data.size() < MaxUploadPhotoSize) {
|
||||
type = ToPreparePhoto;
|
||||
type = PreparePhoto;
|
||||
} else if (data.size() < MaxUploadDocumentSize) {
|
||||
type = ToPrepareDocument;
|
||||
type = PrepareDocument;
|
||||
} else {
|
||||
img = QImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
MimeType mimeType = mimeTypeForData(data);
|
||||
if (type == ToPrepareDocument || type == ToPrepareAudio) {
|
||||
if (type == PrepareDocument || type == PrepareAudio) {
|
||||
mime = mimeType.name();
|
||||
}
|
||||
if (mime == "image/jpeg") {
|
||||
filename = filedialogDefaultName(qsl("image"), qsl(".jpg"), QString(), true);
|
||||
} else if (type == ToPrepareAudio) {
|
||||
} else if (type == PrepareAudio) {
|
||||
filename = filedialogDefaultName(qsl("audio"), qsl(".ogg"), QString(), true);
|
||||
mime = "audio/ogg";
|
||||
} else {
|
||||
@ -122,12 +127,12 @@ void LocalImageLoaderPrivate::prepareImages() {
|
||||
if (!patterns.isEmpty()) {
|
||||
ext = patterns.front().replace('*', QString());
|
||||
}
|
||||
filename = filedialogDefaultName((type == ToPrepareAudio) ? qsl("audio") : qsl("doc"), ext, QString(), true);
|
||||
filename = filedialogDefaultName((type == PrepareAudio) ? qsl("audio") : qsl("doc"), ext, QString(), true);
|
||||
}
|
||||
filesize = data.size();
|
||||
}
|
||||
} else {
|
||||
if (type == ToPrepareDocument) {
|
||||
if (type == PrepareDocument) {
|
||||
filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
|
||||
mime = mimeTypeForName("image/png").name();
|
||||
data = QByteArray();
|
||||
@ -145,13 +150,13 @@ void LocalImageLoaderPrivate::prepareImages() {
|
||||
}
|
||||
img = solid;
|
||||
}
|
||||
type = ToPreparePhoto;
|
||||
type = PreparePhoto;
|
||||
filename = qsl("Untitled.jpg");
|
||||
filesize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((img.isNull() && ((type != ToPrepareDocument && type != ToPrepareAudio) || !filesize)) || type == ToPrepareAuto || (img.isNull() && file.isEmpty() && data.isEmpty())) { // if could not decide what type
|
||||
if ((img.isNull() && ((type != PrepareDocument && type != PrepareAudio) || !filesize)) || type == PrepareAuto || (img.isNull() && file.isEmpty() && data.isEmpty())) { // if could not decide what type
|
||||
{
|
||||
QMutexLocker lock(loader->toPrepareMutex());
|
||||
ToPrepareMedias &list(loader->toPrepareMedias());
|
||||
@ -174,7 +179,7 @@ void LocalImageLoaderPrivate::prepareImages() {
|
||||
|
||||
bool isSong = false;
|
||||
QByteArray jpeg;
|
||||
if (type == ToPrepareDocument) {
|
||||
if (type == PrepareDocument) {
|
||||
if (mime == qstr("audio/mp3") || mime == qstr("audio/m4a") || mime == qstr("audio/aac") || mime == qstr("audio/ogg") || mime == qstr("audio/flac") ||
|
||||
filename.endsWith(qstr(".mp3"), Qt::CaseInsensitive) || filename.endsWith(qstr(".m4a"), Qt::CaseInsensitive) ||
|
||||
filename.endsWith(qstr(".aac"), Qt::CaseInsensitive) || filename.endsWith(qstr(".ogg"), Qt::CaseInsensitive) ||
|
||||
@ -207,7 +212,7 @@ void LocalImageLoaderPrivate::prepareImages() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == ToPreparePhoto) {
|
||||
if (type == PreparePhoto) {
|
||||
int32 w = img.width(), h = img.height();
|
||||
|
||||
QPixmap thumb = (w > 100 || h > 100) ? QPixmap::fromImage(img.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(img);
|
||||
@ -231,7 +236,7 @@ void LocalImageLoaderPrivate::prepareImages() {
|
||||
photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes));
|
||||
|
||||
thumbId = id;
|
||||
} else if ((type == ToPrepareVideo || type == ToPrepareDocument) && !img.isNull() && !isSong) {
|
||||
} else if ((type == PrepareVideo || type == PrepareDocument) && !img.isNull() && !isSong) {
|
||||
int32 w = img.width(), h = img.height();
|
||||
QByteArray thumbFormat = "JPG";
|
||||
int32 thumbQuality = 87;
|
||||
@ -258,9 +263,9 @@ void LocalImageLoaderPrivate::prepareImages() {
|
||||
}
|
||||
}
|
||||
|
||||
if (type == ToPrepareDocument) {
|
||||
if (type == PrepareDocument) {
|
||||
document = MTP_document(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(filesize), thumb, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
|
||||
} else if (type == ToPrepareAudio) {
|
||||
} else if (type == PrepareAudio) {
|
||||
audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc()));
|
||||
}
|
||||
|
||||
@ -288,7 +293,7 @@ LocalImageLoaderPrivate::~LocalImageLoaderPrivate() {
|
||||
LocalImageLoader::LocalImageLoader(QObject *parent) : QObject(parent), thread(0), priv(0) {
|
||||
}
|
||||
|
||||
void LocalImageLoader::append(const QStringList &files, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t) {
|
||||
void LocalImageLoader::append(const QStringList &files, const PeerId &peer, bool broadcast, MsgId replyTo, PrepareMediaType t) {
|
||||
{
|
||||
QMutexLocker lock(toPrepareMutex());
|
||||
for (QStringList::const_iterator i = files.cbegin(), e = files.cend(); i != e; ++i) {
|
||||
@ -303,7 +308,7 @@ void LocalImageLoader::append(const QStringList &files, const PeerId &peer, bool
|
||||
emit needToPrepare();
|
||||
}
|
||||
|
||||
PhotoId LocalImageLoader::append(const QByteArray &img, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t) {
|
||||
PhotoId LocalImageLoader::append(const QByteArray &img, const PeerId &peer, bool broadcast, MsgId replyTo, PrepareMediaType t) {
|
||||
PhotoId result = 0;
|
||||
{
|
||||
QMutexLocker lock(toPrepareMutex());
|
||||
@ -319,7 +324,7 @@ PhotoId LocalImageLoader::append(const QByteArray &img, const PeerId &peer, bool
|
||||
return result;
|
||||
}
|
||||
|
||||
AudioId LocalImageLoader::append(const QByteArray &audio, int32 duration, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t) {
|
||||
AudioId LocalImageLoader::append(const QByteArray &audio, int32 duration, const PeerId &peer, bool broadcast, MsgId replyTo, PrepareMediaType t) {
|
||||
AudioId result = 0;
|
||||
{
|
||||
QMutexLocker lock(toPrepareMutex());
|
||||
@ -335,7 +340,7 @@ AudioId LocalImageLoader::append(const QByteArray &audio, int32 duration, const
|
||||
return result;
|
||||
}
|
||||
|
||||
PhotoId LocalImageLoader::append(const QImage &img, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t, bool ctrlShiftEnter) {
|
||||
PhotoId LocalImageLoader::append(const QImage &img, const PeerId &peer, bool broadcast, MsgId replyTo, PrepareMediaType t, bool ctrlShiftEnter) {
|
||||
PhotoId result = 0;
|
||||
{
|
||||
QMutexLocker lock(toPrepareMutex());
|
||||
@ -351,7 +356,7 @@ PhotoId LocalImageLoader::append(const QImage &img, const PeerId &peer, bool bro
|
||||
return result;
|
||||
}
|
||||
|
||||
PhotoId LocalImageLoader::append(const QString &file, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t) {
|
||||
PhotoId LocalImageLoader::append(const QString &file, const PeerId &peer, bool broadcast, MsgId replyTo, PrepareMediaType t) {
|
||||
PhotoId result = 0;
|
||||
{
|
||||
QMutexLocker lock(toPrepareMutex());
|
||||
@ -416,7 +421,6 @@ LocalImageLoader::~LocalImageLoader() {
|
||||
delete thread;
|
||||
}
|
||||
|
||||
|
||||
TaskQueue::TaskQueue(QObject *parent, int32 stopTimeoutMs) : QObject(parent), _thread(0), _worker(0), _stopTimer(0) {
|
||||
if (stopTimeoutMs > 0) {
|
||||
_stopTimer = new QTimer(this);
|
||||
@ -534,3 +538,256 @@ void TaskQueueWorker::onTaskAdded() {
|
||||
|
||||
_inTaskAdded = false;
|
||||
}
|
||||
|
||||
FileLoadTask::FileLoadTask(const QString &filepath, PrepareMediaType type, const FileLoadTo &to, FileLoadForceConfirmType confirm) : _id(MTP::nonce<uint64>())
|
||||
, _to(to)
|
||||
, _filepath(filepath)
|
||||
, _duration(0)
|
||||
, _type(type)
|
||||
, _confirm(confirm)
|
||||
, _result(0) {
|
||||
}
|
||||
|
||||
FileLoadTask::FileLoadTask(const QByteArray &content, PrepareMediaType type, const FileLoadTo &to) : _id(MTP::nonce<uint64>())
|
||||
, _to(to)
|
||||
, _content(content)
|
||||
, _duration(0)
|
||||
, _type(type)
|
||||
, _confirm(FileLoadNoForceConfirm)
|
||||
, _result(0) {
|
||||
}
|
||||
|
||||
FileLoadTask::FileLoadTask(const QImage &image, const FileLoadTo &to, FileLoadForceConfirmType confirm, const QString &originalText) : _id(MTP::nonce<uint64>())
|
||||
, _to(to)
|
||||
, _image(image)
|
||||
, _duration(0)
|
||||
, _type(PrepareAuto)
|
||||
, _confirm(confirm)
|
||||
, _originalText(originalText)
|
||||
, _result(0) {
|
||||
}
|
||||
|
||||
FileLoadTask::FileLoadTask(const QByteArray &audio, int32 duration, const FileLoadTo &to) : _id(MTP::nonce<uint64>())
|
||||
, _to(to)
|
||||
, _content(audio)
|
||||
, _duration(duration)
|
||||
, _type(PrepareAudio)
|
||||
, _confirm(FileLoadNoForceConfirm)
|
||||
, _result(0) {
|
||||
}
|
||||
|
||||
void FileLoadTask::process() {
|
||||
const QString stickerMime = qsl("image/webp");
|
||||
|
||||
_result = FileLoadResultPtr(new FileLoadResult(_id, _to));
|
||||
|
||||
QString filename, filemime;
|
||||
qint64 filesize = 0;
|
||||
QByteArray filedata;
|
||||
|
||||
uint64 thumbId = 0;
|
||||
QString thumbname = "thumb.jpg";
|
||||
QByteArray thumbdata;
|
||||
|
||||
bool animated = false;
|
||||
QImage fullimage = _image;
|
||||
|
||||
if (!_filepath.isEmpty()) {
|
||||
QFileInfo info(_filepath);
|
||||
filesize = info.size();
|
||||
filemime = mimeTypeForFile(info).name();
|
||||
filename = info.fileName();
|
||||
if (filesize <= MaxUploadPhotoSize && _type != PrepareAudio) {
|
||||
bool opaque = (filemime != stickerMime);
|
||||
fullimage = App::readImage(_filepath, 0, opaque, &animated);
|
||||
}
|
||||
} else if (!_content.isEmpty()) {
|
||||
filesize = _content.size();
|
||||
MimeType mimeType = mimeTypeForData(_content);
|
||||
filemime = mimeType.name();
|
||||
if (filesize <= MaxUploadPhotoSize && _type != PrepareAudio) {
|
||||
bool opaque = (filemime != stickerMime);
|
||||
fullimage = App::readImage(_content, 0, opaque, &animated);
|
||||
}
|
||||
if (filemime == "image/jpeg") {
|
||||
filename = filedialogDefaultName(qsl("image"), qsl(".jpg"), QString(), true);
|
||||
} else if (_type == PrepareAudio) {
|
||||
filename = filedialogDefaultName(qsl("audio"), qsl(".ogg"), QString(), true);
|
||||
filemime = "audio/ogg";
|
||||
} else {
|
||||
QString ext;
|
||||
QStringList patterns = mimeType.globPatterns();
|
||||
if (!patterns.isEmpty()) {
|
||||
ext = patterns.front().replace('*', QString());
|
||||
}
|
||||
filename = filedialogDefaultName(qsl("file"), ext, QString(), true);
|
||||
}
|
||||
} else if (!_image.isNull()) {
|
||||
_image = QImage();
|
||||
|
||||
filemime = mimeTypeForName("image/png").name();
|
||||
filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
|
||||
{
|
||||
QBuffer buffer(&_content);
|
||||
fullimage.save(&buffer, "PNG");
|
||||
}
|
||||
filesize = _content.size();
|
||||
|
||||
if (fullimage.hasAlphaChannel()) {
|
||||
QImage solid(fullimage.width(), fullimage.height(), QImage::Format_ARGB32_Premultiplied);
|
||||
solid.fill(st::white->c);
|
||||
{
|
||||
QPainter(&solid).drawImage(0, 0, fullimage);
|
||||
}
|
||||
fullimage = solid;
|
||||
}
|
||||
}
|
||||
_result->filesize = (int32)qMin(filesize, qint64(INT_MAX));
|
||||
|
||||
if (!filesize || filesize > MaxUploadDocumentSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
PreparedPhotoThumbs photoThumbs;
|
||||
QVector<MTPPhotoSize> photoSizes;
|
||||
QPixmap thumb;
|
||||
|
||||
QVector<MTPDocumentAttribute> attributes(1, MTP_documentAttributeFilename(MTP_string(filename)));
|
||||
|
||||
MTPPhotoSize thumbSize(MTP_photoSizeEmpty(MTP_string("")));
|
||||
MTPPhoto photo(MTP_photoEmpty(MTP_long(0)));
|
||||
MTPDocument document(MTP_documentEmpty(MTP_long(0)));
|
||||
MTPAudio audio(MTP_audioEmpty(MTP_long(0)));
|
||||
|
||||
bool song = false;
|
||||
if (_type != PrepareAudio) {
|
||||
if (filemime == qstr("audio/mp3") || filemime == qstr("audio/m4a") || filemime == qstr("audio/aac") || filemime == qstr("audio/ogg") || filemime == qstr("audio/flac") ||
|
||||
filename.endsWith(qstr(".mp3"), Qt::CaseInsensitive) || filename.endsWith(qstr(".m4a"), Qt::CaseInsensitive) ||
|
||||
filename.endsWith(qstr(".aac"), Qt::CaseInsensitive) || filename.endsWith(qstr(".ogg"), Qt::CaseInsensitive) ||
|
||||
filename.endsWith(qstr(".flac"), Qt::CaseInsensitive)) {
|
||||
|
||||
QImage cover;
|
||||
QByteArray coverBytes, coverFormat;
|
||||
MTPDocumentAttribute audioAttribute = audioReadSongAttributes(_filepath, _content, cover, coverBytes, coverFormat);
|
||||
if (audioAttribute.type() == mtpc_documentAttributeAudio) {
|
||||
attributes.push_back(audioAttribute);
|
||||
song = true;
|
||||
if (!cover.isNull()) { // cover to thumb
|
||||
int32 cw = cover.width(), ch = cover.height();
|
||||
if (cw < 20 * ch && ch < 20 * cw) {
|
||||
QPixmap full = (cw > 90 || ch > 90) ? QPixmap::fromImage(cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(cover, Qt::ColorOnly);
|
||||
{
|
||||
QByteArray thumbFormat = "JPG";
|
||||
int32 thumbQuality = 87;
|
||||
|
||||
QBuffer buffer(&thumbdata);
|
||||
full.save(&buffer, thumbFormat, thumbQuality);
|
||||
}
|
||||
|
||||
thumb = full;
|
||||
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));
|
||||
|
||||
thumbId = MTP::nonce<uint64>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!fullimage.isNull() && fullimage.width() > 0 && !song) {
|
||||
int32 w = fullimage.width(), h = fullimage.height();
|
||||
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));
|
||||
|
||||
if (w < 20 * h && h < 20 * w) {
|
||||
if (animated) {
|
||||
attributes.push_back(MTP_documentAttributeAnimated());
|
||||
} else {
|
||||
QPixmap thumb = (w > 100 || h > 100) ? QPixmap::fromImage(fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage);
|
||||
photoThumbs.insert('s', thumb);
|
||||
photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));
|
||||
|
||||
QPixmap medium = (w > 320 || h > 320) ? QPixmap::fromImage(fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage);
|
||||
photoThumbs.insert('m', medium);
|
||||
photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));
|
||||
|
||||
QPixmap full = (w > 1280 || h > 1280) ? QPixmap::fromImage(fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage);
|
||||
photoThumbs.insert('y', full);
|
||||
photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));
|
||||
|
||||
{
|
||||
QBuffer buffer(&filedata);
|
||||
full.save(&buffer, "JPG", 77);
|
||||
}
|
||||
|
||||
photo = MTP_photo(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes));
|
||||
}
|
||||
|
||||
QByteArray thumbFormat = "JPG";
|
||||
int32 thumbQuality = 87;
|
||||
if (!animated && filemime == stickerMime && w > 0 && h > 0 && w <= StickerMaxSize && h <= StickerMaxSize && filesize < StickerInMemory) {
|
||||
attributes.push_back(MTP_documentAttributeSticker(MTP_string(""), MTP_inputStickerSetEmpty()));
|
||||
thumbFormat = "webp";
|
||||
thumbname = qsl("thumb.webp");
|
||||
}
|
||||
|
||||
QPixmap full = (w > 90 || h > 90) ? QPixmap::fromImage(fullimage.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage, Qt::ColorOnly);
|
||||
|
||||
{
|
||||
QBuffer buffer(&thumbdata);
|
||||
full.save(&buffer, thumbFormat, thumbQuality);
|
||||
}
|
||||
|
||||
thumb = full;
|
||||
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));
|
||||
|
||||
thumbId = MTP::nonce<uint64>();
|
||||
}
|
||||
}
|
||||
|
||||
if (_type == PrepareAudio) {
|
||||
audio = MTP_audio(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_int(_duration), MTP_string(filemime), MTP_int(filesize), MTP_int(MTP::maindc()));
|
||||
} else {
|
||||
document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
|
||||
if (photo.type() == mtpc_photoEmpty) {
|
||||
_type = PrepareDocument;
|
||||
}
|
||||
}
|
||||
|
||||
_result->type = _type;
|
||||
_result->filepath = _filepath;
|
||||
_result->content = _content;
|
||||
|
||||
_result->filename = filename;
|
||||
_result->setFileData(filedata);
|
||||
|
||||
_result->thumbId = thumbId;
|
||||
_result->thumbname = thumbname;
|
||||
_result->setThumbData(thumbdata);
|
||||
_result->thumb = thumb;
|
||||
|
||||
_result->photo = photo;
|
||||
_result->audio = audio;
|
||||
_result->document = document;
|
||||
_result->photoThumbs = photoThumbs;
|
||||
}
|
||||
|
||||
void FileLoadTask::finish() {
|
||||
if (!_result || !_result->filesize) {
|
||||
if (_result) App::main()->onSendFileCancel(_result);
|
||||
App::wnd()->replaceLayer(new InformBox(lang(lng_send_image_empty)));
|
||||
return;
|
||||
}
|
||||
if (_result->filesize > MaxUploadDocumentSize) {
|
||||
App::main()->onSendFileCancel(_result);
|
||||
App::wnd()->replaceLayer(new InformBox(lang(lng_send_image_too_large)));
|
||||
return;
|
||||
}
|
||||
if (App::main()) {
|
||||
bool confirm = (_confirm == FileLoadAlwaysConfirm) || (_result->photo.type() != mtpc_photoEmpty && _confirm != FileLoadNeverConfirm);
|
||||
if (confirm) {
|
||||
App::wnd()->showLayerLast(new PhotoSendBox(_result));
|
||||
} else {
|
||||
App::main()->onSendFileConfirm(_result, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,29 +20,29 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
enum ToPrepareMediaType {
|
||||
ToPrepareAuto,
|
||||
ToPreparePhoto,
|
||||
ToPrepareAudio,
|
||||
ToPrepareVideo,
|
||||
ToPrepareDocument,
|
||||
enum PrepareMediaType {
|
||||
PrepareAuto,
|
||||
PreparePhoto,
|
||||
PrepareAudio,
|
||||
PrepareVideo,
|
||||
PrepareDocument,
|
||||
};
|
||||
|
||||
struct ToPrepareMedia {
|
||||
ToPrepareMedia(const QString &file, const PeerId &peer, ToPrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), file(file), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
ToPrepareMedia(const QString &file, const PeerId &peer, PrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), file(file), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
}
|
||||
ToPrepareMedia(const QImage &img, const PeerId &peer, ToPrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), img(img), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
ToPrepareMedia(const QImage &img, const PeerId &peer, PrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), img(img), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
}
|
||||
ToPrepareMedia(const QByteArray &data, const PeerId &peer, ToPrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), data(data), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
ToPrepareMedia(const QByteArray &data, const PeerId &peer, PrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), data(data), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
}
|
||||
ToPrepareMedia(const QByteArray &data, int32 duration, const PeerId &peer, ToPrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), data(data), peer(peer), type(t), duration(duration), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
ToPrepareMedia(const QByteArray &data, int32 duration, const PeerId &peer, PrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), data(data), peer(peer), type(t), duration(duration), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
}
|
||||
PhotoId id;
|
||||
QString file;
|
||||
QImage img;
|
||||
QByteArray data;
|
||||
PeerId peer;
|
||||
ToPrepareMediaType type;
|
||||
PrepareMediaType type;
|
||||
int32 duration;
|
||||
bool broadcast;
|
||||
bool ctrlShiftEnter;
|
||||
@ -50,9 +50,9 @@ struct ToPrepareMedia {
|
||||
};
|
||||
typedef QList<ToPrepareMedia> ToPrepareMedias;
|
||||
|
||||
typedef QMap<int32, QByteArray> LocalFileParts;
|
||||
typedef QMap<int32, QByteArray> UploadFileParts;
|
||||
struct ReadyLocalMedia {
|
||||
ReadyLocalMedia(ToPrepareMediaType type, const QString &file, const QString &filename, int32 filesize, const QByteArray &data, const uint64 &id, const uint64 &thumbId, const QString &thumbExt, const PeerId &peer, const MTPPhoto &photo, const MTPAudio &audio, const PreparedPhotoThumbs &photoThumbs, const MTPDocument &document, const QByteArray &jpeg, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) :
|
||||
ReadyLocalMedia(PrepareMediaType type, const QString &file, const QString &filename, int32 filesize, const QByteArray &data, const uint64 &id, const uint64 &thumbId, const QString &thumbExt, const PeerId &peer, const MTPPhoto &photo, const MTPAudio &audio, const PreparedPhotoThumbs &photoThumbs, const MTPDocument &document, const QByteArray &jpeg, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) :
|
||||
replyTo(replyTo), type(type), file(file), filename(filename), filesize(filesize), data(data), thumbExt(thumbExt), id(id), thumbId(thumbId), peer(peer), photo(photo), document(document), audio(audio), photoThumbs(photoThumbs), broadcast(broadcast), ctrlShiftEnter(ctrlShiftEnter) {
|
||||
if (!jpeg.isEmpty()) {
|
||||
int32 size = jpeg.size();
|
||||
@ -64,7 +64,7 @@ struct ReadyLocalMedia {
|
||||
}
|
||||
}
|
||||
MsgId replyTo;
|
||||
ToPrepareMediaType type;
|
||||
PrepareMediaType type;
|
||||
QString file, filename;
|
||||
int32 filesize;
|
||||
QByteArray data;
|
||||
@ -76,12 +76,15 @@ struct ReadyLocalMedia {
|
||||
MTPDocument document;
|
||||
MTPAudio audio;
|
||||
PreparedPhotoThumbs photoThumbs;
|
||||
LocalFileParts parts;
|
||||
UploadFileParts parts;
|
||||
QByteArray jpeg_md5;
|
||||
|
||||
bool broadcast;
|
||||
bool ctrlShiftEnter;
|
||||
QString caption;
|
||||
|
||||
ReadyLocalMedia() : type(PrepareAuto) { // temp
|
||||
}
|
||||
};
|
||||
typedef QList<ReadyLocalMedia> ReadyLocalMedias;
|
||||
|
||||
@ -115,11 +118,11 @@ class LocalImageLoader : public QObject {
|
||||
public:
|
||||
|
||||
LocalImageLoader(QObject *parent);
|
||||
void append(const QStringList &files, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t);
|
||||
PhotoId append(const QByteArray &img, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t);
|
||||
AudioId append(const QByteArray &audio, int32 duration, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t);
|
||||
PhotoId append(const QImage &img, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t, bool ctrlShiftEnter = false);
|
||||
PhotoId append(const QString &file, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t);
|
||||
void append(const QStringList &files, const PeerId &peer, bool broadcast, MsgId replyTo, PrepareMediaType t);
|
||||
PhotoId append(const QByteArray &img, const PeerId &peer, bool broadcast, MsgId replyTo, PrepareMediaType t);
|
||||
AudioId append(const QByteArray &audio, int32 duration, const PeerId &peer, bool broadcast, MsgId replyTo, PrepareMediaType t);
|
||||
PhotoId append(const QImage &img, const PeerId &peer, bool broadcast, MsgId replyTo, PrepareMediaType t, bool ctrlShiftEnter = false);
|
||||
PhotoId append(const QString &file, const PeerId &peer, bool broadcast, MsgId replyTo, PrepareMediaType t);
|
||||
|
||||
QMutex *readyMutex();
|
||||
ReadyLocalMedias &readyList();
|
||||
@ -176,8 +179,7 @@ public:
|
||||
TaskId addTask(TaskPtr task);
|
||||
void cancelTask(TaskId id); // this task finish() won't be called
|
||||
|
||||
template <typename DerivedTask>
|
||||
TaskId addTask(DerivedTask *task) {
|
||||
TaskId addTask(Task *task) {
|
||||
return addTask(TaskPtr(task));
|
||||
}
|
||||
|
||||
@ -226,3 +228,101 @@ private:
|
||||
bool _inTaskAdded;
|
||||
|
||||
};
|
||||
|
||||
struct FileLoadTo {
|
||||
FileLoadTo(const PeerId &peer, bool broadcast, MsgId replyTo) : peer(peer), broadcast(broadcast), replyTo(replyTo) {
|
||||
}
|
||||
PeerId peer;
|
||||
bool broadcast;
|
||||
MsgId replyTo;
|
||||
};
|
||||
|
||||
struct FileLoadResult {
|
||||
FileLoadResult(const uint64 &id, const FileLoadTo &to) : id(id), to(to), type(PrepareAuto), thumbId(0), filesize(0) {
|
||||
}
|
||||
|
||||
uint64 id;
|
||||
FileLoadTo to;
|
||||
PrepareMediaType type;
|
||||
QString filepath;
|
||||
QByteArray content;
|
||||
|
||||
QString filename;
|
||||
int32 filesize;
|
||||
UploadFileParts fileparts;
|
||||
QByteArray filemd5;
|
||||
|
||||
uint64 thumbId; // id is always file-id of media, thumbId is file-id of thumb ( == id for photos)
|
||||
QString thumbname;
|
||||
UploadFileParts thumbparts;
|
||||
QByteArray thumbmd5;
|
||||
QPixmap thumb;
|
||||
|
||||
MTPPhoto photo;
|
||||
MTPAudio audio;
|
||||
MTPDocument document;
|
||||
|
||||
PreparedPhotoThumbs photoThumbs;
|
||||
QString photoCaption;
|
||||
|
||||
QString originalText; // when pasted had an image mime save text mime here to insert if image send was cancelled
|
||||
|
||||
void setFileData(const QByteArray &filedata) {
|
||||
if (!filedata.isEmpty()) {
|
||||
int32 size = filedata.size();
|
||||
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) {
|
||||
fileparts.insert(part, filedata.mid(i, UploadPartSize));
|
||||
}
|
||||
filemd5.resize(32);
|
||||
hashMd5Hex(filedata.constData(), filedata.size(), filemd5.data());
|
||||
}
|
||||
}
|
||||
void setThumbData(const QByteArray &thumbdata) {
|
||||
if (!thumbdata.isEmpty()) {
|
||||
int32 size = thumbdata.size();
|
||||
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) {
|
||||
thumbparts.insert(part, thumbdata.mid(i, UploadPartSize));
|
||||
}
|
||||
thumbmd5.resize(32);
|
||||
hashMd5Hex(thumbdata.constData(), thumbdata.size(), thumbmd5.data());
|
||||
}
|
||||
}
|
||||
};
|
||||
typedef QSharedPointer<FileLoadResult> FileLoadResultPtr;
|
||||
|
||||
enum FileLoadForceConfirmType {
|
||||
FileLoadNoForceConfirm,
|
||||
FileLoadNeverConfirm,
|
||||
FileLoadAlwaysConfirm,
|
||||
};
|
||||
|
||||
class FileLoadTask : public Task {
|
||||
public:
|
||||
|
||||
FileLoadTask(const QString &filepath, PrepareMediaType type, const FileLoadTo &to, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm);
|
||||
FileLoadTask(const QByteArray &content, PrepareMediaType type, const FileLoadTo &to);
|
||||
FileLoadTask(const QImage &image, const FileLoadTo &to, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm, const QString &originalText = QString());
|
||||
FileLoadTask(const QByteArray &audio, int32 duration, const FileLoadTo &to);
|
||||
|
||||
uint64 fileid() const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
void process();
|
||||
void finish();
|
||||
|
||||
protected:
|
||||
|
||||
uint64 _id;
|
||||
FileLoadTo _to;
|
||||
QString _filepath;
|
||||
QImage _image;
|
||||
QByteArray _content;
|
||||
int32 _duration;
|
||||
PrepareMediaType _type;
|
||||
FileLoadForceConfirmType _confirm;
|
||||
QString _originalText;
|
||||
|
||||
FileLoadResultPtr _result;
|
||||
|
||||
};
|
||||
|
@ -1828,7 +1828,7 @@ namespace Local {
|
||||
if (!_started) {
|
||||
_started = true;
|
||||
_manager = new _local_inner::Manager();
|
||||
_localLoader = new TaskQueue(0, 5000);
|
||||
_localLoader = new TaskQueue(0, FileLoaderQueueStopTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1108,7 +1108,7 @@ void MainWidget::onResendAsDocument() {
|
||||
photo->full->forget();
|
||||
QByteArray data = photo->full->savedData();
|
||||
if (!data.isEmpty()) {
|
||||
history.uploadMedia(data, ToPrepareDocument, item->history()->peer->id);
|
||||
history.uploadMedia(data, PrepareDocument, item->history()->peer->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2046,6 +2046,16 @@ void MainWidget::updateOnlineDisplay() {
|
||||
if (App::wnd()->settingsWidget()) App::wnd()->settingsWidget()->updateOnlineDisplay();
|
||||
}
|
||||
|
||||
void MainWidget::onSendFileConfirm(const FileLoadResultPtr &file, bool ctrlShiftEnter) {
|
||||
bool lastKeyboardUsed = history.lastForceReplyReplied(FullMsgId(peerToChannel(file->to.peer), file->to.replyTo));
|
||||
history.confirmSendFile(file, ctrlShiftEnter);
|
||||
history.cancelReply(lastKeyboardUsed);
|
||||
}
|
||||
|
||||
void MainWidget::onSendFileCancel(const FileLoadResultPtr &file) {
|
||||
history.cancelSendFile(file);
|
||||
}
|
||||
|
||||
void MainWidget::confirmShareContact(bool ctrlShiftEnter, const QString &phone, const QString &fname, const QString &lname, MsgId replyTo) {
|
||||
history.confirmShareContact(ctrlShiftEnter, phone, fname, lname, replyTo);
|
||||
}
|
||||
|
@ -265,6 +265,9 @@ public:
|
||||
void orderWidgets();
|
||||
QRect historyRect() const;
|
||||
|
||||
void onSendFileConfirm(const FileLoadResultPtr &file, bool ctrlShiftEnter);
|
||||
void onSendFileCancel(const FileLoadResultPtr &file);
|
||||
|
||||
void confirmShareContact(bool ctrlShiftEnter, const QString &phone, const QString &fname, const QString &lname, MsgId replyTo);
|
||||
void confirmSendImage(const ReadyLocalMedia &img);
|
||||
void confirmSendImageUncompressed(bool ctrlShiftEnter, MsgId replyTo);
|
||||
|
@ -810,6 +810,14 @@ void Window::replaceLayer(LayeredWidget *w) {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::showLayerLast(LayeredWidget *w) {
|
||||
if (layerBg) {
|
||||
layerBg->showLayerLast(w);
|
||||
} else {
|
||||
layerBg = new BackgroundWidget(this, w);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::showConnecting(const QString &text, const QString &reconnect) {
|
||||
if (_connecting) {
|
||||
_connecting->set(text, reconnect);
|
||||
|
@ -181,8 +181,11 @@ public:
|
||||
void showPhoto(PhotoData *photo, HistoryItem *item);
|
||||
void showPhoto(PhotoData *photo, PeerData *item);
|
||||
void showDocument(DocumentData *doc, HistoryItem *item);
|
||||
|
||||
void showLayer(LayeredWidget *w, bool forceFast = false);
|
||||
void replaceLayer(LayeredWidget *w);
|
||||
void showLayerLast(LayeredWidget *w);
|
||||
|
||||
void hideLayer(bool fast = false);
|
||||
bool hideInnerLayer();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user