mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-18 22:17:01 +00:00
Merge branch 'master' of https://github.com/telegramdesktop/tdesktop
This commit is contained in:
commit
f143cec54e
@ -1,8 +1,8 @@
|
||||
@echo OFF
|
||||
|
||||
set "AppVersionStrSmall=0.6.15"
|
||||
set "AppVersionStr=0.6.15"
|
||||
set "AppVersionStrFull=0.6.15.0"
|
||||
set "AppVersionStrSmall=0.6.16"
|
||||
set "AppVersionStr=0.6.16"
|
||||
set "AppVersionStrFull=0.6.16.0"
|
||||
|
||||
echo.
|
||||
echo Preparing version %AppVersionStr%..
|
||||
|
@ -59,6 +59,7 @@ lng_month_day: "{month} {day}";
|
||||
|
||||
lng_cancel: "Cancel";
|
||||
lng_continue: "Continue";
|
||||
lng_close: "Close";
|
||||
lng_connecting: "Connecting..";
|
||||
lng_reconnecting: "Reconnect in %1 s..";
|
||||
lng_reconnecting_try_now: "Try now";
|
||||
@ -161,6 +162,7 @@ lng_username_occupied: "This name is already occupied.";
|
||||
lng_username_too_short: "This name is too short.";
|
||||
lng_username_bad_symbols: "This name has bad symbols.";
|
||||
lng_username_available: "This name is available.";
|
||||
lng_username_not_found: "User @{user} not found.";
|
||||
|
||||
lng_settings_section_contact_info: "Contact info";
|
||||
lng_settings_phone_number: "Phone number:";
|
||||
|
@ -1272,6 +1272,9 @@ aboutCloseButton: flatButton(contactsClose) {
|
||||
overTextTop: 15px;
|
||||
downTextTop: 16px;
|
||||
}
|
||||
btnInfoClose: flatButton(aboutCloseButton) {
|
||||
width: confirmWidth;
|
||||
}
|
||||
|
||||
emojiTextFont: font(16px);
|
||||
emojiReplaceWidth: 56px;
|
||||
|
@ -1088,6 +1088,10 @@ namespace App {
|
||||
convert->dc = dc;
|
||||
convert->size = size;
|
||||
}
|
||||
|
||||
if (convert->location.check()) {
|
||||
Local::writeFileLocation(mediaKey(mtpc_inputDocumentFileLocation, convert->dc, convert->id), convert->location);
|
||||
}
|
||||
}
|
||||
DocumentsData::const_iterator i = documentsData.constFind(document);
|
||||
DocumentData *result;
|
||||
|
@ -368,8 +368,8 @@ void Application::killDownloadSessions() {
|
||||
uint64 ms = getms(), left = MTPAckSendWaiting + MTPKillFileSessionTimeout;
|
||||
for (QMap<int32, uint64>::iterator i = killDownloadSessionTimes.begin(); i != killDownloadSessionTimes.end(); ) {
|
||||
if (i.value() <= ms) {
|
||||
for (int j = 1; j < MTPDownloadSessionsCount; ++j) {
|
||||
MTP::killSession(MTP::dld[j] + i.key());
|
||||
for (int j = 0; j < MTPDownloadSessionsCount; ++j) {
|
||||
MTP::stopSession(MTP::dld[j] + i.key());
|
||||
}
|
||||
i = killDownloadSessionTimes.erase(i);
|
||||
} else {
|
||||
|
@ -22,23 +22,53 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
|
||||
ConfirmBox::ConfirmBox(QString text, QString doneText, QString cancelText) :
|
||||
_confirm(this, doneText.isEmpty() ? lang(lng_continue) : doneText, st::btnSelectDone),
|
||||
_cancel(this, cancelText.isEmpty() ? lang(lng_cancel) : cancelText, st::btnSelectCancel),
|
||||
_text(100), _hiding(false), a_opacity(0, 1), af_opacity(anim::linear) {
|
||||
TextParseOptions _confirmBoxTextOptions = {
|
||||
TextParseLinks | TextParseMultiline | TextParseRichText, // flags
|
||||
0, // maxw
|
||||
0, // maxh
|
||||
Qt::LayoutDirectionAuto, // dir
|
||||
};
|
||||
|
||||
_text.setText(st::boxFont, text, _textPlainOptions);
|
||||
ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const QString &cancelText) : _infoMsg(false),
|
||||
_confirm(this, doneText.isEmpty() ? lang(lng_continue) : doneText, st::btnSelectDone),
|
||||
_cancel(this, cancelText.isEmpty() ? lang(lng_cancel) : cancelText, st::btnSelectCancel),
|
||||
_close(this, QString(), st::btnInfoClose),
|
||||
_text(100), _hiding(false), a_opacity(0, 1), af_opacity(anim::linear) {
|
||||
init(text);
|
||||
}
|
||||
|
||||
ConfirmBox::ConfirmBox(const QString &text, bool noDone, const QString &cancelText) : _infoMsg(true),
|
||||
_confirm(this, QString(), st::btnSelectDone),
|
||||
_cancel(this, QString(), st::btnSelectCancel),
|
||||
_close(this, cancelText.isEmpty() ? lang(lng_close) : cancelText, st::btnInfoClose),
|
||||
_text(100), _hiding(false), a_opacity(0, 1), af_opacity(anim::linear) {
|
||||
init(text);
|
||||
}
|
||||
|
||||
void ConfirmBox::init(const QString &text) {
|
||||
_text.setText(st::boxFont, text, (_infoMsg ? _confirmBoxTextOptions : _textPlainOptions));
|
||||
|
||||
_width = st::confirmWidth;
|
||||
_textWidth = _width - st::boxPadding.left() - st::boxPadding.right();
|
||||
_textHeight = _text.countHeight(_textWidth);
|
||||
_height = st::boxPadding.top() + _textHeight + st::boxPadding.bottom() + _confirm.height();
|
||||
_height = st::boxPadding.top() + _textHeight + st::boxPadding.bottom() + (_infoMsg ? _close.height() : _confirm.height());
|
||||
|
||||
_confirm.move(_width - _confirm.width(), st::boxPadding.top() + _textHeight + st::boxPadding.bottom());
|
||||
_cancel.move(0, st::boxPadding.top() + _textHeight + st::boxPadding.bottom());
|
||||
if (_infoMsg) {
|
||||
_confirm.hide();
|
||||
_cancel.hide();
|
||||
_close.move(0, st::boxPadding.top() + _textHeight + st::boxPadding.bottom());
|
||||
|
||||
connect(&_confirm, SIGNAL(clicked()), this, SIGNAL(confirmed()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onCancel()));
|
||||
connect(&_close, SIGNAL(clicked()), this, SLOT(onCancel()));
|
||||
|
||||
setMouseTracking(_text.hasLinks());
|
||||
} else {
|
||||
_confirm.move(_width - _confirm.width(), st::boxPadding.top() + _textHeight + st::boxPadding.bottom());
|
||||
_cancel.move(0, st::boxPadding.top() + _textHeight + st::boxPadding.bottom());
|
||||
_close.hide();
|
||||
|
||||
connect(&_confirm, SIGNAL(clicked()), this, SIGNAL(confirmed()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onCancel()));
|
||||
}
|
||||
|
||||
resize(_width, _height);
|
||||
|
||||
@ -47,14 +77,73 @@ ConfirmBox::ConfirmBox(QString text, QString doneText, QString cancelText) :
|
||||
hideAll();
|
||||
}
|
||||
|
||||
void ConfirmBox::mouseMoveEvent(QMouseEvent *e) {
|
||||
_lastMousePos = e->globalPos();
|
||||
updateHover();
|
||||
}
|
||||
|
||||
void ConfirmBox::mousePressEvent(QMouseEvent *e) {
|
||||
_lastMousePos = e->globalPos();
|
||||
updateHover();
|
||||
if (textlnkOver()) {
|
||||
textlnkDown(textlnkOver());
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) {
|
||||
_lastMousePos = e->globalPos();
|
||||
updateHover();
|
||||
if (textlnkOver() && textlnkOver() == textlnkDown()) {
|
||||
App::wnd()->hideLayer();
|
||||
textlnkOver()->onClick(e->button());
|
||||
}
|
||||
textlnkDown(TextLinkPtr());
|
||||
}
|
||||
|
||||
void ConfirmBox::leaveEvent(QEvent *e) {
|
||||
if (_myLink) {
|
||||
if (textlnkOver() == _myLink) {
|
||||
textlnkOver(TextLinkPtr());
|
||||
update();
|
||||
}
|
||||
_myLink = TextLinkPtr();
|
||||
setCursor(style::cur_default);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfirmBox::updateLink() {
|
||||
_lastMousePos = QCursor::pos();
|
||||
updateHover();
|
||||
}
|
||||
|
||||
void ConfirmBox::updateHover() {
|
||||
QPoint m(mapFromGlobal(_lastMousePos));
|
||||
bool wasMy = (_myLink == textlnkOver());
|
||||
_myLink = _text.link(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, (_text.maxWidth() < _width) ? style::al_center : style::al_left);
|
||||
if (_myLink != textlnkOver()) {
|
||||
if (wasMy || _myLink || rect().contains(m)) {
|
||||
textlnkOver(_myLink);
|
||||
}
|
||||
setCursor(_myLink ? style::cur_pointer : style::cur_default);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfirmBox::hideAll() {
|
||||
_confirm.hide();
|
||||
_cancel.hide();
|
||||
_close.hide();
|
||||
}
|
||||
|
||||
void ConfirmBox::showAll() {
|
||||
_confirm.show();
|
||||
_cancel.show();
|
||||
if (_infoMsg) {
|
||||
_close.show();
|
||||
} else {
|
||||
_confirm.show();
|
||||
_cancel.show();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfirmBox::keyPressEvent(QKeyEvent *e) {
|
||||
@ -78,11 +167,13 @@ void ConfirmBox::paintEvent(QPaintEvent *e) {
|
||||
// fill bg
|
||||
p.fillRect(0, 0, _width, _height, st::boxBG->b);
|
||||
|
||||
// paint shadows
|
||||
p.fillRect(0, _height - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b);
|
||||
if (!_infoMsg) {
|
||||
// paint shadows
|
||||
p.fillRect(0, _height - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b);
|
||||
|
||||
// paint button sep
|
||||
p.fillRect(st::btnSelectCancel.width, _height - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b);
|
||||
// paint button sep
|
||||
p.fillRect(st::btnSelectCancel.width, _height - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b);
|
||||
}
|
||||
|
||||
// draw box title / text
|
||||
p.setFont(st::boxFont->f);
|
||||
|
@ -24,11 +24,17 @@ class ConfirmBox : public LayeredWidget, public RPCSender {
|
||||
|
||||
public:
|
||||
|
||||
ConfirmBox(QString text, QString doneText = QString(), QString cancelText = QString());
|
||||
ConfirmBox(const QString &text, const QString &doneText = QString(), const QString &cancelText = QString());
|
||||
ConfirmBox(const QString &text, bool noDone, const QString &cancelText = QString());
|
||||
void parentResized();
|
||||
void animStep(float64 ms);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void mouseReleaseEvent(QMouseEvent *e);
|
||||
void leaveEvent(QEvent *e);
|
||||
void updateLink();
|
||||
void startHide();
|
||||
~ConfirmBox();
|
||||
|
||||
@ -43,11 +49,16 @@ public slots:
|
||||
|
||||
private:
|
||||
|
||||
void init(const QString &text);
|
||||
|
||||
bool _infoMsg;
|
||||
|
||||
void hideAll();
|
||||
void showAll();
|
||||
|
||||
int32 _width, _height;
|
||||
FlatButton _confirm, _cancel;
|
||||
BottomButton _close;
|
||||
Text _text;
|
||||
int32 _textWidth, _textHeight;
|
||||
|
||||
@ -56,4 +67,9 @@ private:
|
||||
|
||||
anim::fvalue a_opacity;
|
||||
anim::transition af_opacity;
|
||||
|
||||
void updateHover();
|
||||
|
||||
QPoint _lastMousePos;
|
||||
TextLinkPtr _myLink;
|
||||
};
|
||||
|
@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
static const int32 AppVersion = 6015;
|
||||
static const wchar_t *AppVersionStr = L"0.6.15";
|
||||
static const int32 AppVersion = 6016;
|
||||
static const wchar_t *AppVersionStr = L"0.6.16";
|
||||
|
||||
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
||||
static const wchar_t *AppName = L"Telegram Desktop";
|
||||
|
@ -38,8 +38,7 @@ void FileUploader::uploadMedia(MsgId msgId, const ReadyLocalMedia &media) {
|
||||
}
|
||||
document->status = FileUploading;
|
||||
if (!media.file.isEmpty()) {
|
||||
document->fileName = media.file;
|
||||
document->modDate = QFileInfo(media.file).lastModified();
|
||||
document->location = FileLocation(mtpc_storage_filePartial, media.file);
|
||||
}
|
||||
}
|
||||
queue.insert(msgId, File(media));
|
||||
@ -75,7 +74,7 @@ void FileUploader::currentFailed() {
|
||||
|
||||
void FileUploader::killSessions() {
|
||||
for (int i = 0; i < MTPUploadSessionsCount; ++i) {
|
||||
MTP::killSession(MTP::upl[i]);
|
||||
MTP::stopSession(MTP::upl[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,7 +203,7 @@ void FileUploader::clear() {
|
||||
dcMap.clear();
|
||||
sentSize = 0;
|
||||
for (int32 i = 0; i < MTPUploadSessionsCount; ++i) {
|
||||
MTP::killSession(MTP::upl[i]);
|
||||
MTP::stopSession(MTP::upl[i]);
|
||||
sentSizes[i] = 0;
|
||||
}
|
||||
killSessionsTimer.stop();
|
||||
|
@ -203,3 +203,59 @@ public:
|
||||
void clearStorageImages();
|
||||
void clearAllImages();
|
||||
int64 imageCacheSize();
|
||||
|
||||
struct FileLocation {
|
||||
FileLocation(mtpTypeId type, const QString &name, const QDateTime &modified, qint32 size) : type(type), name(name), modified(modified), size(size) {
|
||||
}
|
||||
FileLocation(mtpTypeId type, const QString &name) : type(type), name(name) {
|
||||
QFileInfo f(name);
|
||||
if (f.exists()) {
|
||||
qint64 s = f.size();
|
||||
if (s > INT_MAX) {
|
||||
this->name = QString();
|
||||
size = 0;
|
||||
type = mtpc_storage_fileUnknown;
|
||||
} else {
|
||||
modified = f.lastModified();
|
||||
size = qint32(s);
|
||||
}
|
||||
} else {
|
||||
this->name = QString();
|
||||
size = 0;
|
||||
type = mtpc_storage_fileUnknown;
|
||||
}
|
||||
}
|
||||
FileLocation() : size(0) {
|
||||
}
|
||||
bool check() const {
|
||||
if (name.isEmpty()) return false;
|
||||
QFileInfo f(name);
|
||||
if (!f.exists()) return false;
|
||||
|
||||
quint64 s = f.size();
|
||||
if (s > INT_MAX) return false;
|
||||
|
||||
return (f.lastModified() == modified) && (qint32(s) == size);
|
||||
}
|
||||
mtpTypeId type;
|
||||
QString name;
|
||||
QDateTime modified;
|
||||
qint32 size;
|
||||
};
|
||||
inline bool operator==(const FileLocation &a, const FileLocation &b) {
|
||||
return a.type == b.type && a.name == b.name && a.modified == b.modified && a.size == b.size;
|
||||
}
|
||||
inline bool operator!=(const FileLocation &a, const FileLocation &b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
typedef QPair<uint64, uint64> MediaKey;
|
||||
inline uint64 mediaMix32To64(mtpTypeId a, int32 b) {
|
||||
return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b));
|
||||
}
|
||||
inline MediaKey mediaKey(mtpTypeId type, int32 dc, const int64 &id) {
|
||||
return MediaKey(mediaMix32To64(type, dc), id);
|
||||
}
|
||||
inline StorageKey mediaKey(const MTPDfileLocation &location) {
|
||||
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
|
||||
}
|
||||
|
@ -516,6 +516,11 @@ void VideoCancelLink::onClick(Qt::MouseButton button) const {
|
||||
data->cancel();
|
||||
}
|
||||
|
||||
VideoData::VideoData(const VideoId &id, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) :
|
||||
id(id), access(access), user(user), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
|
||||
location = Local::readFileLocation(mediaKey(mtpc_inputVideoFileLocation, dc, id));
|
||||
}
|
||||
|
||||
void VideoData::save(const QString &toFile) {
|
||||
cancel(true);
|
||||
loader = new mtpFileLoader(dc, id, access, mtpc_inputVideoFileLocation, toFile, size);
|
||||
@ -524,6 +529,12 @@ void VideoData::save(const QString &toFile) {
|
||||
loader->start();
|
||||
}
|
||||
|
||||
QString VideoData::already(bool check) {
|
||||
if (!check) return location.name;
|
||||
if (!location.check()) location = Local::readFileLocation(mediaKey(mtpc_inputVideoFileLocation, dc, id));
|
||||
return location.name;
|
||||
}
|
||||
|
||||
void AudioOpenLink::onClick(Qt::MouseButton button) const {
|
||||
AudioData *data = audio();
|
||||
if ((!data->user && !data->date) || button != Qt::LeftButton) return;
|
||||
@ -591,6 +602,11 @@ void AudioCancelLink::onClick(Qt::MouseButton button) const {
|
||||
data->cancel();
|
||||
}
|
||||
|
||||
AudioData::AudioData(const AudioId &id, const uint64 &access, int32 user, int32 date, int32 duration, int32 dc, int32 size) :
|
||||
id(id), access(access), user(user), date(date), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
|
||||
location = Local::readFileLocation(mediaKey(mtpc_inputAudioFileLocation, dc, id));
|
||||
}
|
||||
|
||||
void AudioData::save(const QString &toFile) {
|
||||
cancel(true);
|
||||
loader = new mtpFileLoader(dc, id, access, mtpc_inputAudioFileLocation, toFile, size, (size < AudioVoiceMsgInMemory));
|
||||
@ -599,6 +615,12 @@ void AudioData::save(const QString &toFile) {
|
||||
loader->start();
|
||||
}
|
||||
|
||||
QString AudioData::already(bool check) {
|
||||
if (!check) return location.name;
|
||||
if (!location.check()) location = Local::readFileLocation(mediaKey(mtpc_inputAudioFileLocation, dc, id));
|
||||
return location.name;
|
||||
}
|
||||
|
||||
void DocumentOpenLink::onClick(Qt::MouseButton button) const {
|
||||
DocumentData *data = document();
|
||||
if ((!data->user && !data->date) || button != Qt::LeftButton) return;
|
||||
@ -694,6 +716,11 @@ void DocumentCancelLink::onClick(Qt::MouseButton button) const {
|
||||
data->cancel();
|
||||
}
|
||||
|
||||
DocumentData::DocumentData(const DocumentId &id, const uint64 &access, int32 user, int32 date, const QString &name, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size) :
|
||||
id(id), access(access), user(user), date(date), name(name), mime(mime), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
|
||||
location = Local::readFileLocation(mediaKey(mtpc_inputDocumentFileLocation, dc, id));
|
||||
}
|
||||
|
||||
void DocumentData::save(const QString &toFile) {
|
||||
cancel(true);
|
||||
loader = new mtpFileLoader(dc, id, access, mtpc_inputDocumentFileLocation, toFile, size);
|
||||
@ -702,6 +729,12 @@ void DocumentData::save(const QString &toFile) {
|
||||
loader->start();
|
||||
}
|
||||
|
||||
QString DocumentData::already(bool check) {
|
||||
if (!check) return location.name;
|
||||
if (!location.check()) location = Local::readFileLocation(mediaKey(mtpc_inputDocumentFileLocation, dc, id));
|
||||
return location.name;
|
||||
}
|
||||
|
||||
void PeerLink::onClick(Qt::MouseButton button) const {
|
||||
if (button == Qt::LeftButton && App::main()) {
|
||||
App::main()->showPeerProfile(peer());
|
||||
@ -4089,6 +4122,7 @@ void HistoryMessage::drawInDialog(QPainter &p, const QRect &r, bool act, const H
|
||||
p.setFont(st::dlgHistFont->f);
|
||||
p.setPen((act ? st::dlgActiveColor : (_media ? st::dlgSystemColor : st::dlgTextColor))->p);
|
||||
cache.drawElided(p, r.left(), r.top(), r.width(), r.height() / st::dlgHistFont->height);
|
||||
textstyleRestore();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,10 +219,8 @@ enum FileStatus {
|
||||
};
|
||||
|
||||
struct VideoData {
|
||||
VideoData(const VideoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0) :
|
||||
id(id), access(access), user(user), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
|
||||
memset(md5, 0, sizeof(md5));
|
||||
}
|
||||
VideoData(const VideoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
|
||||
|
||||
void forget() {
|
||||
thumb->forget();
|
||||
}
|
||||
@ -237,8 +235,7 @@ struct VideoData {
|
||||
l->deleteLater();
|
||||
l->rpcInvalidate();
|
||||
}
|
||||
fileName = QString();
|
||||
modDate = QDateTime();
|
||||
location = FileLocation();
|
||||
if (!beforeDownload) {
|
||||
openOnSave = openOnSaveMsgId = 0;
|
||||
}
|
||||
@ -246,26 +243,14 @@ struct VideoData {
|
||||
|
||||
void finish() {
|
||||
if (loader->done()) {
|
||||
fileName = loader->fileName();
|
||||
modDate = fileName.isEmpty() ? QDateTime() : QFileInfo(fileName).lastModified();
|
||||
location = FileLocation(loader->fileType(), loader->fileName());
|
||||
}
|
||||
loader->deleteLater();
|
||||
loader->rpcInvalidate();
|
||||
loader = 0;
|
||||
}
|
||||
|
||||
QString already(bool check = false) {
|
||||
if (!check) return fileName;
|
||||
|
||||
QString res = modDate.isNull() ? QString() : fileName;
|
||||
if (!res.isEmpty()) {
|
||||
QFileInfo f(res);
|
||||
if (f.exists() && f.lastModified() <= modDate) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
QString already(bool check = false);
|
||||
|
||||
VideoId id;
|
||||
uint64 access;
|
||||
@ -283,9 +268,7 @@ struct VideoData {
|
||||
mtpTypeId fileType;
|
||||
int32 openOnSave, openOnSaveMsgId;
|
||||
mtpFileLoader *loader;
|
||||
QString fileName;
|
||||
QDateTime modDate;
|
||||
int32 md5[8];
|
||||
FileLocation location;
|
||||
};
|
||||
|
||||
class VideoLink : public ITextLink {
|
||||
@ -323,10 +306,8 @@ public:
|
||||
};
|
||||
|
||||
struct AudioData {
|
||||
AudioData(const AudioId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 dc = 0, int32 size = 0) :
|
||||
id(id), access(access), user(user), date(date), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
|
||||
memset(md5, 0, sizeof(md5));
|
||||
}
|
||||
AudioData(const AudioId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 dc = 0, int32 size = 0);
|
||||
|
||||
void forget() {
|
||||
}
|
||||
|
||||
@ -340,8 +321,7 @@ struct AudioData {
|
||||
l->deleteLater();
|
||||
l->rpcInvalidate();
|
||||
}
|
||||
fileName = QString();
|
||||
modDate = QDateTime();
|
||||
location = FileLocation();
|
||||
if (!beforeDownload) {
|
||||
openOnSave = openOnSaveMsgId = 0;
|
||||
}
|
||||
@ -349,8 +329,7 @@ struct AudioData {
|
||||
|
||||
void finish() {
|
||||
if (loader->done()) {
|
||||
fileName = loader->fileName();
|
||||
modDate = fileName.isEmpty() ? QDateTime() : QFileInfo(fileName).lastModified();
|
||||
location = FileLocation(loader->fileType(), loader->fileName());
|
||||
data = loader->bytes();
|
||||
}
|
||||
loader->deleteLater();
|
||||
@ -358,18 +337,7 @@ struct AudioData {
|
||||
loader = 0;
|
||||
}
|
||||
|
||||
QString already(bool check = false) {
|
||||
if (!check) return fileName;
|
||||
|
||||
QString res = modDate.isNull() ? QString() : fileName;
|
||||
if (!res.isEmpty()) {
|
||||
QFileInfo f(res);
|
||||
if (f.exists() && f.lastModified() <= modDate) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
QString already(bool check = false);
|
||||
|
||||
AudioId id;
|
||||
uint64 access;
|
||||
@ -384,8 +352,7 @@ struct AudioData {
|
||||
|
||||
int32 openOnSave, openOnSaveMsgId;
|
||||
mtpFileLoader *loader;
|
||||
QString fileName;
|
||||
QDateTime modDate;
|
||||
FileLocation location;
|
||||
QByteArray data;
|
||||
int32 md5[8];
|
||||
};
|
||||
@ -425,10 +392,8 @@ public:
|
||||
};
|
||||
|
||||
struct DocumentData {
|
||||
DocumentData(const DocumentId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &name = QString(), const QString &mime = QString(), const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0) :
|
||||
id(id), access(access), user(user), date(date), name(name), mime(mime), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
|
||||
memset(md5, 0, sizeof(md5));
|
||||
}
|
||||
DocumentData(const DocumentId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &name = QString(), const QString &mime = QString(), const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
|
||||
|
||||
void forget() {
|
||||
thumb->forget();
|
||||
}
|
||||
@ -443,8 +408,7 @@ struct DocumentData {
|
||||
l->deleteLater();
|
||||
l->rpcInvalidate();
|
||||
}
|
||||
fileName = QString();
|
||||
modDate = QDateTime();
|
||||
location = FileLocation();
|
||||
if (!beforeDownload) {
|
||||
openOnSave = openOnSaveMsgId = 0;
|
||||
}
|
||||
@ -452,26 +416,14 @@ struct DocumentData {
|
||||
|
||||
void finish() {
|
||||
if (loader->done()) {
|
||||
fileName = loader->fileName();
|
||||
modDate = fileName.isEmpty() ? QDateTime() : QFileInfo(fileName).lastModified();
|
||||
location = FileLocation(loader->fileType(), loader->fileName());
|
||||
}
|
||||
loader->deleteLater();
|
||||
loader->rpcInvalidate();
|
||||
loader = 0;
|
||||
}
|
||||
|
||||
QString already(bool check = false) {
|
||||
if (!check) return fileName;
|
||||
|
||||
QString res = modDate.isNull() ? QString() : fileName;
|
||||
if (!res.isEmpty()) {
|
||||
QFileInfo f(res);
|
||||
if (f.exists() && f.lastModified() <= modDate) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
QString already(bool check = false);
|
||||
|
||||
DocumentId id;
|
||||
uint64 access;
|
||||
@ -487,8 +439,7 @@ struct DocumentData {
|
||||
|
||||
int32 openOnSave, openOnSaveMsgId;
|
||||
mtpFileLoader *loader;
|
||||
QString fileName;
|
||||
QDateTime modDate;
|
||||
FileLocation location;
|
||||
int32 md5[8];
|
||||
};
|
||||
|
||||
|
@ -438,6 +438,7 @@ namespace {
|
||||
lskDraft, // data: PeerId peer
|
||||
lskDraftPosition, // data: PeerId peer
|
||||
lskStorage, // data: StorageKey location
|
||||
lskLocations, // no data
|
||||
};
|
||||
|
||||
typedef QMap<PeerId, FileKey> DraftsMap;
|
||||
@ -450,8 +451,85 @@ namespace {
|
||||
StorageMap _storageMap;
|
||||
int32 _storageFilesSize = 0;
|
||||
|
||||
typedef QMultiMap<MediaKey, FileLocation> FileLocations;
|
||||
FileLocations _fileLocations;
|
||||
typedef QPair<MediaKey, FileLocation> FileLocationPair;
|
||||
typedef QMap<QString, FileLocationPair> FileLocationPairs;
|
||||
FileLocationPairs _fileLocationPairs;
|
||||
FileKey _locationsKey = 0;
|
||||
|
||||
bool _mapChanged = false;
|
||||
int32 _oldMapVersion = 0;
|
||||
|
||||
enum WriteMapWhen {
|
||||
WriteMapNow,
|
||||
WriteMapFast,
|
||||
WriteMapSoon,
|
||||
};
|
||||
|
||||
void _writeMap(WriteMapWhen when = WriteMapSoon);
|
||||
|
||||
void _writeLocations(WriteMapWhen when = WriteMapSoon) {
|
||||
if (when != WriteMapNow) {
|
||||
_manager->writeLocations(when == WriteMapFast);
|
||||
return;
|
||||
}
|
||||
_manager->writingLocations();
|
||||
if (_fileLocations.isEmpty()) {
|
||||
if (_locationsKey) {
|
||||
clearKey(_locationsKey);
|
||||
_locationsKey = 0;
|
||||
_mapChanged = true;
|
||||
_writeMap();
|
||||
}
|
||||
} else {
|
||||
if (!_locationsKey) {
|
||||
while (!_locationsKey) {
|
||||
_locationsKey = genKey();
|
||||
}
|
||||
_mapChanged = true;
|
||||
_writeMap(WriteMapFast);
|
||||
}
|
||||
quint32 size = 0;
|
||||
for (FileLocations::const_iterator i = _fileLocations.cbegin(); i != _fileLocations.cend(); ++i) {
|
||||
size += sizeof(quint64) * 2 + sizeof(quint32) + sizeof(quint32) + i.value().name.size() * sizeof(ushort) + sizeof(qint64) + sizeof(quint32) + sizeof(qint8) + sizeof(quint32);
|
||||
}
|
||||
EncryptedDescriptor data(size);
|
||||
for (FileLocations::const_iterator i = _fileLocations.cbegin(); i != _fileLocations.cend(); ++i) {
|
||||
data.stream << quint64(i.key().first) << quint64(i.key().second) << quint32(i.value().type) << i.value().name << i.value().modified << quint32(i.value().size);
|
||||
}
|
||||
FileWriteDescriptor file(_locationsKey);
|
||||
file.writeEncrypted(data);
|
||||
}
|
||||
}
|
||||
|
||||
void _readLocations() {
|
||||
FileReadDescriptor locations;
|
||||
if (!readEncryptedFile(locations, toFilePart(_locationsKey))) {
|
||||
clearKey(_locationsKey);
|
||||
_locationsKey = 0;
|
||||
_writeMap();
|
||||
return;
|
||||
}
|
||||
|
||||
while (!locations.stream.atEnd()) {
|
||||
quint64 first, second;
|
||||
FileLocation loc;
|
||||
quint32 type;
|
||||
locations.stream >> first >> second >> type >> loc.name >> loc.modified >> loc.size;
|
||||
|
||||
MediaKey key(first, second);
|
||||
loc.type = type;
|
||||
|
||||
if (loc.check()) {
|
||||
_fileLocations.insert(key, loc);
|
||||
_fileLocationPairs.insert(loc.name, FileLocationPair(key, loc));
|
||||
} else {
|
||||
_writeLocations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Local::ReadMapState _readMap(const QByteArray &pass) {
|
||||
uint64 ms = getms();
|
||||
QByteArray dataNameUtf8 = cDataFile().toUtf8();
|
||||
@ -500,6 +578,7 @@ namespace {
|
||||
DraftsNotReadMap draftsNotReadMap;
|
||||
StorageMap storageMap;
|
||||
qint64 storageFilesSize = 0;
|
||||
quint64 locationsKey = 0;
|
||||
while (!map.stream.atEnd()) {
|
||||
quint32 keyType;
|
||||
map.stream >> keyType;
|
||||
@ -537,6 +616,9 @@ namespace {
|
||||
storageFilesSize += size;
|
||||
}
|
||||
} break;
|
||||
case lskLocations: {
|
||||
map.stream >> locationsKey;
|
||||
} break;
|
||||
default:
|
||||
LOG(("App Error: unknown key type in encrypted map: %1").arg(keyType));
|
||||
return Local::ReadMapFailed;
|
||||
@ -552,19 +634,19 @@ namespace {
|
||||
_draftsNotReadMap = draftsNotReadMap;
|
||||
_storageMap = storageMap;
|
||||
_storageFilesSize = storageFilesSize;
|
||||
_locationsKey = locationsKey;
|
||||
_mapChanged = false;
|
||||
_oldMapVersion = mapData.version;
|
||||
|
||||
if (_locationsKey) {
|
||||
_readLocations();
|
||||
}
|
||||
|
||||
LOG(("Map read time: %1").arg(getms() - ms));
|
||||
return Local::ReadMapDone;
|
||||
}
|
||||
|
||||
enum WriteMapWhen {
|
||||
WriteMapNow,
|
||||
WriteMapFast,
|
||||
WriteMapSoon,
|
||||
};
|
||||
void _writeMap(WriteMapWhen when = WriteMapSoon) {
|
||||
void _writeMap(WriteMapWhen when) {
|
||||
if (when != WriteMapNow) {
|
||||
_manager->writeMap(when == WriteMapFast);
|
||||
return;
|
||||
@ -601,6 +683,7 @@ namespace {
|
||||
if (!_draftsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftsMap.size() * sizeof(quint64) * 2;
|
||||
if (!_draftsPositionsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftsPositionsMap.size() * sizeof(quint64) * 2;
|
||||
if (!_storageMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _storageMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
|
||||
if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
EncryptedDescriptor mapData(mapSize);
|
||||
if (!_draftsMap.isEmpty()) {
|
||||
mapData.stream << quint32(lskDraft) << quint32(_draftsMap.size());
|
||||
@ -620,6 +703,9 @@ namespace {
|
||||
mapData.stream << quint64(i.value().first) << quint64(i.key().first) << quint64(i.key().second) << qint32(i.value().second);
|
||||
}
|
||||
}
|
||||
if (_locationsKey) {
|
||||
mapData.stream << quint32(lskLocations) << quint64(_locationsKey);
|
||||
}
|
||||
map.writeEncrypted(mapData);
|
||||
|
||||
map.finish();
|
||||
@ -634,6 +720,8 @@ namespace _local_inner {
|
||||
Manager::Manager() {
|
||||
_mapWriteTimer.setSingleShot(true);
|
||||
connect(&_mapWriteTimer, SIGNAL(timeout()), this, SLOT(mapWriteTimeout()));
|
||||
_locationsWriteTimer.setSingleShot(true);
|
||||
connect(&_locationsWriteTimer, SIGNAL(timeout()), this, SLOT(locationsWriteTimeout()));
|
||||
}
|
||||
|
||||
void Manager::writeMap(bool fast) {
|
||||
@ -648,14 +736,32 @@ namespace _local_inner {
|
||||
_mapWriteTimer.stop();
|
||||
}
|
||||
|
||||
void Manager::writeLocations(bool fast) {
|
||||
if (!_locationsWriteTimer.isActive() || fast) {
|
||||
_locationsWriteTimer.start(fast ? 1 : WriteMapTimeout);
|
||||
} else if (_locationsWriteTimer.remainingTime() <= 0) {
|
||||
locationsWriteTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::writingLocations() {
|
||||
_locationsWriteTimer.stop();
|
||||
}
|
||||
|
||||
void Manager::mapWriteTimeout() {
|
||||
_writeMap(WriteMapNow);
|
||||
}
|
||||
|
||||
void Manager::locationsWriteTimeout() {
|
||||
_writeLocations(WriteMapNow);
|
||||
}
|
||||
|
||||
void Manager::finish() {
|
||||
if (_mapWriteTimer.isActive()) {
|
||||
mapWriteTimeout();
|
||||
_mapWriteTimer.stop();
|
||||
}
|
||||
if (_locationsWriteTimer.isActive()) {
|
||||
locationsWriteTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
@ -799,6 +905,46 @@ namespace Local {
|
||||
return (_draftsPositionsMap.constFind(peer) != _draftsPositionsMap.cend());
|
||||
}
|
||||
|
||||
void writeFileLocation(const MediaKey &location, const FileLocation &local) {
|
||||
if (local.name.isEmpty()) return;
|
||||
|
||||
FileLocationPairs::iterator i = _fileLocationPairs.find(local.name);
|
||||
if (i != _fileLocationPairs.cend()) {
|
||||
if (i.value().second == local) {
|
||||
return;
|
||||
}
|
||||
if (i.value().first != location) {
|
||||
for (FileLocations::iterator j = _fileLocations.find(i.value().first), e = _fileLocations.end(); (j != e) && (j.key() == i.value().first);) {
|
||||
if (j.value() == i.value().second) {
|
||||
_fileLocations.erase(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_fileLocationPairs.erase(i);
|
||||
}
|
||||
}
|
||||
_fileLocations.insert(location, local);
|
||||
_fileLocationPairs.insert(local.name, FileLocationPair(location, local));
|
||||
_writeLocations(WriteMapFast);
|
||||
}
|
||||
|
||||
FileLocation readFileLocation(const MediaKey &location, bool check) {
|
||||
FileLocations::iterator i = _fileLocations.find(location);
|
||||
for (FileLocations::iterator i = _fileLocations.find(location); (i != _fileLocations.end()) && (i.key() == location);) {
|
||||
if (check) {
|
||||
QFileInfo info(i.value().name);
|
||||
if (!info.exists() || info.lastModified() != i.value().modified || info.size() != i.value().size) {
|
||||
_fileLocationPairs.remove(i.value().name);
|
||||
i = _fileLocations.erase(i);
|
||||
_writeLocations();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return i.value();
|
||||
}
|
||||
return FileLocation();
|
||||
}
|
||||
|
||||
qint32 _storageImageSize(qint32 rawlen) {
|
||||
// fulllen + storagekey + type + len + data
|
||||
qint32 result = sizeof(uint32) + sizeof(quint64) * 2 + sizeof(quint32) + sizeof(quint32) + rawlen;
|
||||
|
@ -30,15 +30,20 @@ namespace _local_inner {
|
||||
|
||||
void writeMap(bool fast);
|
||||
void writingMap();
|
||||
void writeLocations(bool fast);
|
||||
void writingLocations();
|
||||
void finish();
|
||||
|
||||
public slots:
|
||||
|
||||
void mapWriteTimeout();
|
||||
void locationsWriteTimeout();
|
||||
|
||||
private:
|
||||
|
||||
QTimer _mapWriteTimer;
|
||||
QTimer _locationsWriteTimer;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@ -94,6 +99,9 @@ namespace Local {
|
||||
MessageCursor readDraftPositions(const PeerId &peer);
|
||||
bool hasDraftPositions(const PeerId &peer);
|
||||
|
||||
void writeFileLocation(const StorageKey &location, const FileLocation &local);
|
||||
FileLocation readFileLocation(const StorageKey &location, bool check = true);
|
||||
|
||||
void writeImage(const StorageKey &location, const ImagePtr &img);
|
||||
void writeImage(const StorageKey &location, const StorageImageSaved &jpeg, bool overwrite = true);
|
||||
StorageImageSaved readImage(const StorageKey &location);
|
||||
|
@ -1854,14 +1854,22 @@ void MainWidget::openUserByName(const QString &username) {
|
||||
if (user) {
|
||||
emit showPeerAsync(user->id, 0, false, true);
|
||||
} else {
|
||||
MTP::send(MTPcontacts_ResolveUsername(MTP_string(username)), rpcDone(&MainWidget::usernameResolveDone));
|
||||
MTP::send(MTPcontacts_ResolveUsername(MTP_string(username)), rpcDone(&MainWidget::usernameResolveDone), rpcFail(&MainWidget::usernameResolveFail, username));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::usernameResolveDone(const MTPUser &user) {
|
||||
App::wnd()->hideLayer();
|
||||
showPeer(App::feedUsers(MTP_vector<MTPUser>(1, user))->id, 0, false, true);
|
||||
}
|
||||
|
||||
bool MainWidget::usernameResolveFail(QString name, const RPCError &error) {
|
||||
if (error.code() == 400) {
|
||||
App::wnd()->showLayer(new ConfirmBox(lang(lng_username_not_found).replace(qsl("{user}"), name), true));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainWidget::startFull(const MTPVector<MTPUser> &users) {
|
||||
const QVector<MTPUser> &v(users.c_vector().v);
|
||||
if (v.isEmpty() || v[0].type() != mtpc_userSelf) { // wtf?..
|
||||
@ -2408,6 +2416,9 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||
|
||||
case mtpc_updateServiceNotification: {
|
||||
const MTPDupdateServiceNotification &d(update.c_updateServiceNotification());
|
||||
if (d.vpopup.v) {
|
||||
App::wnd()->showLayer(new ConfirmBox(qs(d.vmessage), true));
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updatePrivacy: {
|
||||
|
@ -361,6 +361,7 @@ private:
|
||||
bool updateFail(const RPCError &e);
|
||||
|
||||
void usernameResolveDone(const MTPUser &user);
|
||||
bool usernameResolveFail(QString name, const RPCError &error);
|
||||
|
||||
void hideAll();
|
||||
void showAll();
|
||||
|
@ -711,6 +711,15 @@ namespace MTP {
|
||||
}
|
||||
}
|
||||
|
||||
void stopSession(int32 dc) {
|
||||
Sessions::iterator i = sessions.find(dc);
|
||||
if (i != sessions.end()) {
|
||||
if (i.value() != mainSession) { // don't stop main session
|
||||
i.value()->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32 state(mtpRequestId requestId) {
|
||||
if (requestId > 0) {
|
||||
QMutexLocker locker(&requestByDCLock);
|
||||
|
@ -99,6 +99,7 @@ namespace MTP {
|
||||
}
|
||||
void cancel(mtpRequestId req);
|
||||
void killSession(int32 dc);
|
||||
void stopSession(int32 dc);
|
||||
|
||||
enum {
|
||||
RequestSent = 0,
|
||||
|
@ -1125,7 +1125,7 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne
|
||||
qRegisterMetaType<QVector<quint64> >("QVector<quint64>");
|
||||
}
|
||||
|
||||
connect(this, SIGNAL(needToSendAsync()), sessionData->owner(), SIGNAL(needToSend()), Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(needToSendAsync()), sessionData->owner(), SLOT(needToResumeAndSend()), Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(sendAnythingAsync(quint64)), sessionData->owner(), SLOT(sendAnything(quint64)), Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(sendHttpWaitAsync()), sessionData->owner(), SLOT(sendHttpWait()), Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(sendPongAsync(quint64,quint64)), sessionData->owner(), SLOT(sendPong(quint64,quint64)), Qt::QueuedConnection);
|
||||
|
@ -57,7 +57,7 @@ id(0), access(0), fileIsOpen(false), size(size), type(mtpc_storage_fileUnknown)
|
||||
|
||||
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size) : prev(0), next(0),
|
||||
priority(0), inQueue(false), complete(false), triedLocal(false), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
|
||||
dc(dc), locationType(locType),
|
||||
dc(dc), locationType(locType), volume(0), local(0), secret(0),
|
||||
id(id), access(access), file(to), fname(to), fileIsOpen(false), duplicateInData(false), size(size), type(mtpc_storage_fileUnknown) {
|
||||
LoaderQueues::iterator i = queues.find(MTP::dld[0] + dc);
|
||||
if (i == queues.cend()) {
|
||||
@ -68,7 +68,7 @@ id(id), access(access), file(to), fname(to), fileIsOpen(false), duplicateInData(
|
||||
|
||||
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size, bool todata) : prev(0), next(0),
|
||||
priority(0), inQueue(false), complete(false), triedLocal(false), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
|
||||
dc(dc), locationType(locType),
|
||||
dc(dc), locationType(locType), volume(0), local(0), secret(0),
|
||||
id(id), access(access), file(to), fname(to), fileIsOpen(false), duplicateInData(todata), size(size), type(mtpc_storage_fileUnknown) {
|
||||
LoaderQueues::iterator i = queues.find(MTP::dld[0] + dc);
|
||||
if (i == queues.cend()) {
|
||||
@ -171,9 +171,7 @@ bool mtpFileLoader::loadPart() {
|
||||
}
|
||||
}
|
||||
|
||||
if (dcIndex) {
|
||||
App::app()->killDownloadSessionsStop(dc);
|
||||
}
|
||||
App::app()->killDownloadSessionsStop(dc);
|
||||
|
||||
mtpRequestId reqId = MTP::send(MTPupload_GetFile(MTPupload_getFile(loc, MTP_int(offset), MTP_int(limit))), rpcDone(&mtpFileLoader::partLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::dld[dcIndex] + dc, 50);
|
||||
|
||||
@ -250,12 +248,14 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
|
||||
removeFromQueue();
|
||||
App::wnd()->update();
|
||||
App::wnd()->notifyUpdateAllPhotos();
|
||||
if (!queue->queries && dcIndex) {
|
||||
if (!queue->queries) {
|
||||
App::app()->killDownloadSessionsStart(dc);
|
||||
}
|
||||
|
||||
if (!locationType && triedLocal && (fname.isEmpty() || duplicateInData)) {
|
||||
Local::writeImage(storageKey(dc, volume, local), StorageImageSaved(type, data));
|
||||
} else if (locationType && triedLocal && !fname.isEmpty()) {
|
||||
Local::writeFileLocation(mediaKey(locationType, dc, id), FileLocation(type, fname));
|
||||
}
|
||||
}
|
||||
emit progress(this);
|
||||
@ -291,31 +291,35 @@ void mtpFileLoader::pause() {
|
||||
|
||||
void mtpFileLoader::start(bool loadFirst, bool prior) {
|
||||
if (complete) return;
|
||||
if (!locationType && !triedLocal) {
|
||||
triedLocal = true;
|
||||
StorageImageSaved cached = Local::readImage(storageKey(dc, volume, local));
|
||||
if (cached.type != mtpc_storage_fileUnknown) {
|
||||
data = cached.data;
|
||||
if (!fname.isEmpty() && duplicateInData) {
|
||||
if (!fileIsOpen) fileIsOpen = file.open(QIODevice::WriteOnly);
|
||||
if (!fileIsOpen) {
|
||||
return finishFail();
|
||||
if (!triedLocal) {
|
||||
if (!locationType) {
|
||||
triedLocal = true;
|
||||
StorageImageSaved cached = Local::readImage(storageKey(dc, volume, local));
|
||||
if (cached.type != mtpc_storage_fileUnknown) {
|
||||
data = cached.data;
|
||||
if (!fname.isEmpty() && duplicateInData) {
|
||||
if (!fileIsOpen) fileIsOpen = file.open(QIODevice::WriteOnly);
|
||||
if (!fileIsOpen) {
|
||||
return finishFail();
|
||||
}
|
||||
if (file.write(data) != qint64(data.size())) {
|
||||
return finishFail();
|
||||
}
|
||||
}
|
||||
if (file.write(data) != qint64(data.size())) {
|
||||
return finishFail();
|
||||
type = cached.type;
|
||||
complete = true;
|
||||
if (fileIsOpen) {
|
||||
file.close();
|
||||
fileIsOpen = false;
|
||||
psPostprocessFile(QFileInfo(file).absoluteFilePath());
|
||||
}
|
||||
App::wnd()->update();
|
||||
App::wnd()->notifyUpdateAllPhotos();
|
||||
emit progress(this);
|
||||
return loadNext();
|
||||
}
|
||||
type = cached.type;
|
||||
complete = true;
|
||||
if (fileIsOpen) {
|
||||
file.close();
|
||||
fileIsOpen = false;
|
||||
psPostprocessFile(QFileInfo(file).absoluteFilePath());
|
||||
}
|
||||
App::wnd()->update();
|
||||
App::wnd()->notifyUpdateAllPhotos();
|
||||
emit progress(this);
|
||||
return loadNext();
|
||||
} else if (locationType && !fname.isEmpty()) {
|
||||
triedLocal = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,18 +437,16 @@ void mtpFileLoader::cancelRequests() {
|
||||
if (requests.isEmpty()) return;
|
||||
|
||||
int32 limit = locationType ? DocumentDownloadPartSize : DownloadPartSize;
|
||||
bool wasIndex = false;
|
||||
DataRequested &dr(_dataRequested[dc]);
|
||||
for (Requests::const_iterator i = requests.cbegin(), e = requests.cend(); i != e; ++i) {
|
||||
MTP::cancel(i.key());
|
||||
int32 dcIndex = i.value();
|
||||
dr.v[dcIndex] -= limit;
|
||||
if (dcIndex) wasIndex = true;
|
||||
}
|
||||
queue->queries -= requests.size();
|
||||
requests.clear();
|
||||
|
||||
if (!queue->queries && wasIndex) {
|
||||
if (!queue->queries) {
|
||||
App::app()->killDownloadSessionsStart(dc);
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ void MTProtoSession::start(int32 dcenter, uint32 connects) {
|
||||
connect(&timeouter, SIGNAL(timeout()), this, SLOT(checkRequestsByTimer()));
|
||||
timeouter.start(1000);
|
||||
|
||||
connect(&sender, SIGNAL(timeout()), this, SIGNAL(needToSend()));
|
||||
connect(&sender, SIGNAL(timeout()), this, SLOT(needToResumeAndSend()));
|
||||
|
||||
MTProtoDCMap &dcs(mtpDCMap());
|
||||
|
||||
@ -124,6 +124,7 @@ void MTProtoSession::restart() {
|
||||
}
|
||||
|
||||
void MTProtoSession::stop() {
|
||||
DEBUG_LOG(("Session Info: stopping session %1").arg(dcId));
|
||||
while (!connections.isEmpty()) {
|
||||
connections.back()->stop();
|
||||
connections.pop_back();
|
||||
@ -152,10 +153,32 @@ void MTProtoSession::sendAnything(quint64 msCanWait) {
|
||||
DEBUG_LOG(("MTP Info: dc %1 stopped send timer, can wait for %2ms from current %3").arg(dcId).arg(msWait).arg(msSendCall));
|
||||
sender.stop();
|
||||
msSendCall = 0;
|
||||
emit needToSend();
|
||||
needToResumeAndSend();
|
||||
}
|
||||
}
|
||||
|
||||
void MTProtoSession::needToResumeAndSend() {
|
||||
if (connections.isEmpty()) {
|
||||
DEBUG_LOG(("Session Info: resuming session %1").arg(dcId));
|
||||
MTProtoDCMap &dcs(mtpDCMap());
|
||||
|
||||
connections.reserve(cConnectionsInSession());
|
||||
for (uint32 i = 0; i < cConnectionsInSession(); ++i) {
|
||||
connections.push_back(new MTProtoConnection());
|
||||
if (!connections.back()->start(&data, dcId)) {
|
||||
for (MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend(); j != e; ++j) {
|
||||
delete *j;
|
||||
}
|
||||
connections.clear();
|
||||
DEBUG_LOG(("Session Info: could not start connection %1 to dc %2").arg(i).arg(dcId));
|
||||
dcId = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
emit needToSend();
|
||||
}
|
||||
|
||||
void MTProtoSession::sendHttpWait() {
|
||||
send(MTPHttpWait(MTP_http_wait(MTP_int(100), MTP_int(30), MTP_int(25000))), RPCResponseHandler(), 50);
|
||||
}
|
||||
|
@ -251,6 +251,8 @@ signals:
|
||||
|
||||
public slots:
|
||||
|
||||
void needToResumeAndSend();
|
||||
|
||||
mtpRequestId resend(quint64 msgId, quint64 msCanWait = 0, bool forceContainer = false, bool sendMsgStateInfo = false);
|
||||
void resendMany(QVector<quint64> msgIds, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo);
|
||||
void resendAll(); // after connection restart
|
||||
|
@ -743,6 +743,7 @@ bool Window::eventFilter(QObject *obj, QEvent *evt) {
|
||||
cSetStartUrl(QString());
|
||||
}
|
||||
}
|
||||
activate();
|
||||
} else if (obj == this && evt->type() == QEvent::WindowStateChange) {
|
||||
Qt::WindowState state = (windowState() & Qt::WindowMinimized) ? Qt::WindowMinimized : ((windowState() & Qt::WindowMaximized) ? Qt::WindowMaximized : ((windowState() & Qt::WindowFullScreen) ? Qt::WindowFullScreen : Qt::WindowNoState));
|
||||
psStateChanged(state);
|
||||
|
@ -11,7 +11,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.6.15</string>
|
||||
<string>0.6.16</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
Binary file not shown.
@ -1577,7 +1577,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.6.15;
|
||||
CURRENT_PROJECT_VERSION = 0.6.16;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
@ -1595,7 +1595,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 0.6.15;
|
||||
CURRENT_PROJECT_VERSION = 0.6.16;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = fast;
|
||||
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
|
||||
@ -1621,10 +1621,10 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.6.15;
|
||||
CURRENT_PROJECT_VERSION = 0.6.16;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DYLIB_COMPATIBILITY_VERSION = 0.6;
|
||||
DYLIB_CURRENT_VERSION = 0.6.15;
|
||||
DYLIB_CURRENT_VERSION = 0.6.16;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
@ -1764,10 +1764,10 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.6.15;
|
||||
CURRENT_PROJECT_VERSION = 0.6.16;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DYLIB_COMPATIBILITY_VERSION = 0.6;
|
||||
DYLIB_CURRENT_VERSION = 0.6.15;
|
||||
DYLIB_CURRENT_VERSION = 0.6.16;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
|
@ -1,2 +1,2 @@
|
||||
echo 6015 0.6.15
|
||||
echo 6016 0.6.16
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user