Merge remote-tracking branch 'tdesktop/dev' into dev
This commit is contained in:
commit
9123ed2079
32 changed files with 167 additions and 186 deletions
|
|
@ -9,7 +9,7 @@
|
||||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||||
ProcessorArchitecture="ARCHITECTURE"
|
ProcessorArchitecture="ARCHITECTURE"
|
||||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||||
Version="2.1.8.0" />
|
Version="2.1.9.0" />
|
||||||
<Properties>
|
<Properties>
|
||||||
<DisplayName>Telegram Desktop</DisplayName>
|
<DisplayName>Telegram Desktop</DisplayName>
|
||||||
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 2,1,8,0
|
FILEVERSION 2,1,9,0
|
||||||
PRODUCTVERSION 2,1,8,0
|
PRODUCTVERSION 2,1,9,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
|
@ -62,10 +62,10 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||||
VALUE "FileDescription", "Telegram Desktop"
|
VALUE "FileDescription", "Telegram Desktop"
|
||||||
VALUE "FileVersion", "2.1.8.0"
|
VALUE "FileVersion", "2.1.9.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||||
VALUE "ProductName", "Telegram Desktop"
|
VALUE "ProductName", "Telegram Desktop"
|
||||||
VALUE "ProductVersion", "2.1.8.0"
|
VALUE "ProductVersion", "2.1.9.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 2,1,8,0
|
FILEVERSION 2,1,9,0
|
||||||
PRODUCTVERSION 2,1,8,0
|
PRODUCTVERSION 2,1,9,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
|
@ -53,10 +53,10 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||||
VALUE "FileDescription", "Telegram Desktop Updater"
|
VALUE "FileDescription", "Telegram Desktop Updater"
|
||||||
VALUE "FileVersion", "2.1.8.0"
|
VALUE "FileVersion", "2.1.9.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||||
VALUE "ProductName", "Telegram Desktop"
|
VALUE "ProductName", "Telegram Desktop"
|
||||||
VALUE "ProductVersion", "2.1.8.0"
|
VALUE "ProductVersion", "2.1.9.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
||||||
|
|
@ -216,11 +216,11 @@ void AutoDownloadBox::setupContent() {
|
||||||
_session->data().photoLoadSettingsChanged();
|
_session->data().photoLoadSettingsChanged();
|
||||||
}
|
}
|
||||||
if (ranges::find_if(allowMoreTypes, _1 != Type::Photo)
|
if (ranges::find_if(allowMoreTypes, _1 != Type::Photo)
|
||||||
!= allowMoreTypes.end()) {
|
!= allowMoreTypes.end()) {
|
||||||
_session->data().documentLoadSettingsChanged();
|
_session->data().documentLoadSettingsChanged();
|
||||||
}
|
}
|
||||||
if (less) {
|
if (less) {
|
||||||
_session->data().checkPlayingVideoFiles();
|
_session->data().checkPlayingAnimations();
|
||||||
}
|
}
|
||||||
closeBox();
|
closeBox();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -72,31 +72,21 @@ EditCaptionBox::EditCaptionBox(
|
||||||
_isAllowedEditMedia = item->media()->allowsEditMedia();
|
_isAllowedEditMedia = item->media()->allowsEditMedia();
|
||||||
_isAlbum = !item->groupId().empty();
|
_isAlbum = !item->groupId().empty();
|
||||||
|
|
||||||
QSize dimensions;
|
auto dimensions = QSize();
|
||||||
auto image = (Image*)nullptr;
|
|
||||||
|
|
||||||
const auto media = item->media();
|
const auto media = item->media();
|
||||||
if (const auto photo = media->photo()) {
|
if (const auto photo = media->photo()) {
|
||||||
_photoMedia = photo->createMediaView();
|
_photoMedia = photo->createMediaView();
|
||||||
_photoMedia->wanted(PhotoSize::Large, _msgId);
|
_photoMedia->wanted(PhotoSize::Large, _msgId);
|
||||||
image = _photoMedia->image(PhotoSize::Large);
|
|
||||||
if (!image) {
|
|
||||||
image = _photoMedia->image(PhotoSize::Thumbnail);
|
|
||||||
if (!image) {
|
|
||||||
image = _photoMedia->image(PhotoSize::Small);
|
|
||||||
if (!image) {
|
|
||||||
image = _photoMedia->thumbnailInline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dimensions = _photoMedia->size(PhotoSize::Large);
|
dimensions = _photoMedia->size(PhotoSize::Large);
|
||||||
|
if (dimensions.isEmpty()) {
|
||||||
|
dimensions = QSize(1, 1);
|
||||||
|
}
|
||||||
_photo = true;
|
_photo = true;
|
||||||
} else if (const auto document = media->document()) {
|
} else if (const auto document = media->document()) {
|
||||||
_documentMedia = document->createMediaView();
|
_documentMedia = document->createMediaView();
|
||||||
_documentMedia->thumbnailWanted(_msgId);
|
_documentMedia->thumbnailWanted(_msgId);
|
||||||
image = _documentMedia->thumbnail();
|
dimensions = _documentMedia->thumbnail()
|
||||||
dimensions = image
|
? _documentMedia->thumbnail()->size()
|
||||||
? image->size()
|
|
||||||
: document->dimensions;
|
: document->dimensions;
|
||||||
if (document->isAnimation()) {
|
if (document->isAnimation()) {
|
||||||
_gifw = style::ConvertScale(document->dimensions.width());
|
_gifw = style::ConvertScale(document->dimensions.width());
|
||||||
|
|
@ -107,24 +97,42 @@ EditCaptionBox::EditCaptionBox(
|
||||||
} else {
|
} else {
|
||||||
_doc = true;
|
_doc = true;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Unexpected("Photo or document should be set.");
|
||||||
}
|
}
|
||||||
const auto editData = PrepareEditText(item);
|
const auto editData = PrepareEditText(item);
|
||||||
|
|
||||||
if (!_animated
|
const auto computeImage = [=] {
|
||||||
&& (dimensions.isEmpty()
|
if (_documentMedia) {
|
||||||
|| _documentMedia
|
return _documentMedia->thumbnail();
|
||||||
|| (!_photoMedia && !image))) {
|
} else if (const auto large = _photoMedia->image(PhotoSize::Large)) {
|
||||||
if (!image) {
|
return large;
|
||||||
_thumbw = 0;
|
} else if (const auto thumbnail = _photoMedia->image(
|
||||||
|
PhotoSize::Thumbnail)) {
|
||||||
|
return thumbnail;
|
||||||
|
} else if (const auto small = _photoMedia->image(PhotoSize::Small)) {
|
||||||
|
return small;
|
||||||
} else {
|
} else {
|
||||||
const auto tw = image->width(), th = image->height();
|
return _photoMedia->thumbnailInline();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!_animated && _documentMedia) {
|
||||||
|
if (dimensions.isEmpty()) {
|
||||||
|
_thumbw = 0;
|
||||||
|
_thumbnailImageLoaded = true;
|
||||||
|
} else {
|
||||||
|
const auto tw = dimensions.width(), th = dimensions.height();
|
||||||
if (tw > th) {
|
if (tw > th) {
|
||||||
_thumbw = (tw * st::msgFileThumbSize) / th;
|
_thumbw = (tw * st::msgFileThumbSize) / th;
|
||||||
} else {
|
} else {
|
||||||
_thumbw = st::msgFileThumbSize;
|
_thumbw = st::msgFileThumbSize;
|
||||||
}
|
}
|
||||||
_thumbnailImage = image;
|
|
||||||
_refreshThumbnail = [=] {
|
_refreshThumbnail = [=] {
|
||||||
|
const auto image = computeImage();
|
||||||
|
if (!image) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto options = Images::Option::Smooth
|
const auto options = Images::Option::Smooth
|
||||||
| Images::Option::RoundedSmall
|
| Images::Option::RoundedSmall
|
||||||
| Images::Option::RoundedTopLeft
|
| Images::Option::RoundedTopLeft
|
||||||
|
|
@ -138,7 +146,9 @@ EditCaptionBox::EditCaptionBox(
|
||||||
options,
|
options,
|
||||||
st::msgFileThumbSize,
|
st::msgFileThumbSize,
|
||||||
st::msgFileThumbSize));
|
st::msgFileThumbSize));
|
||||||
|
_thumbnailImageLoaded = true;
|
||||||
};
|
};
|
||||||
|
_refreshThumbnail();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_documentMedia) {
|
if (_documentMedia) {
|
||||||
|
|
@ -151,13 +161,7 @@ EditCaptionBox::EditCaptionBox(
|
||||||
_isAudio = document->isVoiceMessage()
|
_isAudio = document->isVoiceMessage()
|
||||||
|| document->isAudioFile();
|
|| document->isAudioFile();
|
||||||
}
|
}
|
||||||
if (_refreshThumbnail) {
|
|
||||||
_refreshThumbnail();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!image && !_photoMedia) {
|
|
||||||
image = Image::BlankMedia();
|
|
||||||
}
|
|
||||||
auto maxW = 0, maxH = 0;
|
auto maxW = 0, maxH = 0;
|
||||||
const auto limitW = st::sendMediaPreviewSize;
|
const auto limitW = st::sendMediaPreviewSize;
|
||||||
auto limitH = std::min(st::confirmMaxHeight, _gifh ? _gifh : INT_MAX);
|
auto limitH = std::min(st::confirmMaxHeight, _gifh ? _gifh : INT_MAX);
|
||||||
|
|
@ -175,35 +179,38 @@ EditCaptionBox::EditCaptionBox(
|
||||||
maxH = limitH;
|
maxH = limitH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_thumbnailImage = image;
|
|
||||||
_refreshThumbnail = [=] {
|
_refreshThumbnail = [=] {
|
||||||
|
const auto image = computeImage();
|
||||||
|
const auto use = image ? image : Image::BlankMedia().get();
|
||||||
const auto options = Images::Option::Smooth
|
const auto options = Images::Option::Smooth
|
||||||
| Images::Option::Blurred;
|
| Images::Option::Blurred;
|
||||||
_thumb = image->pixNoCache(
|
_thumb = use->pixNoCache(
|
||||||
maxW * cIntRetinaFactor(),
|
maxW * cIntRetinaFactor(),
|
||||||
maxH * cIntRetinaFactor(),
|
maxH * cIntRetinaFactor(),
|
||||||
options,
|
options,
|
||||||
maxW,
|
maxW,
|
||||||
maxH);
|
maxH);
|
||||||
|
_thumbnailImageLoaded = true;
|
||||||
};
|
};
|
||||||
prepareStreamedPreview();
|
prepareStreamedPreview();
|
||||||
} else {
|
} else {
|
||||||
|
Assert(_photoMedia != nullptr);
|
||||||
|
|
||||||
maxW = dimensions.width();
|
maxW = dimensions.width();
|
||||||
maxH = dimensions.height();
|
maxH = dimensions.height();
|
||||||
_thumbnailImage = image;
|
|
||||||
_refreshThumbnail = [=] {
|
_refreshThumbnail = [=] {
|
||||||
const auto photo = _photoMedia
|
const auto image = computeImage();
|
||||||
? _photoMedia->image(Data::PhotoSize::Large)
|
const auto photo = _photoMedia->image(Data::PhotoSize::Large);
|
||||||
: nullptr;
|
|
||||||
const auto use = photo
|
const auto use = photo
|
||||||
? photo
|
? photo
|
||||||
: _thumbnailImage
|
: image
|
||||||
? _thumbnailImage
|
? image
|
||||||
: Image::BlankMedia().get();
|
: Image::BlankMedia().get();
|
||||||
const auto options = Images::Option::Smooth
|
const auto options = Images::Option::Smooth
|
||||||
| ((_photoMedia && !photo)
|
| (photo
|
||||||
? Images::Option::Blurred
|
? Images::Option(0)
|
||||||
: Images::Option(0));
|
: Images::Option::Blurred);
|
||||||
|
_thumbnailImageLoaded = (photo != nullptr);
|
||||||
_thumb = use->pixNoCache(
|
_thumb = use->pixNoCache(
|
||||||
maxW * cIntRetinaFactor(),
|
maxW * cIntRetinaFactor(),
|
||||||
maxH * cIntRetinaFactor(),
|
maxH * cIntRetinaFactor(),
|
||||||
|
|
@ -276,35 +283,17 @@ EditCaptionBox::EditCaptionBox(
|
||||||
scaleThumbDown();
|
scaleThumbDown();
|
||||||
}
|
}
|
||||||
Assert(_animated || _photo || _doc);
|
Assert(_animated || _photo || _doc);
|
||||||
|
Assert(_thumbnailImageLoaded || _refreshThumbnail);
|
||||||
|
|
||||||
_thumbnailImageLoaded = _photoMedia
|
|
||||||
? (_photoMedia->image(Data::PhotoSize::Large) != nullptr)
|
|
||||||
: _thumbnailImage
|
|
||||||
? true
|
|
||||||
: _documentMedia
|
|
||||||
? !_documentMedia->owner()->hasThumbnail()
|
|
||||||
: true;
|
|
||||||
if (!_thumbnailImageLoaded) {
|
if (!_thumbnailImageLoaded) {
|
||||||
subscribe(_controller->session().downloaderTaskFinished(), [=] {
|
subscribe(_controller->session().downloaderTaskFinished(), [=] {
|
||||||
if (_thumbnailImageLoaded) {
|
if (_thumbnailImageLoaded
|
||||||
|
|| (_photoMedia && !_photoMedia->image(PhotoSize::Large))
|
||||||
|
|| (_documentMedia && !_documentMedia->thumbnail())) {
|
||||||
return;
|
return;
|
||||||
} else if (!_thumbnailImage
|
|
||||||
&& _photoMedia
|
|
||||||
&& _photoMedia->image(PhotoSize::Large)) {
|
|
||||||
_thumbnailImage = _photoMedia->image(PhotoSize::Large);
|
|
||||||
} else if (!_thumbnailImage
|
|
||||||
&& _documentMedia
|
|
||||||
&& _documentMedia->owner()->hasThumbnail()) {
|
|
||||||
_thumbnailImage = _documentMedia->thumbnail();
|
|
||||||
}
|
|
||||||
if (_thumbnailImage) {
|
|
||||||
_thumbnailImageLoaded = !_photoMedia
|
|
||||||
|| _photoMedia->image(PhotoSize::Large);
|
|
||||||
if (_thumbnailImageLoaded) {
|
|
||||||
_refreshThumbnail();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_refreshThumbnail();
|
||||||
|
update();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_field.create(
|
_field.create(
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,6 @@ private:
|
||||||
FullMsgId _msgId;
|
FullMsgId _msgId;
|
||||||
std::shared_ptr<Data::PhotoMedia> _photoMedia;
|
std::shared_ptr<Data::PhotoMedia> _photoMedia;
|
||||||
std::shared_ptr<Data::DocumentMedia> _documentMedia;
|
std::shared_ptr<Data::DocumentMedia> _documentMedia;
|
||||||
Image *_thumbnailImage = nullptr;
|
|
||||||
bool _thumbnailImageLoaded = false;
|
bool _thumbnailImageLoaded = false;
|
||||||
Fn<void()> _refreshThumbnail;
|
Fn<void()> _refreshThumbnail;
|
||||||
bool _animated = false;
|
bool _animated = false;
|
||||||
|
|
|
||||||
|
|
@ -1921,20 +1921,28 @@ void StickersBox::Inner::readVisibleSets() {
|
||||||
int rowFrom = floorclamp(itemsVisibleTop, _rowHeight, 0, _rows.size());
|
int rowFrom = floorclamp(itemsVisibleTop, _rowHeight, 0, _rows.size());
|
||||||
int rowTo = ceilclamp(itemsVisibleBottom, _rowHeight, 0, _rows.size());
|
int rowTo = ceilclamp(itemsVisibleBottom, _rowHeight, 0, _rows.size());
|
||||||
for (int i = rowFrom; i < rowTo; ++i) {
|
for (int i = rowFrom; i < rowTo; ++i) {
|
||||||
if (!_rows[i]->unread) {
|
const auto row = _rows[i].get();
|
||||||
|
if (!row->unread) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (i * _rowHeight < itemsVisibleTop || (i + 1) * _rowHeight > itemsVisibleBottom) {
|
if ((i * _rowHeight < itemsVisibleTop)
|
||||||
|
|| ((i + 1) * _rowHeight > itemsVisibleBottom)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto thumbnailLoading = _rows[i]->set->hasThumbnail()
|
const auto thumbnailLoading = row->set->hasThumbnail()
|
||||||
? _rows[i]->set->thumbnailLoading()
|
? row->set->thumbnailLoading()
|
||||||
: _rows[i]->sticker
|
: row->sticker
|
||||||
? ((_rows[i]->stickerMedia && _rows[i]->stickerMedia->loaded())
|
? row->sticker->thumbnailLoading()
|
||||||
|| _rows[i]->sticker->thumbnailLoading())
|
|
||||||
: false;
|
: false;
|
||||||
if (!thumbnailLoading || _rows[i]->stickerMedia->loaded()) {
|
const auto thumbnailLoaded = row->set->hasThumbnail()
|
||||||
_session->api().readFeaturedSetDelayed(_rows[i]->set->id);
|
? (row->thumbnailMedia
|
||||||
|
&& (row->thumbnailMedia->image()
|
||||||
|
|| !row->thumbnailMedia->content().isEmpty()))
|
||||||
|
: row->sticker
|
||||||
|
? (row->stickerMedia && row->stickerMedia->loaded())
|
||||||
|
: true;
|
||||||
|
if (!thumbnailLoading || thumbnailLoaded) {
|
||||||
|
_session->api().readFeaturedSetDelayed(row->set->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using namespace Ui::Text;
|
||||||
|
|
||||||
using EditLinkAction = Ui::InputField::EditLinkAction;
|
using EditLinkAction = Ui::InputField::EditLinkAction;
|
||||||
using EditLinkSelection = Ui::InputField::EditLinkSelection;
|
using EditLinkSelection = Ui::InputField::EditLinkSelection;
|
||||||
|
|
||||||
|
|
@ -298,7 +300,7 @@ bool HasSendText(not_null<const Ui::InputField*> field) {
|
||||||
if (code != ' '
|
if (code != ' '
|
||||||
&& code != '\n'
|
&& code != '\n'
|
||||||
&& code != '\r'
|
&& code != '\r'
|
||||||
&& !chReplacedBySpace(code)) {
|
&& !IsReplacedBySpace(code)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -585,13 +587,14 @@ void MessageLinksParser::parse() {
|
||||||
const QChar *domainEnd = start + m.capturedEnd(), *p = domainEnd;
|
const QChar *domainEnd = start + m.capturedEnd(), *p = domainEnd;
|
||||||
for (; p < end; ++p) {
|
for (; p < end; ++p) {
|
||||||
QChar ch(*p);
|
QChar ch(*p);
|
||||||
if (chIsLinkEnd(ch)) break; // link finished
|
if (IsLinkEnd(ch)) {
|
||||||
if (chIsAlmostLinkEnd(ch)) {
|
break; // link finished
|
||||||
|
} else if (IsAlmostLinkEnd(ch)) {
|
||||||
const QChar *endTest = p + 1;
|
const QChar *endTest = p + 1;
|
||||||
while (endTest < end && chIsAlmostLinkEnd(*endTest)) {
|
while (endTest < end && IsAlmostLinkEnd(*endTest)) {
|
||||||
++endTest;
|
++endTest;
|
||||||
}
|
}
|
||||||
if (endTest >= end || chIsLinkEnd(*endTest)) {
|
if (endTest >= end || IsLinkEnd(*endTest)) {
|
||||||
break; // link finished at p
|
break; // link finished at p
|
||||||
}
|
}
|
||||||
p = endTest;
|
p = endTest;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ constexpr auto AppId = "{C4A4AE8F-B9F7-4CC7-8A6C-BF7EEE87ACA5}"_cs;
|
||||||
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
|
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
|
||||||
constexpr auto AppName = "Kotatogram Desktop"_cs;
|
constexpr auto AppName = "Kotatogram Desktop"_cs;
|
||||||
constexpr auto AppFile = "Kotatogram"_cs;
|
constexpr auto AppFile = "Kotatogram"_cs;
|
||||||
constexpr auto AppVersion = 2001008;
|
constexpr auto AppVersion = 2001009;
|
||||||
constexpr auto AppVersionStr = "2.1.8";
|
constexpr auto AppVersionStr = "2.1.9";
|
||||||
constexpr auto AppBetaVersion = true;
|
constexpr auto AppBetaVersion = true;
|
||||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||||
|
|
|
||||||
|
|
@ -913,7 +913,7 @@ void DocumentData::save(
|
||||||
const QString &toFile,
|
const QString &toFile,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
bool autoLoading) {
|
bool autoLoading) {
|
||||||
if (const auto media = activeMediaView(); media->loaded(true)) {
|
if (const auto media = activeMediaView(); media && media->loaded(true)) {
|
||||||
auto &l = location(true);
|
auto &l = location(true);
|
||||||
if (!toFile.isEmpty()) {
|
if (!toFile.isEmpty()) {
|
||||||
if (!media->bytes().isEmpty()) {
|
if (!media->bytes().isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -3224,43 +3224,19 @@ void Session::unregisterContactItem(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::registerPlayingVideoFile(not_null<ViewElement*> view) {
|
void Session::checkPlayingAnimations() {
|
||||||
if (++_playingVideoFiles[view] == 1) {
|
auto check = base::flat_set<not_null<ViewElement*>>();
|
||||||
registerHeavyViewPart(view);
|
for (const auto view : _heavyViewParts) {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Session::unregisterPlayingVideoFile(not_null<ViewElement*> view) {
|
|
||||||
const auto i = _playingVideoFiles.find(view);
|
|
||||||
if (i != _playingVideoFiles.end()) {
|
|
||||||
if (!--i->second) {
|
|
||||||
_playingVideoFiles.erase(i);
|
|
||||||
view->checkHeavyPart();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
view->checkHeavyPart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Session::stopPlayingVideoFiles() {
|
|
||||||
for (const auto &[view, count] : base::take(_playingVideoFiles)) {
|
|
||||||
if (const auto media = view->media()) {
|
if (const auto media = view->media()) {
|
||||||
media->stopAnimation();
|
if (const auto document = media->getDocument()) {
|
||||||
}
|
if (document->isAnimation() || document->isVideoFile()) {
|
||||||
}
|
check.emplace(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::checkPlayingVideoFiles() {
|
|
||||||
const auto old = base::take(_playingVideoFiles);
|
|
||||||
for (const auto &[view, count] : old) {
|
|
||||||
if (const auto media = view->media()) {
|
|
||||||
if (const auto left = media->checkAnimationCount()) {
|
|
||||||
_playingVideoFiles.emplace(view, left);
|
|
||||||
registerHeavyViewPart(view);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view->checkHeavyPart();
|
}
|
||||||
|
for (const auto view : check) {
|
||||||
|
view->media()->checkAnimation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3355,7 +3331,6 @@ void Session::registerItemView(not_null<ViewElement*> view) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::unregisterItemView(not_null<ViewElement*> view) {
|
void Session::unregisterItemView(not_null<ViewElement*> view) {
|
||||||
Expects(!_playingVideoFiles.contains(view));
|
|
||||||
Expects(!_heavyViewParts.contains(view));
|
Expects(!_heavyViewParts.contains(view));
|
||||||
|
|
||||||
const auto i = _views.find(view->data());
|
const auto i = _views.find(view->data());
|
||||||
|
|
|
||||||
|
|
@ -613,10 +613,7 @@ public:
|
||||||
UserId contactId,
|
UserId contactId,
|
||||||
not_null<HistoryItem*> item);
|
not_null<HistoryItem*> item);
|
||||||
|
|
||||||
void registerPlayingVideoFile(not_null<ViewElement*> view);
|
void checkPlayingAnimations();
|
||||||
void unregisterPlayingVideoFile(not_null<ViewElement*> view);
|
|
||||||
void checkPlayingVideoFiles();
|
|
||||||
void stopPlayingVideoFiles();
|
|
||||||
|
|
||||||
HistoryItem *findWebPageItem(not_null<WebPageData*> page) const;
|
HistoryItem *findWebPageItem(not_null<WebPageData*> page) const;
|
||||||
QString findContactPhone(not_null<UserData*> contact) const;
|
QString findContactPhone(not_null<UserData*> contact) const;
|
||||||
|
|
@ -958,7 +955,6 @@ private:
|
||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
UserId,
|
UserId,
|
||||||
base::flat_set<not_null<ViewElement*>>> _contactViews;
|
base::flat_set<not_null<ViewElement*>>> _contactViews;
|
||||||
base::flat_map<not_null<ViewElement*>, int> _playingVideoFiles;
|
|
||||||
|
|
||||||
base::flat_set<not_null<WebPageData*>> _webpagesUpdated;
|
base::flat_set<not_null<WebPageData*>> _webpagesUpdated;
|
||||||
base::flat_set<not_null<GameData*>> _gamesUpdated;
|
base::flat_set<not_null<GameData*>> _gamesUpdated;
|
||||||
|
|
|
||||||
|
|
@ -257,9 +257,7 @@ QByteArray SerializeMessage(
|
||||||
SerializeString(message.action.content ? "service" : "message")
|
SerializeString(message.action.content ? "service" : "message")
|
||||||
},
|
},
|
||||||
{ "date", SerializeDate(message.date) },
|
{ "date", SerializeDate(message.date) },
|
||||||
{ "edited", SerializeDate(message.edited) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
context.nesting.push_back(Context::kObject);
|
context.nesting.push_back(Context::kObject);
|
||||||
const auto serialized = [&] {
|
const auto serialized = [&] {
|
||||||
context.nesting.pop_back();
|
context.nesting.pop_back();
|
||||||
|
|
@ -273,6 +271,10 @@ QByteArray SerializeMessage(
|
||||||
values.emplace_back(key, value);
|
values.emplace_back(key, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if (message.edited) {
|
||||||
|
pushBare("edited", SerializeDate(message.edited));
|
||||||
|
}
|
||||||
|
|
||||||
const auto push = [&](const QByteArray &key, const auto &value) {
|
const auto push = [&](const QByteArray &key, const auto &value) {
|
||||||
if constexpr (std::is_arithmetic_v<std::decay_t<decltype(value)>>) {
|
if constexpr (std::is_arithmetic_v<std::decay_t<decltype(value)>>) {
|
||||||
pushBare(key, Data::NumberToString(value));
|
pushBare(key, Data::NumberToString(value));
|
||||||
|
|
|
||||||
|
|
@ -1799,8 +1799,6 @@ void HistoryWidget::showHistory(
|
||||||
cancelTypingAction();
|
cancelTypingAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
session().data().stopPlayingVideoFiles();
|
|
||||||
|
|
||||||
clearReplyReturns();
|
clearReplyReturns();
|
||||||
if (_history) {
|
if (_history) {
|
||||||
if (Ui::InFocusChain(_list)) {
|
if (Ui::InFocusChain(_list)) {
|
||||||
|
|
|
||||||
|
|
@ -229,4 +229,12 @@ TextState Contact::textState(QPoint point, StateRequest request) const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Contact::unloadHeavyPart() {
|
||||||
|
_userpic = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Contact::hasHeavyPart() const {
|
||||||
|
return (_userpic != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
||||||
|
|
@ -59,13 +59,8 @@ public:
|
||||||
// Should be called only by Data::Session.
|
// Should be called only by Data::Session.
|
||||||
void updateSharedContactUserId(UserId userId) override;
|
void updateSharedContactUserId(UserId userId) override;
|
||||||
|
|
||||||
void unloadHeavyPart() override {
|
void unloadHeavyPart() override;
|
||||||
_userpic = nullptr;
|
bool hasHeavyPart() const override;
|
||||||
}
|
|
||||||
|
|
||||||
bool hasHeavyPart() const override {
|
|
||||||
return (_userpic != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSize countOptimalSize() override;
|
QSize countOptimalSize() override;
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ public:
|
||||||
void stopAnimation() override {
|
void stopAnimation() override {
|
||||||
if (_attach) _attach->stopAnimation();
|
if (_attach) _attach->stopAnimation();
|
||||||
}
|
}
|
||||||
int checkAnimationCount() override {
|
void checkAnimation() override {
|
||||||
return _attach ? _attach->checkAnimationCount() : 0;
|
if (_attach) _attach->checkAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<GameData*> game() {
|
not_null<GameData*> game() {
|
||||||
|
|
|
||||||
|
|
@ -1425,7 +1425,7 @@ void Gif::playAnimation(bool autoplay) {
|
||||||
stopAnimation();
|
stopAnimation();
|
||||||
} else if (_dataMedia->canBePlayed()) {
|
} else if (_dataMedia->canBePlayed()) {
|
||||||
if (!autoplayEnabled()) {
|
if (!autoplayEnabled()) {
|
||||||
history()->owner().checkPlayingVideoFiles();
|
history()->owner().checkPlayingAnimations();
|
||||||
}
|
}
|
||||||
createStreamedPlayer();
|
createStreamedPlayer();
|
||||||
}
|
}
|
||||||
|
|
@ -1482,12 +1482,11 @@ void Gif::checkStreamedIsStarted() const {
|
||||||
void Gif::setStreamed(std::unique_ptr<Streamed> value) {
|
void Gif::setStreamed(std::unique_ptr<Streamed> value) {
|
||||||
const auto removed = (_streamed && !value);
|
const auto removed = (_streamed && !value);
|
||||||
const auto set = (!_streamed && value);
|
const auto set = (!_streamed && value);
|
||||||
if (removed) {
|
|
||||||
history()->owner().unregisterPlayingVideoFile(_parent);
|
|
||||||
}
|
|
||||||
_streamed = std::move(value);
|
_streamed = std::move(value);
|
||||||
if (set) {
|
if (set) {
|
||||||
history()->owner().registerPlayingVideoFile(_parent);
|
history()->owner().registerHeavyViewPart(_parent);
|
||||||
|
} else if (removed) {
|
||||||
|
_parent->checkHeavyPart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1539,14 +1538,10 @@ void Gif::stopAnimation() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Gif::checkAnimationCount() {
|
void Gif::checkAnimation() {
|
||||||
if (!_streamed) {
|
if (_streamed && !autoplayEnabled()) {
|
||||||
return 0;
|
stopAnimation();
|
||||||
} else if (autoplayEnabled()) {
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
stopAnimation();
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float64 Gif::dataProgress() const {
|
float64 Gif::dataProgress() const {
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ public:
|
||||||
StateRequest request) const override;
|
StateRequest request) const override;
|
||||||
|
|
||||||
void stopAnimation() override;
|
void stopAnimation() override;
|
||||||
int checkAnimationCount() override;
|
void checkAnimation() override;
|
||||||
|
|
||||||
TextWithEntities getCaption() const override {
|
TextWithEntities getCaption() const override {
|
||||||
return _caption.toTextWithEntities();
|
return _caption.toTextWithEntities();
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,14 @@ Location::~Location() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Location::unloadHeavyPart() {
|
||||||
|
_media = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Location::hasHeavyPart() const {
|
||||||
|
return (_media != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void Location::ensureMediaCreated() const {
|
void Location::ensureMediaCreated() const {
|
||||||
if (_media) {
|
if (_media) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -58,12 +58,8 @@ public:
|
||||||
return isBubbleBottom();
|
return isBubbleBottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
void unloadHeavyPart() override {
|
void unloadHeavyPart() override;
|
||||||
_media = nullptr;
|
bool hasHeavyPart() const override;
|
||||||
}
|
|
||||||
bool hasHeavyPart() const override {
|
|
||||||
return (_media != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ensureMediaCreated() const;
|
void ensureMediaCreated() const;
|
||||||
|
|
|
||||||
|
|
@ -141,8 +141,7 @@ public:
|
||||||
}
|
}
|
||||||
virtual void clearStickerLoopPlayed() {
|
virtual void clearStickerLoopPlayed() {
|
||||||
}
|
}
|
||||||
virtual int checkAnimationCount() {
|
virtual void checkAnimation() {
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] virtual QSize sizeForGrouping() const {
|
[[nodiscard]] virtual QSize sizeForGrouping() const {
|
||||||
|
|
|
||||||
|
|
@ -425,21 +425,19 @@ void GroupedMedia::updateNeedBubbleState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupedMedia::stopAnimation() {
|
void GroupedMedia::stopAnimation() {
|
||||||
for (auto &part : _parts) {
|
for (const auto &part : _parts) {
|
||||||
part.content->stopAnimation();
|
part.content->stopAnimation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GroupedMedia::checkAnimationCount() {
|
void GroupedMedia::checkAnimation() {
|
||||||
auto result = 0;
|
for (const auto &part : _parts) {
|
||||||
for (auto &part : _parts) {
|
part.content->checkAnimation();
|
||||||
result += part.content->checkAnimationCount();
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupedMedia::hasHeavyPart() const {
|
bool GroupedMedia::hasHeavyPart() const {
|
||||||
for (auto &part : _parts) {
|
for (const auto &part : _parts) {
|
||||||
if (part.content->hasHeavyPart()) {
|
if (part.content->hasHeavyPart()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -448,7 +446,7 @@ bool GroupedMedia::hasHeavyPart() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupedMedia::unloadHeavyPart() {
|
void GroupedMedia::unloadHeavyPart() {
|
||||||
for (auto &part : _parts) {
|
for (const auto &part : _parts) {
|
||||||
part.content->unloadHeavyPart();
|
part.content->unloadHeavyPart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopAnimation() override;
|
void stopAnimation() override;
|
||||||
int checkAnimationCount() override;
|
void checkAnimation() override;
|
||||||
bool hasHeavyPart() const override;
|
bool hasHeavyPart() const override;
|
||||||
void unloadHeavyPart() override;
|
void unloadHeavyPart() override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,8 @@ public:
|
||||||
void stopAnimation() override {
|
void stopAnimation() override {
|
||||||
if (_attach) _attach->stopAnimation();
|
if (_attach) _attach->stopAnimation();
|
||||||
}
|
}
|
||||||
int checkAnimationCount() override {
|
void checkAnimation() override {
|
||||||
return _attach ? _attach->checkAnimationCount() : 0;
|
if (_attach) _attach->checkAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<WebPageData*> webpage() {
|
not_null<WebPageData*> webpage() {
|
||||||
|
|
|
||||||
|
|
@ -847,6 +847,9 @@ void Pip::setupPanel() {
|
||||||
return _instance.info().video.size;
|
return _instance.info().video.size;
|
||||||
}
|
}
|
||||||
const auto media = _data->activeMediaView();
|
const auto media = _data->activeMediaView();
|
||||||
|
if (media) {
|
||||||
|
media->goodThumbnailWanted();
|
||||||
|
}
|
||||||
const auto good = media ? media->goodThumbnail() : nullptr;
|
const auto good = media ? media->goodThumbnail() : nullptr;
|
||||||
const auto original = good ? good->size() : _data->dimensions;
|
const auto original = good ? good->size() : _data->dimensions;
|
||||||
return original.isEmpty() ? QSize(1, 1) : original;
|
return original.isEmpty() ? QSize(1, 1) : original;
|
||||||
|
|
@ -1387,6 +1390,9 @@ QImage Pip::videoFrame(const FrameRequest &request) const {
|
||||||
: _data->inlineThumbnailBytes().isEmpty()
|
: _data->inlineThumbnailBytes().isEmpty()
|
||||||
? nullptr
|
? nullptr
|
||||||
: _data->createMediaView();
|
: _data->createMediaView();
|
||||||
|
if (use) {
|
||||||
|
use->goodThumbnailWanted();
|
||||||
|
}
|
||||||
const auto good = use ? use->goodThumbnail() : nullptr;
|
const auto good = use ? use->goodThumbnail() : nullptr;
|
||||||
const auto thumb = use ? use->thumbnail() : nullptr;
|
const auto thumb = use ? use->thumbnail() : nullptr;
|
||||||
const auto blurred = use ? use->thumbnailInline() : nullptr;
|
const auto blurred = use ? use->thumbnailInline() : nullptr;
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ StreamedFileDownloader::StreamedFileDownloader(
|
||||||
StreamedFileDownloader::~StreamedFileDownloader() {
|
StreamedFileDownloader::~StreamedFileDownloader() {
|
||||||
if (!_finished) {
|
if (!_finished) {
|
||||||
cancel();
|
cancel();
|
||||||
|
} else {
|
||||||
|
_reader->cancelForDownloader(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -375,7 +375,7 @@ void EmptyUserpic::fillString(const QString &name) {
|
||||||
}
|
}
|
||||||
} else if (!letterFound && ch->isLetterOrNumber()) {
|
} else if (!letterFound && ch->isLetterOrNumber()) {
|
||||||
letterFound = true;
|
letterFound = true;
|
||||||
if (ch + 1 != end && chIsDiac(*(ch + 1))) {
|
if (ch + 1 != end && Ui::Text::IsDiac(*(ch + 1))) {
|
||||||
letters.push_back(QString(ch, 2));
|
letters.push_back(QString(ch, 2));
|
||||||
levels.push_back(level);
|
levels.push_back(level);
|
||||||
++ch;
|
++ch;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ QString fillLetters(const QString &name) {
|
||||||
}
|
}
|
||||||
} else if (!letterFound && ch->isLetterOrNumber()) {
|
} else if (!letterFound && ch->isLetterOrNumber()) {
|
||||||
letterFound = true;
|
letterFound = true;
|
||||||
if (ch + 1 != end && chIsDiac(*(ch + 1))) {
|
if (ch + 1 != end && Ui::Text::IsDiac(*(ch + 1))) {
|
||||||
letters.push_back(QString(ch, 2));
|
letters.push_back(QString(ch, 2));
|
||||||
levels.push_back(level);
|
levels.push_back(level);
|
||||||
++ch;
|
++ch;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
AppVersion 2001008
|
AppVersion 2001009
|
||||||
AppVersionStrMajor 2.1
|
AppVersionStrMajor 2.1
|
||||||
AppVersionStrSmall 2.1.8
|
AppVersionStrSmall 2.1.9
|
||||||
AppVersionStr 2.1.8
|
AppVersionStr 2.1.9
|
||||||
BetaChannel 1
|
BetaChannel 1
|
||||||
AlphaVersion 0
|
AlphaVersion 0
|
||||||
AppVersionOriginal 2.1.8.beta
|
AppVersionOriginal 2.1.9.beta
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit c87e6390de08f0b0f98ef8666304370d946adfa0
|
Subproject commit c1877cc35f5d3e36a5d71728ebfa6e1605a4f980
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
2.1.9 beta (04.06.20)
|
||||||
|
|
||||||
|
- Several crash fixes.
|
||||||
|
|
||||||
2.1.8 beta (03.06.20)
|
2.1.8 beta (03.06.20)
|
||||||
|
|
||||||
- Add support for full group message history export.
|
- Add support for full group message history export.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue