Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f8725e1af | ||
|
|
0ce6a4cbdb | ||
|
|
ad3f705f50 | ||
|
|
c5847caa91 | ||
|
|
8df6d9db7e | ||
|
|
a9c1970f41 | ||
|
|
c3f0d2ef31 | ||
|
|
0dcc439dda | ||
|
|
5b0cac47ad | ||
|
|
b39e78a4a9 |
@@ -10,7 +10,7 @@
|
||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="4.16.2.0" />
|
||||
Version="4.16.3.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
||||
|
||||
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,16,2,0
|
||||
PRODUCTVERSION 4,16,2,0
|
||||
FILEVERSION 4,16,3,0
|
||||
PRODUCTVERSION 4,16,3,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -62,10 +62,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop"
|
||||
VALUE "FileVersion", "4.16.2.0"
|
||||
VALUE "FileVersion", "4.16.3.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "4.16.2.0"
|
||||
VALUE "ProductVersion", "4.16.3.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,16,2,0
|
||||
PRODUCTVERSION 4,16,2,0
|
||||
FILEVERSION 4,16,3,0
|
||||
PRODUCTVERSION 4,16,3,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -53,10 +53,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop Updater"
|
||||
VALUE "FileVersion", "4.16.2.0"
|
||||
VALUE "FileVersion", "4.16.3.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "4.16.2.0"
|
||||
VALUE "ProductVersion", "4.16.3.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace {
|
||||
|
||||
constexpr auto kSharedMediaLimit = 100;
|
||||
|
||||
[[nodiscard]] SendMediaReady PreparePeerPhoto(
|
||||
[[nodiscard]] std::shared_ptr<FilePrepareResult> PreparePeerPhoto(
|
||||
MTP::DcId dcId,
|
||||
PeerId peerId,
|
||||
QImage &&image) {
|
||||
@@ -80,24 +80,17 @@ constexpr auto kSharedMediaLimit = 100;
|
||||
MTPVector<MTPVideoSize>(),
|
||||
MTP_int(dcId));
|
||||
|
||||
QString file, filename;
|
||||
int64 filesize = 0;
|
||||
QByteArray data;
|
||||
|
||||
return SendMediaReady(
|
||||
SendMediaType::Photo,
|
||||
file,
|
||||
filename,
|
||||
filesize,
|
||||
data,
|
||||
id,
|
||||
id,
|
||||
u"jpg"_q,
|
||||
peerId,
|
||||
photo,
|
||||
photoThumbs,
|
||||
MTP_documentEmpty(MTP_long(0)),
|
||||
jpeg);
|
||||
auto result = MakePreparedFile({
|
||||
.id = id,
|
||||
.type = SendMediaType::Photo,
|
||||
});
|
||||
result->type = SendMediaType::Photo;
|
||||
result->setFileData(jpeg);
|
||||
result->thumbId = id;
|
||||
result->thumbname = "thumb.jpg";
|
||||
result->photo = photo;
|
||||
result->photoThumbs = photoThumbs;
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::optional<MTPVideoSize> PrepareMtpMarkup(
|
||||
@@ -239,7 +232,7 @@ void PeerPhoto::upload(
|
||||
_api.instance().mainDcId(),
|
||||
peer->id,
|
||||
base::take(photo.image));
|
||||
_session->uploader().uploadMedia(fakeId, ready);
|
||||
_session->uploader().upload(fakeId, ready);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,16 +24,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
SendMediaReady PrepareRingtoneDocument(
|
||||
std::shared_ptr<FilePrepareResult> PrepareRingtoneDocument(
|
||||
MTP::DcId dcId,
|
||||
const QString &filename,
|
||||
const QString &filemime,
|
||||
const QByteArray &content) {
|
||||
const auto id = base::RandomValue<DocumentId>();
|
||||
auto attributes = QVector<MTPDocumentAttribute>(
|
||||
1,
|
||||
MTP_documentAttributeFilename(MTP_string(filename)));
|
||||
const auto id = base::RandomValue<DocumentId>();
|
||||
const auto document = MTP_document(
|
||||
|
||||
auto result = MakePreparedFile({
|
||||
.id = id,
|
||||
.type = SendMediaType::File,
|
||||
});
|
||||
result->filename = filename;
|
||||
result->content = content;
|
||||
result->filesize = content.size();
|
||||
result->setFileData(content);
|
||||
result->document = MTP_document(
|
||||
MTP_flags(0),
|
||||
MTP_long(id),
|
||||
MTP_long(0),
|
||||
@@ -45,21 +54,7 @@ SendMediaReady PrepareRingtoneDocument(
|
||||
MTPVector<MTPVideoSize>(),
|
||||
MTP_int(dcId),
|
||||
MTP_vector<MTPDocumentAttribute>(std::move(attributes)));
|
||||
|
||||
return SendMediaReady(
|
||||
SendMediaType::File,
|
||||
QString(), // filepath
|
||||
filename,
|
||||
content.size(),
|
||||
content,
|
||||
id,
|
||||
0,
|
||||
QString(),
|
||||
PeerId(),
|
||||
MTP_photoEmpty(MTP_long(0)),
|
||||
PreparedPhotoThumbs(),
|
||||
document,
|
||||
QByteArray());
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -102,7 +97,7 @@ void Ringtones::upload(
|
||||
_uploads.erase(already);
|
||||
}
|
||||
_uploads.emplace(fakeId, uploadedData);
|
||||
_session->uploader().uploadMedia(fakeId, ready);
|
||||
_session->uploader().upload(fakeId, ready);
|
||||
}
|
||||
|
||||
void Ringtones::ready(const FullMsgId &msgId, const MTPInputFile &file) {
|
||||
|
||||
@@ -353,7 +353,7 @@ void FillMessagePostFlags(
|
||||
|
||||
void SendConfirmedFile(
|
||||
not_null<Main::Session*> session,
|
||||
const std::shared_ptr<FileLoadResult> &file) {
|
||||
const std::shared_ptr<FilePrepareResult> &file) {
|
||||
const auto isEditing = (file->type != SendMediaType::Audio)
|
||||
&& (file->to.replaceMediaOf != 0);
|
||||
const auto newId = FullMsgId(
|
||||
|
||||
@@ -14,7 +14,7 @@ class Session;
|
||||
class History;
|
||||
class PhotoData;
|
||||
class DocumentData;
|
||||
struct FileLoadResult;
|
||||
struct FilePrepareResult;
|
||||
|
||||
namespace Api {
|
||||
|
||||
@@ -40,6 +40,6 @@ void FillMessagePostFlags(
|
||||
|
||||
void SendConfirmedFile(
|
||||
not_null<Main::Session*> session,
|
||||
const std::shared_ptr<FileLoadResult> &file);
|
||||
const std::shared_ptr<FilePrepareResult> &file);
|
||||
|
||||
} // namespace Api
|
||||
|
||||
@@ -593,11 +593,11 @@ void BackgroundPreviewBox::uploadForPeer(bool both) {
|
||||
const auto ready = Window::Theme::PrepareWallPaper(
|
||||
session->mainDcId(),
|
||||
_paper.localThumbnail()->original());
|
||||
const auto documentId = ready.id;
|
||||
const auto documentId = ready->id;
|
||||
_uploadId = FullMsgId(
|
||||
session->userPeerId(),
|
||||
session->data().nextLocalMessageId());
|
||||
session->uploader().uploadMedia(_uploadId, ready);
|
||||
session->uploader().upload(_uploadId, ready);
|
||||
if (_uploadLifetime) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include <QtGui/QSessionManager>
|
||||
#include <QtGui/QScreen>
|
||||
#include <QtGui/qpa/qplatformscreen.h>
|
||||
#include <ksandbox.h>
|
||||
|
||||
namespace Core {
|
||||
namespace {
|
||||
@@ -518,10 +517,8 @@ void Sandbox::refreshGlobalProxy() {
|
||||
|| proxy.type == MTP::ProxyData::Type::Http) {
|
||||
QNetworkProxy::setApplicationProxy(
|
||||
MTP::ToNetworkProxy(MTP::ToDirectIpProxy(proxy)));
|
||||
} else if ((!Core::IsAppLaunched()
|
||||
|| Core::App().settings().proxy().isSystem())
|
||||
// this works stable only in sandboxed environment where it works through portal
|
||||
&& (!Platform::IsLinux() || KSandbox::isInside() || cDebugMode())) {
|
||||
} else if (!Core::IsAppLaunched()
|
||||
|| Core::App().settings().proxy().isSystem()) {
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
} else {
|
||||
QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
|
||||
|
||||
@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs;
|
||||
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
|
||||
constexpr auto AppName = "Telegram Desktop"_cs;
|
||||
constexpr auto AppFile = "Telegram"_cs;
|
||||
constexpr auto AppVersion = 4016002;
|
||||
constexpr auto AppVersionStr = "4.16.2";
|
||||
constexpr auto AppBetaVersion = false;
|
||||
constexpr auto AppVersion = 4016003;
|
||||
constexpr auto AppVersionStr = "4.16.3";
|
||||
constexpr auto AppBetaVersion = true;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
|
||||
@@ -18,7 +18,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
struct FileLoadResult;
|
||||
enum class SendMediaType;
|
||||
class MessageLinksParser;
|
||||
struct InlineBotQuery;
|
||||
|
||||
@@ -25,7 +25,7 @@ QByteArray GeoPointId(Geo point) {
|
||||
const auto lon = int(point.lon * 1000000);
|
||||
const auto combined = (std::uint64_t(std::uint32_t(lat)) << 32)
|
||||
| std::uint64_t(std::uint32_t(lon));
|
||||
return QByteArray::number(combined)
|
||||
return QByteArray::number(quint64(combined))
|
||||
+ ','
|
||||
+ QByteArray::number(point.access);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ struct HistoryMessageMarkupButton;
|
||||
class MainWindow;
|
||||
class HistoryWidget;
|
||||
class StackItem;
|
||||
struct FileLoadResult;
|
||||
class History;
|
||||
class Image;
|
||||
|
||||
|
||||
@@ -40,8 +40,6 @@ constexpr ShiftedDcId groupCallStreamDcId(DcId dcId) {
|
||||
return ShiftDcId(dcId, kGroupCallStreamDcShift);
|
||||
}
|
||||
|
||||
constexpr auto kUploadSessionsCount = 2;
|
||||
|
||||
namespace details {
|
||||
|
||||
constexpr ShiftedDcId downloadDcId(DcId dcId, int index) {
|
||||
@@ -92,7 +90,6 @@ inline DcId getTemporaryIdFromRealDcId(ShiftedDcId shiftedDcId) {
|
||||
namespace details {
|
||||
|
||||
constexpr ShiftedDcId uploadDcId(DcId dcId, int index) {
|
||||
static_assert(kUploadSessionsCount < kMaxMediaDcCount, "Too large MTPUploadSessionsCount!");
|
||||
return ShiftDcId(dcId, kBaseUploadDcShift + index);
|
||||
};
|
||||
|
||||
@@ -101,14 +98,14 @@ constexpr ShiftedDcId uploadDcId(DcId dcId, int index) {
|
||||
// send(req, callbacks, MTP::uploadDcId(index)) - for upload shifted dc id
|
||||
// uploading always to the main dc so BareDcId(result) == 0
|
||||
inline ShiftedDcId uploadDcId(int index) {
|
||||
Expects(index >= 0 && index < kUploadSessionsCount);
|
||||
Expects(index >= 0 && index < kMaxMediaDcCount);
|
||||
|
||||
return details::uploadDcId(0, index);
|
||||
};
|
||||
|
||||
constexpr bool isUploadDcId(ShiftedDcId shiftedDcId) {
|
||||
return (shiftedDcId >= details::uploadDcId(0, 0))
|
||||
&& (shiftedDcId < details::uploadDcId(0, kUploadSessionsCount - 1) + kDcShift);
|
||||
&& (shiftedDcId < details::uploadDcId(0, kMaxMediaDcCount - 1) + kDcShift);
|
||||
}
|
||||
|
||||
inline ShiftedDcId destroyKeyNextDcId(ShiftedDcId shiftedDcId) {
|
||||
|
||||
@@ -60,6 +60,8 @@ constexpr auto kSendStateRequestWaiting = crl::time(1000);
|
||||
// How much time to wait for some more requests, when sending msg acks.
|
||||
constexpr auto kAckSendWaiting = 10 * crl::time(1000);
|
||||
|
||||
constexpr auto kCutContainerOnSize = 16 * 1024;
|
||||
|
||||
auto SyncTimeRequestDuration = kFastRequestDuration;
|
||||
|
||||
using namespace details;
|
||||
@@ -696,7 +698,8 @@ void SessionPrivate::tryToSend() {
|
||||
initSize = initSizeInInts * sizeof(mtpPrime);
|
||||
}
|
||||
|
||||
bool needAnyResponse = false;
|
||||
auto needAnyResponse = false;
|
||||
auto someSkipped = false;
|
||||
SerializedRequest toSendRequest;
|
||||
{
|
||||
QWriteLocker locker1(_sessionData->toSendMutex());
|
||||
@@ -711,15 +714,33 @@ void SessionPrivate::tryToSend() {
|
||||
locker1.unlock();
|
||||
}
|
||||
|
||||
uint32 toSendCount = toSend.size();
|
||||
if (pingRequest) ++toSendCount;
|
||||
if (ackRequest) ++toSendCount;
|
||||
if (resendRequest) ++toSendCount;
|
||||
if (stateRequest) ++toSendCount;
|
||||
if (httpWaitRequest) ++toSendCount;
|
||||
if (bindDcKeyRequest) ++toSendCount;
|
||||
auto totalSending = int(toSend.size());
|
||||
auto sendingFrom = begin(toSend);
|
||||
auto sendingTill = end(toSend);
|
||||
auto combinedLength = 0;
|
||||
for (auto i = sendingFrom; i != sendingTill; ++i) {
|
||||
combinedLength += i->second->size();
|
||||
if (combinedLength >= kCutContainerOnSize) {
|
||||
++i;
|
||||
if (const auto skipping = int(sendingTill - i)) {
|
||||
sendingTill = i;
|
||||
totalSending -= skipping;
|
||||
Assert(totalSending > 0);
|
||||
someSkipped = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto sendingRange = ranges::make_subrange(sendingFrom, sendingTill);
|
||||
const auto sendingCount = totalSending;
|
||||
if (pingRequest) ++totalSending;
|
||||
if (ackRequest) ++totalSending;
|
||||
if (resendRequest) ++totalSending;
|
||||
if (stateRequest) ++totalSending;
|
||||
if (httpWaitRequest) ++totalSending;
|
||||
if (bindDcKeyRequest) ++totalSending;
|
||||
|
||||
if (!toSendCount) {
|
||||
if (!totalSending) {
|
||||
return; // nothing to send
|
||||
}
|
||||
|
||||
@@ -735,11 +756,11 @@ void SessionPrivate::tryToSend() {
|
||||
? httpWaitRequest
|
||||
: bindDcKeyRequest
|
||||
? bindDcKeyRequest
|
||||
: toSend.begin()->second;
|
||||
if (toSendCount == 1 && !first->forceSendInContainer) {
|
||||
: sendingRange.begin()->second;
|
||||
if (totalSending == 1 && !first->forceSendInContainer) {
|
||||
toSendRequest = first;
|
||||
if (sendAll) {
|
||||
toSend.clear();
|
||||
toSend.erase(sendingFrom, sendingTill);
|
||||
locker1.unlock();
|
||||
}
|
||||
|
||||
@@ -808,7 +829,7 @@ void SessionPrivate::tryToSend() {
|
||||
if (stateRequest) containerSize += stateRequest.messageSize();
|
||||
if (httpWaitRequest) containerSize += httpWaitRequest.messageSize();
|
||||
if (bindDcKeyRequest) containerSize += bindDcKeyRequest.messageSize();
|
||||
for (const auto &[requestId, request] : toSend) {
|
||||
for (const auto &[requestId, request] : sendingRange) {
|
||||
containerSize += request.messageSize();
|
||||
if (needsLayer && request->needsLayer) {
|
||||
containerSize += initSizeInInts;
|
||||
@@ -825,9 +846,9 @@ void SessionPrivate::tryToSend() {
|
||||
// prepare container + each in invoke after
|
||||
toSendRequest = SerializedRequest::Prepare(
|
||||
containerSize,
|
||||
containerSize + 3 * toSend.size());
|
||||
containerSize + 3 * sendingCount);
|
||||
toSendRequest->push_back(mtpc_msg_container);
|
||||
toSendRequest->push_back(toSendCount);
|
||||
toSendRequest->push_back(totalSending);
|
||||
|
||||
// check for a valid container
|
||||
auto bigMsgId = base::unixtime::mtproto_msg_id();
|
||||
@@ -839,7 +860,7 @@ void SessionPrivate::tryToSend() {
|
||||
// prepare sent container
|
||||
auto sentIdsWrap = SentContainer();
|
||||
sentIdsWrap.sent = crl::now();
|
||||
sentIdsWrap.messages.reserve(toSendCount);
|
||||
sentIdsWrap.messages.reserve(totalSending);
|
||||
|
||||
if (bindDcKeyRequest) {
|
||||
_bindMsgId = placeToContainer(
|
||||
@@ -859,7 +880,7 @@ void SessionPrivate::tryToSend() {
|
||||
needAnyResponse = true;
|
||||
}
|
||||
|
||||
for (auto &[requestId, request] : toSend) {
|
||||
for (auto &[requestId, request] : sendingRange) {
|
||||
const auto msgId = prepareToSend(
|
||||
request,
|
||||
bigMsgId,
|
||||
@@ -904,7 +925,7 @@ void SessionPrivate::tryToSend() {
|
||||
memcpy(toSendRequest->data() + from, request->constData() + 4, len * sizeof(mtpPrime));
|
||||
}
|
||||
}
|
||||
toSend.clear();
|
||||
toSend.erase(sendingFrom, sendingTill);
|
||||
|
||||
if (stateRequest) {
|
||||
const auto msgId = placeToContainer(
|
||||
@@ -951,6 +972,11 @@ void SessionPrivate::tryToSend() {
|
||||
}
|
||||
}
|
||||
sendSecureRequest(std::move(toSendRequest), needAnyResponse);
|
||||
if (someSkipped) {
|
||||
InvokeQueued(this, [=] {
|
||||
tryToSend();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void SessionPrivate::retryByTimer() {
|
||||
@@ -1108,9 +1134,6 @@ void SessionPrivate::onSentSome(uint64 size) {
|
||||
DEBUG_LOG(("Checking connect for request with size %1 bytes, delay will be %2").arg(size).arg(remain));
|
||||
}
|
||||
}
|
||||
if (isUploadDcId(_shiftedDcId)) {
|
||||
remain *= kUploadSessionsCount;
|
||||
}
|
||||
_waitForReceivedTimer.callOnce(remain);
|
||||
}
|
||||
if (!_firstSentAt) {
|
||||
@@ -1628,7 +1651,9 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
|
||||
}
|
||||
|
||||
_sessionSalt = data.vnew_server_salt().v;
|
||||
correctUnixtimeWithBadLocal(info.serverTime);
|
||||
|
||||
// Don't force time update here.
|
||||
base::unixtime::update(info.serverTime);
|
||||
|
||||
if (_bindMsgId) {
|
||||
LOG(("Message Info: bad_server_salt received while binding temp key, restarting."));
|
||||
@@ -2056,7 +2081,7 @@ void SessionPrivate::correctUnixtimeByFastRequest(
|
||||
locker.unlock();
|
||||
|
||||
SyncTimeRequestDuration = duration;
|
||||
base::unixtime::update(serverTime, true);
|
||||
base::unixtime::update(serverTime);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1581,14 +1581,10 @@ void FormController::uploadEncryptedFile(
|
||||
&session(),
|
||||
std::make_unique<UploadScanData>(std::move(data)));
|
||||
|
||||
auto prepared = std::make_shared<FileLoadResult>(
|
||||
TaskId(),
|
||||
file.uploadData->fileId,
|
||||
FileLoadTo(PeerId(), Api::SendOptions(), FullReplyTo(), MsgId()),
|
||||
TextWithTags(),
|
||||
false,
|
||||
std::shared_ptr<SendingAlbum>(nullptr));
|
||||
prepared->type = SendMediaType::Secure;
|
||||
auto prepared = MakePreparedFile({
|
||||
.id = file.uploadData->fileId,
|
||||
.type = SendMediaType::Secure,
|
||||
});
|
||||
prepared->content = QByteArray::fromRawData(
|
||||
reinterpret_cast<char*>(file.uploadData->bytes.data()),
|
||||
file.uploadData->bytes.size());
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,11 +9,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "api/api_common.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/weak_ptr.h"
|
||||
#include "mtproto/facade.h"
|
||||
|
||||
class ApiWrap;
|
||||
struct FileLoadResult;
|
||||
struct SendMediaReady;
|
||||
struct FilePrepareResult;
|
||||
|
||||
namespace Api {
|
||||
enum class SendProgressType;
|
||||
@@ -47,54 +47,48 @@ struct UploadSecureDone {
|
||||
int partsCount = 0;
|
||||
};
|
||||
|
||||
class Uploader final : public QObject {
|
||||
class Uploader final : public base::has_weak_ptr {
|
||||
public:
|
||||
explicit Uploader(not_null<ApiWrap*> api);
|
||||
~Uploader();
|
||||
|
||||
[[nodiscard]] Main::Session &session() const;
|
||||
[[nodiscard]] FullMsgId currentUploadId() const;
|
||||
|
||||
[[nodiscard]] FullMsgId currentUploadId() const {
|
||||
return uploadingId;
|
||||
}
|
||||
|
||||
void uploadMedia(const FullMsgId &msgId, const SendMediaReady &image);
|
||||
void upload(
|
||||
const FullMsgId &msgId,
|
||||
const std::shared_ptr<FileLoadResult> &file);
|
||||
|
||||
void cancel(const FullMsgId &msgId);
|
||||
void pause(const FullMsgId &msgId);
|
||||
void confirm(const FullMsgId &msgId);
|
||||
FullMsgId itemId,
|
||||
const std::shared_ptr<FilePrepareResult> &file);
|
||||
|
||||
void pause(FullMsgId itemId);
|
||||
void cancel(FullMsgId itemId);
|
||||
void cancelAll();
|
||||
void clear();
|
||||
|
||||
rpl::producer<UploadedMedia> photoReady() const {
|
||||
[[nodiscard]] rpl::producer<UploadedMedia> photoReady() const {
|
||||
return _photoReady.events();
|
||||
}
|
||||
rpl::producer<UploadedMedia> documentReady() const {
|
||||
[[nodiscard]] rpl::producer<UploadedMedia> documentReady() const {
|
||||
return _documentReady.events();
|
||||
}
|
||||
rpl::producer<UploadSecureDone> secureReady() const {
|
||||
[[nodiscard]] rpl::producer<UploadSecureDone> secureReady() const {
|
||||
return _secureReady.events();
|
||||
}
|
||||
rpl::producer<FullMsgId> photoProgress() const {
|
||||
[[nodiscard]] rpl::producer<FullMsgId> photoProgress() const {
|
||||
return _photoProgress.events();
|
||||
}
|
||||
rpl::producer<FullMsgId> documentProgress() const {
|
||||
[[nodiscard]] rpl::producer<FullMsgId> documentProgress() const {
|
||||
return _documentProgress.events();
|
||||
}
|
||||
rpl::producer<UploadSecureProgress> secureProgress() const {
|
||||
[[nodiscard]] auto secureProgress() const
|
||||
-> rpl::producer<UploadSecureProgress> {
|
||||
return _secureProgress.events();
|
||||
}
|
||||
rpl::producer<FullMsgId> photoFailed() const {
|
||||
[[nodiscard]] rpl::producer<FullMsgId> photoFailed() const {
|
||||
return _photoFailed.events();
|
||||
}
|
||||
rpl::producer<FullMsgId> documentFailed() const {
|
||||
[[nodiscard]] rpl::producer<FullMsgId> documentFailed() const {
|
||||
return _documentFailed.events();
|
||||
}
|
||||
rpl::producer<FullMsgId> secureFailed() const {
|
||||
[[nodiscard]] rpl::producer<FullMsgId> secureFailed() const {
|
||||
return _secureFailed.events();
|
||||
}
|
||||
|
||||
@@ -103,23 +97,53 @@ public:
|
||||
}
|
||||
|
||||
void unpause();
|
||||
void sendNext();
|
||||
void stopSessions();
|
||||
|
||||
private:
|
||||
struct File;
|
||||
struct Entry;
|
||||
struct Request;
|
||||
|
||||
enum class SendResult : uchar {
|
||||
Success,
|
||||
Failed,
|
||||
DcIndexFull,
|
||||
};
|
||||
|
||||
void maybeSend();
|
||||
[[nodiscard]] bool canAddDcIndex() const;
|
||||
[[nodiscard]] std::optional<uchar> chooseDcIndexForNextRequest(
|
||||
const base::flat_set<uchar> &used);
|
||||
[[nodiscard]] Entry *chooseEntryForNextRequest();
|
||||
[[nodiscard]] SendResult sendPart(not_null<Entry*> entry, uchar dcIndex);
|
||||
[[nodiscard]] auto sendPendingPart(not_null<Entry*> entry, uchar dcIndex)
|
||||
-> SendResult;
|
||||
[[nodiscard]] auto sendDocPart(not_null<Entry*> entry, uchar dcIndex)
|
||||
-> SendResult;
|
||||
[[nodiscard]] auto sendSlicedPart(not_null<Entry*> entry, uchar dcIndex)
|
||||
-> SendResult;
|
||||
[[nodiscard]] QByteArray readDocPart(not_null<Entry*> entry);
|
||||
void removeDcIndex();
|
||||
|
||||
template <typename Prepared>
|
||||
void sendPreparedRequest(Prepared &&prepared, Request &&request);
|
||||
|
||||
void maybeFinishFront();
|
||||
void finishFront();
|
||||
|
||||
void partLoaded(const MTPBool &result, mtpRequestId requestId);
|
||||
void partFailed(const MTP::Error &error, mtpRequestId requestId);
|
||||
Request finishRequest(mtpRequestId requestId);
|
||||
|
||||
void processPhotoProgress(const FullMsgId &msgId);
|
||||
void processPhotoFailed(const FullMsgId &msgId);
|
||||
void processDocumentProgress(const FullMsgId &msgId);
|
||||
void processDocumentFailed(const FullMsgId &msgId);
|
||||
void processPhotoProgress(FullMsgId itemId);
|
||||
void processPhotoFailed(FullMsgId itemId);
|
||||
void processDocumentProgress(FullMsgId itemId);
|
||||
void processDocumentFailed(FullMsgId itemId);
|
||||
|
||||
void notifyFailed(FullMsgId id, const File &file);
|
||||
void currentFailed();
|
||||
void cancelRequests();
|
||||
void notifyFailed(const Entry &entry);
|
||||
void failed(FullMsgId itemId);
|
||||
void cancelRequests(FullMsgId itemId);
|
||||
void cancelAllRequests();
|
||||
void clear();
|
||||
|
||||
void sendProgressUpdate(
|
||||
not_null<HistoryItem*> item,
|
||||
@@ -127,16 +151,19 @@ private:
|
||||
int progress = 0);
|
||||
|
||||
const not_null<ApiWrap*> _api;
|
||||
base::flat_map<mtpRequestId, QByteArray> requestsSent;
|
||||
base::flat_map<mtpRequestId, int32> docRequestsSent;
|
||||
base::flat_map<mtpRequestId, int32> dcMap;
|
||||
base::flat_set<mtpRequestId> _nonPremiumDelayed;
|
||||
uint32 sentSize = 0; // FileSize: Right now any file size fits 32 bit.
|
||||
uint32 sentSizes[MTP::kUploadSessionsCount] = { 0 };
|
||||
|
||||
FullMsgId uploadingId;
|
||||
std::vector<Entry> _queue;
|
||||
|
||||
base::flat_map<mtpRequestId, Request> _requests;
|
||||
std::vector<int> _sentPerDcIndex;
|
||||
|
||||
// Fast requests since the latest dc index addition.
|
||||
base::flat_set<uchar> _dcIndicesWithFastRequests;
|
||||
crl::time _latestDcIndexAdded = 0;
|
||||
crl::time _latestDcIndexRemoved = 0;
|
||||
std::vector<Request> _pendingFromRemovedDcIndices;
|
||||
|
||||
FullMsgId _pausedId;
|
||||
std::map<FullMsgId, File> queue;
|
||||
base::Timer _nextTimer, _stopSessionsTimer;
|
||||
|
||||
rpl::event_stream<UploadedMedia> _photoReady;
|
||||
|
||||
@@ -222,42 +222,6 @@ int PhotoSideLimit() {
|
||||
return PhotoSideLimit(SendLargePhotos.value());
|
||||
}
|
||||
|
||||
SendMediaReady::SendMediaReady(
|
||||
SendMediaType type,
|
||||
const QString &file,
|
||||
const QString &filename,
|
||||
int64 filesize,
|
||||
const QByteArray &data,
|
||||
const uint64 &id,
|
||||
const uint64 &thumbId,
|
||||
const QString &thumbExt,
|
||||
const PeerId &peer,
|
||||
const MTPPhoto &photo,
|
||||
const PreparedPhotoThumbs &photoThumbs,
|
||||
const MTPDocument &document,
|
||||
const QByteArray &jpeg)
|
||||
: type(type)
|
||||
, file(file)
|
||||
, filename(filename)
|
||||
, filesize(filesize)
|
||||
, data(data)
|
||||
, thumbExt(thumbExt)
|
||||
, id(id)
|
||||
, thumbId(thumbId)
|
||||
, peer(peer)
|
||||
, photo(photo)
|
||||
, document(document)
|
||||
, photoThumbs(photoThumbs) {
|
||||
if (!jpeg.isEmpty()) {
|
||||
int32 size = jpeg.size();
|
||||
for (int32 i = 0, part = 0; i < size; i += kPhotoUploadPartSize, ++part) {
|
||||
parts.insert(part, jpeg.mid(i, kPhotoUploadPartSize));
|
||||
}
|
||||
jpeg_md5.resize(32);
|
||||
hashMd5Hex(jpeg.constData(), jpeg.size(), jpeg_md5.data());
|
||||
}
|
||||
}
|
||||
|
||||
TaskQueue::TaskQueue(crl::time stopTimeoutMs) {
|
||||
if (stopTimeoutMs > 0) {
|
||||
_stopTimer = new QTimer(this);
|
||||
@@ -455,46 +419,50 @@ SendingAlbum::Item::Item(TaskId taskId)
|
||||
: taskId(taskId) {
|
||||
}
|
||||
|
||||
FileLoadResult::FileLoadResult(
|
||||
TaskId taskId,
|
||||
uint64 id,
|
||||
const FileLoadTo &to,
|
||||
const TextWithTags &caption,
|
||||
bool spoiler,
|
||||
std::shared_ptr<SendingAlbum> album)
|
||||
: taskId(taskId)
|
||||
, id(id)
|
||||
, to(to)
|
||||
, album(std::move(album))
|
||||
, caption(caption)
|
||||
, spoiler(spoiler) {
|
||||
FilePrepareResult::FilePrepareResult(FilePrepareDescriptor &&descriptor)
|
||||
: taskId(descriptor.taskId)
|
||||
, id(descriptor.id)
|
||||
, to(std::move(descriptor.to))
|
||||
, album(std::move(descriptor.album))
|
||||
, type(descriptor.type)
|
||||
, caption(std::move(descriptor.caption))
|
||||
, spoiler(descriptor.spoiler) {
|
||||
}
|
||||
|
||||
void FileLoadResult::setFileData(const QByteArray &filedata) {
|
||||
void FilePrepareResult::setFileData(const QByteArray &filedata) {
|
||||
if (filedata.isEmpty()) {
|
||||
partssize = 0;
|
||||
} else {
|
||||
partssize = filedata.size();
|
||||
fileparts.reserve(
|
||||
(partssize + kPhotoUploadPartSize - 1) / kPhotoUploadPartSize);
|
||||
for (int32 i = 0, part = 0; i < partssize; i += kPhotoUploadPartSize, ++part) {
|
||||
fileparts.insert(part, filedata.mid(i, kPhotoUploadPartSize));
|
||||
fileparts.push_back(filedata.mid(i, kPhotoUploadPartSize));
|
||||
}
|
||||
filemd5.resize(32);
|
||||
hashMd5Hex(filedata.constData(), filedata.size(), filemd5.data());
|
||||
}
|
||||
}
|
||||
|
||||
void FileLoadResult::setThumbData(const QByteArray &thumbdata) {
|
||||
void FilePrepareResult::setThumbData(const QByteArray &thumbdata) {
|
||||
if (!thumbdata.isEmpty()) {
|
||||
thumbbytes = thumbdata;
|
||||
int32 size = thumbdata.size();
|
||||
thumbparts.reserve(
|
||||
(size + kPhotoUploadPartSize - 1) / kPhotoUploadPartSize);
|
||||
for (int32 i = 0, part = 0; i < size; i += kPhotoUploadPartSize, ++part) {
|
||||
thumbparts.insert(part, thumbdata.mid(i, kPhotoUploadPartSize));
|
||||
thumbparts.push_back(thumbdata.mid(i, kPhotoUploadPartSize));
|
||||
}
|
||||
thumbmd5.resize(32);
|
||||
hashMd5Hex(thumbdata.constData(), thumbdata.size(), thumbmd5.data());
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<FilePrepareResult> MakePreparedFile(
|
||||
FilePrepareDescriptor &&descriptor) {
|
||||
return std::make_shared<FilePrepareResult>(std::move(descriptor));
|
||||
}
|
||||
|
||||
FileLoadTask::FileLoadTask(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &filepath,
|
||||
@@ -710,13 +678,14 @@ bool FileLoadTask::FillImageInformation(
|
||||
}
|
||||
|
||||
void FileLoadTask::process(Args &&args) {
|
||||
_result = std::make_shared<FileLoadResult>(
|
||||
id(),
|
||||
_id,
|
||||
_to,
|
||||
_caption,
|
||||
_spoiler,
|
||||
_album);
|
||||
_result = MakePreparedFile({
|
||||
.taskId = id(),
|
||||
.id = _id,
|
||||
.to = _to,
|
||||
.caption = _caption,
|
||||
.spoiler = _spoiler,
|
||||
.album = _album,
|
||||
});
|
||||
|
||||
QString filename, filemime;
|
||||
qint64 filesize = 0;
|
||||
@@ -1062,7 +1031,7 @@ void FileLoadTask::finish() {
|
||||
}
|
||||
}
|
||||
|
||||
FileLoadResult *FileLoadTask::peekResult() const {
|
||||
FilePrepareResult *FileLoadTask::peekResult() const {
|
||||
return _result.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,43 +36,8 @@ enum class SendMediaType {
|
||||
Secure,
|
||||
};
|
||||
|
||||
using UploadFileParts = QMap<int, QByteArray>;
|
||||
struct SendMediaReady {
|
||||
SendMediaReady() = default; // temp
|
||||
SendMediaReady(
|
||||
SendMediaType type,
|
||||
const QString &file,
|
||||
const QString &filename,
|
||||
int64 filesize,
|
||||
const QByteArray &data,
|
||||
const uint64 &id,
|
||||
const uint64 &thumbId,
|
||||
const QString &thumbExt,
|
||||
const PeerId &peer,
|
||||
const MTPPhoto &photo,
|
||||
const PreparedPhotoThumbs &photoThumbs,
|
||||
const MTPDocument &document,
|
||||
const QByteArray &jpeg);
|
||||
|
||||
SendMediaType type;
|
||||
QString file, filename;
|
||||
int64 filesize = 0;
|
||||
QByteArray data;
|
||||
QString thumbExt;
|
||||
uint64 id, thumbId; // id always file-id of media, thumbId is file-id of thumb ( == id for photos)
|
||||
PeerId peer;
|
||||
|
||||
MTPPhoto photo;
|
||||
MTPDocument document;
|
||||
PreparedPhotoThumbs photoThumbs;
|
||||
UploadFileParts parts;
|
||||
QByteArray jpeg_md5;
|
||||
|
||||
QString caption;
|
||||
|
||||
};
|
||||
|
||||
using TaskId = void*; // no interface, just id
|
||||
inline constexpr auto kEmptyTaskId = TaskId();
|
||||
|
||||
class Task {
|
||||
public:
|
||||
@@ -144,7 +109,7 @@ struct SendingAlbum {
|
||||
struct Item {
|
||||
explicit Item(TaskId taskId);
|
||||
|
||||
TaskId taskId;
|
||||
TaskId taskId = kEmptyTaskId;
|
||||
uint64 randomId = 0;
|
||||
FullMsgId msgId;
|
||||
std::optional<MTPInputSingleMedia> media;
|
||||
@@ -182,17 +147,21 @@ struct FileLoadTo {
|
||||
MsgId replaceMediaOf;
|
||||
};
|
||||
|
||||
struct FileLoadResult {
|
||||
FileLoadResult(
|
||||
TaskId taskId,
|
||||
uint64 id,
|
||||
const FileLoadTo &to,
|
||||
const TextWithTags &caption,
|
||||
bool spoiler,
|
||||
std::shared_ptr<SendingAlbum> album);
|
||||
using UploadFileParts = std::vector<QByteArray>;
|
||||
struct FilePrepareDescriptor {
|
||||
TaskId taskId = kEmptyTaskId;
|
||||
base::required<uint64> id;
|
||||
SendMediaType type = SendMediaType::File;
|
||||
FileLoadTo to = { PeerId(), Api::SendOptions(), FullReplyTo(), MsgId() };
|
||||
TextWithTags caption;
|
||||
bool spoiler = false;
|
||||
std::shared_ptr<SendingAlbum> album;
|
||||
};
|
||||
struct FilePrepareResult {
|
||||
explicit FilePrepareResult(FilePrepareDescriptor &&descriptor);
|
||||
|
||||
TaskId taskId;
|
||||
uint64 id;
|
||||
TaskId taskId = kEmptyTaskId;
|
||||
uint64 id = 0;
|
||||
FileLoadTo to;
|
||||
std::shared_ptr<SendingAlbum> album;
|
||||
SendMediaType type = SendMediaType::File;
|
||||
@@ -216,8 +185,8 @@ struct FileLoadResult {
|
||||
QImage goodThumbnail;
|
||||
QByteArray goodThumbnailBytes;
|
||||
|
||||
MTPPhoto photo;
|
||||
MTPDocument document;
|
||||
MTPPhoto photo = MTP_photoEmpty(MTP_long(0));
|
||||
MTPDocument document = MTP_documentEmpty(MTP_long(0));
|
||||
|
||||
PreparedPhotoThumbs photoThumbs;
|
||||
TextWithTags caption;
|
||||
@@ -230,6 +199,9 @@ struct FileLoadResult {
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] std::shared_ptr<FilePrepareResult> MakePreparedFile(
|
||||
FilePrepareDescriptor &&descriptor);
|
||||
|
||||
class FileLoadTask final : public Task {
|
||||
public:
|
||||
static std::unique_ptr<Ui::PreparedFileInformation> ReadMediaInformation(
|
||||
@@ -276,7 +248,7 @@ public:
|
||||
}
|
||||
void finish() override;
|
||||
|
||||
FileLoadResult *peekResult() const;
|
||||
FilePrepareResult *peekResult() const;
|
||||
|
||||
private:
|
||||
static bool CheckForSong(
|
||||
@@ -312,6 +284,6 @@ private:
|
||||
TextWithTags _caption;
|
||||
bool _spoiler = false;
|
||||
|
||||
std::shared_ptr<FileLoadResult> _result;
|
||||
std::shared_ptr<FilePrepareResult> _result;
|
||||
|
||||
};
|
||||
|
||||
@@ -585,11 +585,11 @@ void ChatBackground::checkUploadWallPaper() {
|
||||
}
|
||||
|
||||
const auto ready = PrepareWallPaper(_session->mainDcId(), _original);
|
||||
const auto documentId = ready.id;
|
||||
const auto documentId = ready->id;
|
||||
_wallPaperUploadId = FullMsgId(
|
||||
_session->userPeerId(),
|
||||
_session->data().nextLocalMessageId());
|
||||
_session->uploader().uploadMedia(_wallPaperUploadId, ready);
|
||||
_session->uploader().upload(_wallPaperUploadId, ready);
|
||||
if (_wallPaperUploadLifetime) {
|
||||
return;
|
||||
}
|
||||
@@ -1529,7 +1529,9 @@ bool ReadPaletteValues(const QByteArray &content, Fn<bool(QLatin1String name, QL
|
||||
};
|
||||
}
|
||||
|
||||
SendMediaReady PrepareWallPaper(MTP::DcId dcId, const QImage &image) {
|
||||
std::shared_ptr<FilePrepareResult> PrepareWallPaper(
|
||||
MTP::DcId dcId,
|
||||
const QImage &image) {
|
||||
PreparedPhotoThumbs thumbnails;
|
||||
QVector<MTPPhotoSize> sizes;
|
||||
|
||||
@@ -1555,6 +1557,7 @@ SendMediaReady PrepareWallPaper(MTP::DcId dcId, const QImage &image) {
|
||||
};
|
||||
push("s", scaled(320));
|
||||
|
||||
const auto id = base::RandomValue<DocumentId>();
|
||||
const auto filename = u"wallpaper.jpg"_q;
|
||||
auto attributes = QVector<MTPDocumentAttribute>(
|
||||
1,
|
||||
@@ -1562,8 +1565,20 @@ SendMediaReady PrepareWallPaper(MTP::DcId dcId, const QImage &image) {
|
||||
attributes.push_back(MTP_documentAttributeImageSize(
|
||||
MTP_int(image.width()),
|
||||
MTP_int(image.height())));
|
||||
const auto id = base::RandomValue<DocumentId>();
|
||||
const auto document = MTP_document(
|
||||
|
||||
auto result = MakePreparedFile({
|
||||
.id = id,
|
||||
.type = SendMediaType::ThemeFile,
|
||||
});
|
||||
result->filename = filename;
|
||||
result->content = jpeg;
|
||||
result->filesize = jpeg.size();
|
||||
result->setFileData(jpeg);
|
||||
if (thumbnails.empty()) {
|
||||
result->thumb = thumbnails.front().second.image;
|
||||
result->thumbbytes = thumbnails.front().second.bytes;
|
||||
}
|
||||
result->document = MTP_document(
|
||||
MTP_flags(0),
|
||||
MTP_long(id),
|
||||
MTP_long(0),
|
||||
@@ -1575,21 +1590,7 @@ SendMediaReady PrepareWallPaper(MTP::DcId dcId, const QImage &image) {
|
||||
MTPVector<MTPVideoSize>(),
|
||||
MTP_int(dcId),
|
||||
MTP_vector<MTPDocumentAttribute>(attributes));
|
||||
|
||||
return SendMediaReady(
|
||||
SendMediaType::ThemeFile,
|
||||
QString(), // filepath
|
||||
filename,
|
||||
jpeg.size(),
|
||||
jpeg,
|
||||
id,
|
||||
0,
|
||||
QString(),
|
||||
PeerId(),
|
||||
MTP_photoEmpty(MTP_long(0)),
|
||||
thumbnails,
|
||||
document,
|
||||
QByteArray());
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<Ui::ChatTheme> DefaultChatThemeOn(rpl::lifetime &lifetime) {
|
||||
|
||||
@@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/style/style_core_palette.h"
|
||||
|
||||
class QFileSystemWatcher;
|
||||
struct SendMediaReady;
|
||||
struct FilePrepareResult;
|
||||
|
||||
namespace style {
|
||||
struct colorizer;
|
||||
@@ -298,7 +298,7 @@ private:
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] SendMediaReady PrepareWallPaper(
|
||||
[[nodiscard]] std::shared_ptr<FilePrepareResult> PrepareWallPaper(
|
||||
MTP::DcId dcId,
|
||||
const QImage &image);
|
||||
|
||||
|
||||
@@ -385,7 +385,7 @@ bool CopyColorsToPalette(
|
||||
});
|
||||
}
|
||||
|
||||
SendMediaReady PrepareThemeMedia(
|
||||
std::shared_ptr<FilePrepareResult> PrepareThemeMedia(
|
||||
MTP::DcId dcId,
|
||||
const QString &name,
|
||||
const QByteArray &content) {
|
||||
@@ -403,28 +403,29 @@ SendMediaReady PrepareThemeMedia(
|
||||
thumbnail.save(&buffer, "JPG", 87);
|
||||
}
|
||||
|
||||
const auto push = [&](
|
||||
const char *type,
|
||||
QImage &&image,
|
||||
QByteArray bytes = QByteArray()) {
|
||||
sizes.push_back(MTP_photoSize(
|
||||
MTP_string(type),
|
||||
MTP_int(image.width()),
|
||||
MTP_int(image.height()), MTP_int(0)));
|
||||
thumbnails.emplace(type[0], PreparedPhotoThumb{
|
||||
.image = std::move(image),
|
||||
.bytes = std::move(bytes)
|
||||
});
|
||||
};
|
||||
push("s", std::move(thumbnail), thumbnailBytes);
|
||||
sizes.push_back(MTP_photoSize(
|
||||
MTP_string("s"),
|
||||
MTP_int(thumbnail.width()),
|
||||
MTP_int(thumbnail.height()), MTP_int(0)));
|
||||
|
||||
const auto id = base::RandomValue<DocumentId>();
|
||||
const auto filename = base::FileNameFromUserString(name)
|
||||
+ u".tdesktop-theme"_q;
|
||||
auto attributes = QVector<MTPDocumentAttribute>(
|
||||
1,
|
||||
MTP_documentAttributeFilename(MTP_string(filename)));
|
||||
const auto id = base::RandomValue<DocumentId>();
|
||||
const auto document = MTP_document(
|
||||
|
||||
auto result = MakePreparedFile({
|
||||
.id = id,
|
||||
.type = SendMediaType::ThemeFile,
|
||||
});
|
||||
result->filename = filename;
|
||||
result->content = content;
|
||||
result->filesize = content.size();
|
||||
result->thumb = thumbnail;
|
||||
result->thumbname = "thumb.jpg";
|
||||
result->setThumbData(thumbnailBytes);
|
||||
result->document = MTP_document(
|
||||
MTP_flags(0),
|
||||
MTP_long(id),
|
||||
MTP_long(0),
|
||||
@@ -436,21 +437,7 @@ SendMediaReady PrepareThemeMedia(
|
||||
MTPVector<MTPVideoSize>(),
|
||||
MTP_int(dcId),
|
||||
MTP_vector<MTPDocumentAttribute>(attributes));
|
||||
|
||||
return SendMediaReady(
|
||||
SendMediaType::ThemeFile,
|
||||
QString(), // filepath
|
||||
filename,
|
||||
content.size(),
|
||||
content,
|
||||
id,
|
||||
0,
|
||||
QString(),
|
||||
PeerId(),
|
||||
MTP_photoEmpty(MTP_long(0)),
|
||||
thumbnails,
|
||||
document,
|
||||
thumbnailBytes);
|
||||
return result;
|
||||
}
|
||||
|
||||
Fn<void()> SavePreparedTheme(
|
||||
@@ -570,7 +557,7 @@ Fn<void()> SavePreparedTheme(
|
||||
session->mainDcId(),
|
||||
fields.title,
|
||||
theme);
|
||||
state->filename = media.filename;
|
||||
state->filename = media->filename;
|
||||
state->themeContent = theme;
|
||||
|
||||
session->uploader().documentReady(
|
||||
@@ -580,7 +567,7 @@ Fn<void()> SavePreparedTheme(
|
||||
uploadTheme(data);
|
||||
}, state->lifetime);
|
||||
|
||||
session->uploader().uploadMedia(state->id, media);
|
||||
session->uploader().upload(state->id, media);
|
||||
};
|
||||
|
||||
const auto save = [=] {
|
||||
@@ -999,12 +986,15 @@ ParsedTheme ParseTheme(
|
||||
[[nodiscard]] QString GenerateSlug() {
|
||||
const auto letters = uint8('Z' + 1 - 'A');
|
||||
const auto digits = uint8('9' + 1 - '0');
|
||||
const auto firstValues = uint8(2 * letters);
|
||||
const auto values = uint8(2 * letters + digits);
|
||||
|
||||
auto result = QString();
|
||||
result.reserve(kRandomSlugSize);
|
||||
for (auto i = 0; i != kRandomSlugSize; ++i) {
|
||||
const auto value = base::RandomValue<uint8>() % values;
|
||||
const auto value = i
|
||||
? (base::RandomValue<uint8>() % values)
|
||||
: (base::RandomValue<uint8>() % firstValues);
|
||||
if (value < letters) {
|
||||
result.append(char('A' + value));
|
||||
} else if (value < 2 * letters) {
|
||||
|
||||
@@ -479,7 +479,7 @@ RUN git clone -b 1.19.0 --depth=1 {{ GIT_FREEDESKTOP }}/wayland.git \
|
||||
&& rm -rf wayland
|
||||
|
||||
FROM builder AS nv-codec-headers
|
||||
RUN git clone -b n12.0.16.0 --depth=1 {{ GIT }}/FFmpeg/nv-codec-headers.git \
|
||||
RUN git clone -b n12.1.14.0 --depth=1 {{ GIT }}/FFmpeg/nv-codec-headers.git \
|
||||
&& DESTDIR="{{ LibrariesPath }}/nv-codec-headers-cache" make -C nv-codec-headers install \
|
||||
&& rm -rf nv-codec-headers
|
||||
|
||||
@@ -491,7 +491,7 @@ COPY --link --from=libXext {{ LibrariesPath }}/libXext-cache /
|
||||
COPY --link --from=libXv {{ LibrariesPath }}/libXv-cache /
|
||||
COPY --link --from=nv-codec-headers {{ LibrariesPath }}/nv-codec-headers-cache /
|
||||
|
||||
RUN git clone -b n5.1.3 --depth=1 {{ GIT }}/FFmpeg/FFmpeg.git \
|
||||
RUN git clone -b n6.1.1 --depth=1 {{ GIT }}/FFmpeg/FFmpeg.git \
|
||||
&& cd FFmpeg \
|
||||
&& ./configure \
|
||||
--extra-cflags="-DCONFIG_SAFE_BITSTREAM_READER=1" \
|
||||
|
||||
@@ -425,7 +425,7 @@ if customRunCommand:
|
||||
stage('patches', """
|
||||
git clone https://github.com/desktop-app/patches.git
|
||||
cd patches
|
||||
git checkout cc0c2f8365
|
||||
git checkout 1fef4b342a
|
||||
""")
|
||||
|
||||
stage('msys64', """
|
||||
@@ -696,14 +696,17 @@ mac:
|
||||
make install
|
||||
""")
|
||||
|
||||
# Somehow in x86 Debug build dav1d crashes on AV1 10bpc videos.
|
||||
stage('dav1d', """
|
||||
git clone -b 1.4.1 --depth 1 https://code.videolan.org/videolan/dav1d.git
|
||||
git clone -b 1.4.1 https://code.videolan.org/videolan/dav1d.git
|
||||
cd dav1d
|
||||
win:
|
||||
if "%X8664%" equ "x64" (
|
||||
SET "TARGET=x86_64"
|
||||
SET "DAV1D_ASM_DISABLE="
|
||||
) else (
|
||||
SET "TARGET=x86"
|
||||
SET "DAV1D_ASM_DISABLE=-Denable_asm=false"
|
||||
)
|
||||
set FILE=cross-file.txt
|
||||
echo [binaries] > %FILE%
|
||||
@@ -719,7 +722,7 @@ win:
|
||||
|
||||
depends:python/Scripts/activate.bat
|
||||
%THIRDPARTY_DIR%\\python\\Scripts\\activate.bat
|
||||
meson setup --cross-file %FILE% --prefix %LIBS_DIR%/local --default-library=static --buildtype=debug -Denable_tools=false -Denable_tests=false -Db_vscrt=mtd builddir-debug
|
||||
meson setup --cross-file %FILE% --prefix %LIBS_DIR%/local --default-library=static --buildtype=debug -Denable_tools=false -Denable_tests=false %DAV1D_ASM_DISABLE% -Db_vscrt=mtd builddir-debug
|
||||
meson compile -C builddir-debug
|
||||
meson install -C builddir-debug
|
||||
release:
|
||||
@@ -775,7 +778,7 @@ mac:
|
||||
""")
|
||||
|
||||
stage('libavif', """
|
||||
git clone -b v1.0.4 --depth 1 https://github.com/AOMediaCodec/libavif.git
|
||||
git clone -b v1.0.4 https://github.com/AOMediaCodec/libavif.git
|
||||
cd libavif
|
||||
win:
|
||||
cmake . ^
|
||||
@@ -805,7 +808,7 @@ mac:
|
||||
""")
|
||||
|
||||
stage('libde265', """
|
||||
git clone --depth 1 -b v1.0.15 https://github.com/strukturag/libde265.git
|
||||
git clone -b v1.0.15 https://github.com/strukturag/libde265.git
|
||||
cd libde265
|
||||
win:
|
||||
cmake . ^
|
||||
@@ -881,7 +884,7 @@ mac:
|
||||
""")
|
||||
|
||||
stage('libheif', """
|
||||
git clone --depth 1 -b v1.17.6 https://github.com/strukturag/libheif.git
|
||||
git clone -b v1.17.6 https://github.com/strukturag/libheif.git
|
||||
cd libheif
|
||||
win:
|
||||
%THIRDPARTY_DIR%\\msys64\\usr\\bin\\sed.exe -i 's/LIBHEIF_EXPORTS/LIBDE265_STATIC_BUILD/g' libheif/CMakeLists.txt
|
||||
@@ -933,7 +936,7 @@ mac:
|
||||
""")
|
||||
|
||||
stage('libjxl', """
|
||||
git clone -b v0.8.2 --depth 1 --recursive --shallow-submodules https://github.com/libjxl/libjxl.git
|
||||
git clone -b v0.8.2 --recursive --shallow-submodules https://github.com/libjxl/libjxl.git
|
||||
cd libjxl
|
||||
""" + setVar("cmake_defines", """
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
@@ -1052,9 +1055,7 @@ depends:yasm/yasm
|
||||
|
||||
stage('nv-codec-headers', """
|
||||
win:
|
||||
git clone https://github.com/FFmpeg/nv-codec-headers.git
|
||||
cd nv-codec-headers
|
||||
git checkout n11.1.5.1
|
||||
git clone -b n12.1.14.0 https://github.com/FFmpeg/nv-codec-headers.git
|
||||
""")
|
||||
|
||||
stage('regex', """
|
||||
@@ -1062,9 +1063,8 @@ stage('regex', """
|
||||
""")
|
||||
|
||||
stage('ffmpeg', """
|
||||
git clone https://github.com/FFmpeg/FFmpeg.git ffmpeg
|
||||
git clone -b n6.1.1 https://github.com/FFmpeg/FFmpeg.git ffmpeg
|
||||
cd ffmpeg
|
||||
git checkout 7268323193
|
||||
win:
|
||||
SET PATH_BACKUP_=%PATH%
|
||||
SET PATH=%ROOT_DIR%\\ThirdParty\\msys64\\usr\\bin;%PATH%
|
||||
@@ -1095,6 +1095,7 @@ depends:yasm/yasm
|
||||
--disable-network \
|
||||
--disable-everything \
|
||||
--enable-protocol=file \
|
||||
--enable-libdav1d \
|
||||
--enable-libopus \
|
||||
--enable-libvpx \
|
||||
--enable-hwaccel=h264_videotoolbox \
|
||||
@@ -1116,6 +1117,7 @@ depends:yasm/yasm
|
||||
--enable-decoder=gif \
|
||||
--enable-decoder=h264 \
|
||||
--enable-decoder=hevc \
|
||||
--enable-decoder=libdav1d \
|
||||
--enable-decoder=libvpx_vp8 \
|
||||
--enable-decoder=libvpx_vp9 \
|
||||
--enable-decoder=mp1 \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
AppVersion 4016002
|
||||
AppVersion 4016003
|
||||
AppVersionStrMajor 4.16
|
||||
AppVersionStrSmall 4.16.2
|
||||
AppVersionStr 4.16.2
|
||||
BetaChannel 0
|
||||
AppVersionStrSmall 4.16.3
|
||||
AppVersionStr 4.16.3
|
||||
BetaChannel 1
|
||||
AlphaVersion 0
|
||||
AppVersionOriginal 4.16.2
|
||||
AppVersionOriginal 4.16.3.beta
|
||||
|
||||
Submodule Telegram/lib_base updated: beef65fac5...3d1ea724a8
@@ -1,3 +1,8 @@
|
||||
4.16.3 beta (05.04.24)
|
||||
|
||||
- Improve media upload speed.
|
||||
- Update FFmpeg to 6.1.1.
|
||||
|
||||
4.16.2 (04.04.24)
|
||||
|
||||
- Use IV by default for Telegraph and some Telegram links.
|
||||
|
||||
2
cmake
2
cmake
Submodule cmake updated: 9f1b85aa9d...022c15d437
Reference in New Issue
Block a user