sticker packs done

This commit is contained in:
John Preston 2015-05-19 18:46:45 +03:00
parent 136fd5c8e1
commit 92858dc7d3
39 changed files with 2312 additions and 702 deletions

View File

@ -428,7 +428,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_emoji_category5" = "Activity"; "lng_emoji_category5" = "Activity";
"lng_emoji_category6" = "Travel & Places"; "lng_emoji_category6" = "Travel & Places";
"lng_emoji_category7" = "Objects & Symbols"; "lng_emoji_category7" = "Objects & Symbols";
"lng_emoji_category8" = "Stickers";
"lng_switch_stickers" = "Stickers";
"lng_switch_emoji" = "Emoji";
"lng_custom_stickers" = "Custom stickers";
"lng_stickers_remove_pack" = "Remove «{sticker_pack}»?";
"lng_stickers_add_pack" = "Add {count:_not_used_|# Sticker|# Stickers}";
"lng_stickers_share_pack" = "Share Stickers";
"lng_stickers_not_found" = "Sticker pack not found.";
"lng_stickers_copied" = "Sticker pack link copied to clipboard.";
"lng_in_dlg_photo" = "Photo"; "lng_in_dlg_photo" = "Photo";
"lng_in_dlg_video" = "Video"; "lng_in_dlg_video" = "Video";
@ -481,6 +490,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_context_save_video" = "Save Video As.."; "lng_context_save_video" = "Save Video As..";
"lng_context_open_audio" = "Open Audio"; "lng_context_open_audio" = "Open Audio";
"lng_context_save_audio" = "Save Audio As.."; "lng_context_save_audio" = "Save Audio As..";
"lng_context_pack_info" = "Pack Info";
"lng_context_open_file" = "Open File"; "lng_context_open_file" = "Open File";
"lng_context_save_file" = "Save File As.."; "lng_context_save_file" = "Save File As..";
"lng_context_forward_file" = "Forward File"; "lng_context_forward_file" = "Forward File";

View File

@ -308,7 +308,8 @@ scrollDef: flatScroll {
width: 10px; width: 10px;
minHeight: 20px; minHeight: 20px;
deltax: 3px; deltax: 3px;
deltay: 3px; deltat: 3px;
deltab: 3px;
topsh: 2px; topsh: 2px;
bottomsh: 2px; bottomsh: 2px;
@ -983,12 +984,12 @@ btnAttachPhoto: iconedButton(btnAttachDocument) {
} }
btnAttachEmoji: iconedButton(btnAttachDocument) { btnAttachEmoji: iconedButton(btnAttachDocument) {
overBgColor: white; overBgColor: white;
icon: sprite(311px, 221px, 20px, 20px); icon: sprite(363px, 344px, 21px, 22px);
iconPos: point(6px, 13px); iconPos: point(6px, 13px);
downIcon: sprite(311px, 221px, 20px, 20px); downIcon: sprite(363px, 344px, 21px, 22px);
downIconPos: point(6px, 13px); downIconPos: point(6px, 13px);
width: 32px; width: 33px;
} }
replySkip: 51px; replySkip: 51px;
@ -1020,7 +1021,8 @@ historyScroll: flatScroll(scrollDef) {
width: 12px; width: 12px;
deltax: 3px; deltax: 3px;
deltay: 3px; deltat: 3px;
deltab: 3px;
topsh: 0px; topsh: 0px;
bottomsh: -1px; bottomsh: -1px;
@ -1452,19 +1454,62 @@ dpiFont2: linkFont;
dpiFont3: linkFont; dpiFont3: linkFont;
dpiFont4: linkFont; dpiFont4: linkFont;
emojiScroll: flatScroll(scrollDef) { newScroll: flatScroll(scrollDef) {
width: 5px; barColor: #3f729734;
deltax: 2px; bgColor: #214f751a;
deltay: 1px; barOverColor: #3f729734;
bgOverColor: #214f751a;
deltax: 5px;
width: 14px;
deltat: 6px;
deltab: 6px;
topsh: 0px; topsh: 0px;
bottomsh: 0px; bottomsh: 0px;
hiding: 0;
}
stickersMaxHeight: 340px;
stickersAddOrShare: 70px;
btnStickersAdd: flatButton(btnDefNext, btnDefBig) {
width: 180px;
height: 42px;
textTop: 9px;
overTextTop: 9px;
downTextTop: 10px;
font: font(17px);
overFont: font(17px);
bgColor: #15c23c;
overBgColor: #13a835;
downBgColor: #13a835;
}
btnStickersClose: iconedButton(notifyClose) {
iconPos: point(21px, 21px);
downIconPos: point(21px, 22px);
width: 52px;
height: 48px;
}
stickersWidth: 344px;
stickersPadding: 10px;
stickersSize: size(64px, 64px);
stickersScroll: flatScroll(newScroll) {
deltab: 76px;
}
emojiScroll: flatScroll(newScroll) {
deltat: 48px;
} }
emojiRecent: sprite(0px, 196px, 21px, 22px); emojiRecent: sprite(0px, 196px, 21px, 22px);
emojiRecentOver: sprite(287px, 220px, 21px, 22px); emojiRecentOver: sprite(287px, 220px, 21px, 22px);
emojiRecentActive: sprite(287px, 242px, 21px, 22px); emojiRecentActive: sprite(287px, 242px, 21px, 22px);
emojiPeople: sprite(21px, 196px, 21px, 22px); emojiPeople: sprite(21px, 196px, 21px, 22px);
emojiPeopleOver: sprite(298px, 220px, 21px, 22px); emojiPeopleOver: sprite(308px, 220px, 21px, 22px);
emojiPeopleActive: sprite(298px, 242px, 21px, 22px); emojiPeopleActive: sprite(308px, 242px, 21px, 22px);
emojiNature: sprite(42px, 196px, 21px, 22px); emojiNature: sprite(42px, 196px, 21px, 22px);
emojiNatureOver: sprite(245px, 264px, 21px, 22px); emojiNatureOver: sprite(245px, 264px, 21px, 22px);
emojiNatureActive: sprite(245px, 286px, 21px, 22px); emojiNatureActive: sprite(245px, 286px, 21px, 22px);
@ -1483,10 +1528,13 @@ emojiTravelActive: sprite(321px, 366px, 21px, 22px);
emojiObjects: sprite(147px, 196px, 21px, 22px); emojiObjects: sprite(147px, 196px, 21px, 22px);
emojiObjectsOver: sprite(342px, 344px, 21px, 22px); emojiObjectsOver: sprite(342px, 344px, 21px, 22px);
emojiObjectsActive: sprite(342px, 366px, 21px, 22px); emojiObjectsActive: sprite(342px, 366px, 21px, 22px);
emojiPanCategories: #f7f7f7;
rbEmoji: flatCheckbox { rbEmoji: flatCheckbox {
textColor: transparent; textColor: transparent;
bgColor: transparent; bgColor: emojiPanCategories;
disColor: transparent; disColor: emojiPanCategories;
width: 36px; width: 36px;
height: 46px; height: 46px;
@ -1565,27 +1613,33 @@ rbEmojiObjects: flatCheckbox(rbEmoji) {
disImageRect: emojiObjects; disImageRect: emojiObjects;
chkDisImageRect: emojiObjectsActive; chkDisImageRect: emojiObjectsActive;
} }
emojiPanPadding: margins(5px, 0px, 0px, 5px); emojiPanPadding: 10px;
emojiPanSize: size(39px, 35px); emojiPanSize: size(39px, 35px);
emojiPanFullSize: size(300px, 321px);
emojiPanDuration: 200; emojiPanDuration: 200;
emojiPanHover: #f0f0f0; emojiPanHover: #f0f4f7;
emojiPanRound: 2px; emojiPanRound: 2px;
emojiPanHeader: 25px; emojiPanHeader: 42px;
emojiPanHeaderFont: font(fsize semibold); emojiPanHeaderFont: font(fsize semibold);
emojiPanHeaderColor: #999; emojiPanHeaderColor: #999;
emojiPanHeaderLeft: 5px; emojiPanHeaderLeft: 17px;
emojiPanHeaderTop: 5px; emojiPanHeaderTop: 12px;
emojiPanHeaderBg: #fffd; emojiPanHeaderBg: #fffffff2;
emojiColorsPadding: 5px; emojiColorsPadding: 5px;
emojiColorsSep: 1px; emojiColorsSep: 1px;
emojiColorsSepColor: #d5d5d5; emojiColorsSepColor: #d5d5d5;
toStickersImg: sprite(); emojiSwitchSkip: 27px;
toEmojiImg: sprite(); emojiSwitchImgSkip: 21px;
emojiSwitchStickers: sprite(318px, 328px, 8px, 12px);
emojiSwitchEmoji: sprite(310px, 328px, 8px, 12px);
emojiSwitchColor: #42a8db;
stickerPanSize: size(55px, 55px);
stickerPanRound: 3px; stickerPanRound: 3px;
stickerPanPadding: 2px; stickerPanPadding: 11px;
stickerPanDelete: sprite(123px, 132px, 12px, 12px); stickerPanDelete: sprite(123px, 132px, 12px, 12px);
stickerPanDeleteOpacity: 0.5; stickerPanDeleteOpacity: 0.5;

View File

@ -173,7 +173,8 @@ flatScroll {
width: number; width: number;
minHeight: number; minHeight: number;
deltax: number; deltax: number;
deltay: number; deltat: number;
deltab: number;
topsh: number; topsh: number;
bottomsh: number; bottomsh: number;

View File

@ -34,7 +34,6 @@ ApiWrap::ApiWrap(QObject *parent) : QObject(parent) {
} }
void ApiWrap::init() { void ApiWrap::init() {
App::initMedia();
} }
void ApiWrap::itemRemoved(HistoryItem *item) { void ApiWrap::itemRemoved(HistoryItem *item) {

View File

@ -633,7 +633,7 @@ namespace App {
const MTPDphotoSize &d(size.c_photoSize()); const MTPDphotoSize &d(size.c_photoSize());
if (d.vlocation.type() == mtpc_fileLocation) { if (d.vlocation.type() == mtpc_fileLocation) {
const MTPDfileLocation &l(d.vlocation.c_fileLocation()); const MTPDfileLocation &l(d.vlocation.c_fileLocation());
return ImagePtr(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v, d.vsize.v); return ImagePtr(StorageImageLocation(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v), d.vsize.v);
} }
} break; } break;
case mtpc_photoCachedSize: { case mtpc_photoCachedSize: {
@ -642,17 +642,43 @@ namespace App {
const MTPDfileLocation &l(d.vlocation.c_fileLocation()); const MTPDfileLocation &l(d.vlocation.c_fileLocation());
const string &s(d.vbytes.c_string().v); const string &s(d.vbytes.c_string().v);
QByteArray bytes(s.data(), s.size()); QByteArray bytes(s.data(), s.size());
return ImagePtr(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v, bytes); return ImagePtr(StorageImageLocation(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v), bytes);
} else if (d.vlocation.type() == mtpc_fileLocationUnavailable) { } else if (d.vlocation.type() == mtpc_fileLocationUnavailable) {
const string &s(d.vbytes.c_string().v); const string &s(d.vbytes.c_string().v);
QByteArray bytes(s.data(), s.size()); QByteArray bytes(s.data(), s.size());
return ImagePtr(d.vw.v, d.vh.v, 0, 0, 0, 0, bytes); return ImagePtr(StorageImageLocation(d.vw.v, d.vh.v, 0, 0, 0, 0), bytes);
} }
} break; } break;
} }
return ImagePtr(); return ImagePtr();
} }
StorageImageLocation imageLocation(const MTPPhotoSize &size) {
switch (size.type()) {
case mtpc_photoSize: {
const MTPDphotoSize &d(size.c_photoSize());
if (d.vlocation.type() == mtpc_fileLocation) {
const MTPDfileLocation &l(d.vlocation.c_fileLocation());
return StorageImageLocation(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v);
}
} break;
case mtpc_photoCachedSize: {
const MTPDphotoCachedSize &d(size.c_photoCachedSize());
if (d.vlocation.type() == mtpc_fileLocation) {
const MTPDfileLocation &l(d.vlocation.c_fileLocation());
const string &s(d.vbytes.c_string().v);
QByteArray bytes(s.data(), s.size());
return StorageImageLocation(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v);
} else if (d.vlocation.type() == mtpc_fileLocationUnavailable) {
const string &s(d.vbytes.c_string().v);
QByteArray bytes(s.data(), s.size());
return StorageImageLocation(d.vw.v, d.vh.v, 0, 0, 0, 0);
}
} break;
}
return StorageImageLocation();
}
void feedWereRead(const QVector<MTPint> &msgsIds) { void feedWereRead(const QVector<MTPint> &msgsIds) {
for (QVector<MTPint>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) { for (QVector<MTPint>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) {
MsgsData::const_iterator j = msgsData.constFind(i->v); MsgsData::const_iterator j = msgsData.constFind(i->v);
@ -874,7 +900,7 @@ namespace App {
switch (document.type()) { switch (document.type()) {
case mtpc_document: { case mtpc_document: {
const MTPDdocument &d(document.c_document()); const MTPDdocument &d(document.c_document());
return App::document(d.vid.v, 0, d.vaccess_hash.v, d.vdate.v, d.vattributes.c_vector().v, qs(d.vmime_type), ImagePtr(thumb, "JPG"), d.vdc_id.v, d.vsize.v); return App::documentSet(d.vid.v, 0, d.vaccess_hash.v, d.vdate.v, d.vattributes.c_vector().v, qs(d.vmime_type), ImagePtr(thumb, "JPG"), d.vdc_id.v, d.vsize.v, StorageImageLocation());
} break; } break;
case mtpc_documentEmpty: return App::document(document.c_documentEmpty().vid.v); case mtpc_documentEmpty: return App::document(document.c_documentEmpty().vid.v);
} }
@ -887,14 +913,14 @@ namespace App {
return feedDocument(document.c_document(), convert); return feedDocument(document.c_document(), convert);
} break; } break;
case mtpc_documentEmpty: { case mtpc_documentEmpty: {
return App::document(document.c_documentEmpty().vid.v, convert); return App::documentSet(document.c_documentEmpty().vid.v, convert, 0, 0, QVector<MTPDocumentAttribute>(), QString(), ImagePtr(), 0, 0, StorageImageLocation());
} break; } break;
} }
return App::document(0); return App::document(0);
} }
DocumentData *feedDocument(const MTPDdocument &document, DocumentData *convert) { DocumentData *feedDocument(const MTPDdocument &document, DocumentData *convert) {
return App::document(document.vid.v, convert, document.vaccess_hash.v, document.vdate.v, document.vattributes.c_vector().v, qs(document.vmime_type), App::image(document.vthumb), document.vdc_id.v, document.vsize.v); return App::documentSet(document.vid.v, convert, document.vaccess_hash.v, document.vdate.v, document.vattributes.c_vector().v, qs(document.vmime_type), App::image(document.vthumb), document.vdc_id.v, document.vsize.v, App::imageLocation(document.vthumb));
} }
WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert) { WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert) {
@ -1128,7 +1154,15 @@ namespace App {
return result; return result;
} }
DocumentData *document(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size) { DocumentData *document(const DocumentId &document) {
DocumentsData::const_iterator i = documentsData.constFind(document);
if (i == documentsData.cend()) {
i = documentsData.insert(document, new DocumentData(document));
}
return i.value();
}
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation) {
if (convert) { if (convert) {
if (convert->id != document) { if (convert->id != document) {
DocumentsData::iterator i = documentsData.find(convert->id); DocumentsData::iterator i = documentsData.find(convert->id);
@ -1146,12 +1180,28 @@ namespace App {
convert->thumb = thumb; convert->thumb = thumb;
convert->dc = dc; convert->dc = dc;
convert->size = size; convert->size = size;
} else if (convert->thumb->isNull() && !thumb->isNull()) { } else {
convert->thumb = thumb; if (!thumb->isNull() && (convert->thumb->isNull() || convert->thumb->width() < thumb->width() || convert->thumb->height() < thumb->height())) {
convert->thumb = thumb;
}
if (convert->sticker && !attributes.isEmpty() && (convert->sticker->alt.isEmpty() || convert->sticker->set.type() == mtpc_inputStickerSetEmpty)) {
for (QVector<MTPDocumentAttribute>::const_iterator i = attributes.cbegin(), e = attributes.cend(); i != e; ++i) {
if (i->type() == mtpc_documentAttributeSticker) {
const MTPDdocumentAttributeSticker &d(i->c_documentAttributeSticker());
if (d.valt.c_string().v.length() > 0) {
convert->sticker->alt = qs(d.valt);
convert->sticker->set = d.vstickerset;
}
}
}
}
}
if (convert->sticker && !convert->sticker->loc.dc && thumbLocation.dc) {
convert->sticker->loc = thumbLocation;
} }
if (convert->location.check()) { if (convert->location.check()) {
Local::writeFileLocation(mediaKey(mtpc_inputDocumentFileLocation, convert->dc, convert->id), convert->location); Local::writeFileLocation(mediaKey(DocumentFileLocation, convert->dc, convert->id), convert->location);
} }
} }
DocumentsData::const_iterator i = documentsData.constFind(document); DocumentsData::const_iterator i = documentsData.constFind(document);
@ -1161,6 +1211,7 @@ namespace App {
result = convert; result = convert;
} else { } else {
result = new DocumentData(document, access, date, attributes, mime, thumb, dc, size); result = new DocumentData(document, access, date, attributes, mime, thumb, dc, size);
if (result->sticker) result->sticker->loc = thumbLocation;
} }
documentsData.insert(document, result); documentsData.insert(document, result);
} else { } else {
@ -1175,19 +1226,23 @@ namespace App {
result->dc = dc; result->dc = dc;
result->size = size; result->size = size;
} else { } else {
if (result->thumb->isNull() && !thumb->isNull()) { if (!thumb->isNull() && (result->thumb->isNull() || result->thumb->width() < thumb->width() || result->thumb->height() < thumb->height())) {
result->thumb = thumb; result->thumb = thumb;
} }
if (result->sticker && result->sticker->alt.isEmpty()) { if (result->sticker && !attributes.isEmpty() && (result->sticker->alt.isEmpty() || result->sticker->set.type() == mtpc_inputStickerSetEmpty)) {
for (QVector<MTPDocumentAttribute>::const_iterator i = attributes.cbegin(), e = attributes.cend(); i != e; ++i) { for (QVector<MTPDocumentAttribute>::const_iterator i = attributes.cbegin(), e = attributes.cend(); i != e; ++i) {
if (i->type() == mtpc_documentAttributeSticker) { if (i->type() == mtpc_documentAttributeSticker) {
const MTPDdocumentAttributeSticker &d(i->c_documentAttributeSticker()); const MTPDdocumentAttributeSticker &d(i->c_documentAttributeSticker());
if (d.valt.c_string().v.length() > 0) { if (d.valt.c_string().v.length() > 0) {
result->sticker->alt = qs(d.valt); result->sticker->alt = qs(d.valt);
result->sticker->set = d.vstickerset;
} }
} }
} }
} }
if (result->sticker && !result->sticker->loc.dc && thumbLocation.dc) {
result->sticker->loc = thumbLocation;
}
} }
} }
} }
@ -1464,8 +1519,9 @@ namespace App {
if (api()) api()->clearWebPageRequests(); if (api()) api()->clearWebPageRequests();
cSetRecentStickers(RecentStickerPack()); cSetRecentStickers(RecentStickerPack());
cSetStickersHash(QByteArray()); cSetStickersHash(QByteArray());
cSetStickers(AllStickers());
cSetEmojiStickers(EmojiStickersMap()); cSetEmojiStickers(EmojiStickersMap());
cSetStickerSets(StickerSets());
cSetLastStickersUpdate(0);
::videoItems.clear(); ::videoItems.clear();
::audioItems.clear(); ::audioItems.clear();
::documentItems.clear(); ::documentItems.clear();
@ -1854,6 +1910,12 @@ namespace App {
} }
} }
void stickersBox(const QString &name) {
if (App::main()) {
App::main()->stickersBox(MTP_inputStickerSetShortName(MTP_string(name)));
}
}
void openLocalUrl(const QString &url) { void openLocalUrl(const QString &url) {
if (App::main()) { if (App::main()) {
App::main()->openLocalUrl(url); App::main()->openLocalUrl(url);

View File

@ -87,6 +87,7 @@ namespace App {
int32 maxMsgId(); int32 maxMsgId();
ImagePtr image(const MTPPhotoSize &size); ImagePtr image(const MTPPhotoSize &size);
StorageImageLocation imageLocation(const MTPPhotoSize &size);
PhotoData *feedPhoto(const MTPPhoto &photo, const PreparedPhotoThumbs &thumbs); PhotoData *feedPhoto(const MTPPhoto &photo, const PreparedPhotoThumbs &thumbs);
PhotoData *feedPhoto(const MTPPhoto &photo, PhotoData *convert = 0); PhotoData *feedPhoto(const MTPPhoto &photo, PhotoData *convert = 0);
@ -117,7 +118,8 @@ namespace App {
PhotoData *photo(const PhotoId &photo, PhotoData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()); PhotoData *photo(const PhotoId &photo, PhotoData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr());
VideoData *video(const VideoId &video, VideoData *convert = 0, 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); VideoData *video(const VideoId &video, VideoData *convert = 0, 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);
AudioData *audio(const AudioId &audio, AudioData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0); AudioData *audio(const AudioId &audio, AudioData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
DocumentData *document(const DocumentId &document, DocumentData *convert = 0, const uint64 &access = 0, int32 date = 0, const QVector<MTPDocumentAttribute> &attributes = QVector<MTPDocumentAttribute>(), const QString &mime = QString(), const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0); DocumentData *document(const DocumentId &document);
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
WebPageData *webPage(const WebPageId &webPage, WebPageData *convert = 0, const QString &type = QString(), const QString &url = QString(), const QString &displayUrl = QString(), const QString &siteName = QString(), const QString &title = QString(), const QString &description = QString(), PhotoData *photo = 0, int32 duration = 0, const QString &author = QString(), int32 pendingTill = -2); WebPageData *webPage(const WebPageId &webPage, WebPageData *convert = 0, const QString &type = QString(), const QString &url = QString(), const QString &displayUrl = QString(), const QString &siteName = QString(), const QString &title = QString(), const QString &description = QString(), PhotoData *photo = 0, int32 duration = 0, const QString &author = QString(), int32 pendingTill = -2);
ImageLinkData *imageLink(const QString &imageLink, ImageLinkType type = InvalidImageLink, const QString &url = QString()); ImageLinkData *imageLink(const QString &imageLink, ImageLinkType type = InvalidImageLink, const QString &url = QString());
void forgetMedia(); void forgetMedia();
@ -200,6 +202,7 @@ namespace App {
void searchByHashtag(const QString &tag); void searchByHashtag(const QString &tag);
void openUserByName(const QString &username, bool toProfile = false); void openUserByName(const QString &username, bool toProfile = false);
void joinGroupByHash(const QString &hash); void joinGroupByHash(const QString &hash);
void stickersBox(const QString &name);
void openLocalUrl(const QString &url); void openLocalUrl(const QString &url);
void initBackground(int32 id = DefaultChatBackground, const QImage &p = QImage(), bool nowrite = false); void initBackground(int32 id = DefaultChatBackground, const QImage &p = QImage(), bool nowrite = false);

View File

@ -662,8 +662,8 @@ void Application::checkMapVersion() {
psRegisterCustomScheme(); psRegisterCustomScheme();
if (Local::oldMapVersion()) { if (Local::oldMapVersion()) {
QString versionFeatures; QString versionFeatures;
if (DevChannel && Local::oldMapVersion() < 8012) { if (DevChannel && Local::oldMapVersion() < 8014) {
versionFeatures = QString::fromUtf8("\xe2\x80\x94 New emojis support added\n\xe2\x80\x94 Emojis and stickers panel improved").replace('@', qsl("@") + QChar(0x200D)); versionFeatures = QString::fromUtf8("\xe2\x80\x94 Added support for sticker packs\n\xe2\x80\x94 New emoji and sticker panel").replace('@', qsl("@") + QChar(0x200D));
} else if (!DevChannel && Local::oldMapVersion() < 8013) { } else if (!DevChannel && Local::oldMapVersion() < 8013) {
versionFeatures = lang(lng_new_version_text).trimmed(); versionFeatures = lang(lng_new_version_text).trimmed();
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 215 KiB

View File

@ -0,0 +1,275 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "lang.h"
#include "stickersetbox.h"
#include "mainwidget.h"
#include "window.h"
#include "settingswidget.h"
#include "boxes/confirmbox.h"
#include "localstorage.h"
StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) :
_loaded(false), _setId(0), _setAccess(0), _bottom(0),
_input(set), _installRequest(0) {
switch (set.type()) {
case mtpc_inputStickerSetID: _setId = set.c_inputStickerSetID().vid.v; _setAccess = set.c_inputStickerSetID().vaccess_hash.v; break;
case mtpc_inputStickerSetShortName: _setShortName = qs(set.c_inputStickerSetShortName().vshort_name); break;
}
MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&StickerSetInner::gotSet), rpcFail(&StickerSetInner::failedSet));
cSetLastStickersUpdate(0);
App::main()->updateStickers();
}
void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) {
_pack.clear();
if (set.type() == mtpc_messages_stickerSet) {
const MTPDmessages_stickerSet &d(set.c_messages_stickerSet());
const QVector<MTPDocument> &v(d.vdocuments.c_vector().v);
_pack.reserve(v.size());
for (int32 i = 0, l = v.size(); i < l; ++i) {
DocumentData *doc = App::feedDocument(v.at(i));
if (!doc || !doc->sticker) continue;
_pack.push_back(doc);
}
if (d.vset.type() == mtpc_stickerSet) {
const MTPDstickerSet &s(d.vset.c_stickerSet());
_setTitle = qs(s.vtitle);
_title = st::boxTitleFont->m.elidedText(_setTitle, Qt::ElideRight, width() - st::btnStickersClose.width - st::boxTitlePos.x());
_setShortName = qs(s.vshort_name);
_setId = s.vid.v;
_setAccess = s.vaccess_hash.v;
}
}
if (_pack.isEmpty() || _setShortName.isEmpty()) {
App::wnd()->showLayer(new ConfirmBox(lang(lng_stickers_not_found), true), true);
} else {
int32 rows = _pack.size() / StickerPanPerRow + ((_pack.size() % StickerPanPerRow) ? 1 : 0);
resize(st::stickersPadding + StickerPanPerRow * st::stickersSize.width(), rows * st::stickersSize.height() + st::stickersAddOrShare);
}
_loaded = true;
emit updateButtons();
}
bool StickerSetInner::failedSet(const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
_loaded = true;
App::wnd()->showLayer(new ConfirmBox(lang(lng_stickers_not_found), true), true);
return true;
}
void StickerSetInner::installDone(const MTPBool &result) {
StickerSets &sets(cRefStickerSets());
sets.insert(_setId, StickerSet(_setId, _setAccess, _setTitle, _setShortName)).value().stickers = _pack;
cSetStickersHash(QByteArray());
Local::writeStickers();
emit installed(_setId);
App::wnd()->hideLayer();
}
bool StickerSetInner::installFailed(const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
App::wnd()->showLayer(new ConfirmBox(lang(lng_stickers_not_found), true), true);
return true;
}
void StickerSetInner::paintEvent(QPaintEvent *e) {
QRect r(e->rect());
Painter p(this);
if (_pack.isEmpty()) return;
int32 rows = _pack.size() / StickerPanPerRow + ((_pack.size() % StickerPanPerRow) ? 1 : 0);
int32 from = qFloor(e->rect().top() / st::stickersSize.height()), to = qFloor(e->rect().bottom() / st::stickersSize.height()) + 1;
for (int32 i = from; i < to; ++i) {
for (int32 j = 0; j < StickerPanPerRow; ++j) {
int32 index = i * StickerPanPerRow + j;
if (index >= _pack.size()) break;
DocumentData *doc = _pack.at(index);
QPoint pos(st::stickerPanPadding + j * st::stickersSize.width(), i * st::stickersSize.height());
bool goodThumb = !doc->thumb->isNull() && ((doc->thumb->width() >= 128) || (doc->thumb->height() >= 128));
if (goodThumb) {
doc->thumb->load();
} else {
bool already = !doc->already().isEmpty(), hasdata = !doc->data.isEmpty();
if (!doc->loader && doc->status != FileFailed && !already && !hasdata) {
doc->save(QString());
}
if (doc->sticker->img->isNull() && (already || hasdata)) {
if (already) {
doc->sticker->img = ImagePtr(doc->already());
} else {
doc->sticker->img = ImagePtr(doc->data);
}
}
}
float64 coef = qMin((st::stickersSize.width() - st::stickerPanRound * 2) / float64(doc->dimensions.width()), (st::stickersSize.height() - st::stickerPanRound * 2) / float64(doc->dimensions.height()));
if (coef > 1) coef = 1;
int32 w = qRound(coef * doc->dimensions.width()), h = qRound(coef * doc->dimensions.height());
if (w < 1) w = 1;
if (h < 1) h = 1;
QPoint ppos = pos + QPoint((st::stickersSize.width() - w) / 2, (st::stickersSize.height() - h) / 2);
if (goodThumb) {
p.drawPixmapLeft(ppos, width(), doc->thumb->pix(w, h));
} else if (!doc->sticker->img->isNull()) {
p.drawPixmapLeft(ppos, width(), doc->sticker->img->pix(w, h));
}
}
}
p.fillRect(0, _bottom - st::stickersAddOrShare, width(), st::stickersAddOrShare, st::emojiPanHeaderBg->b);
}
void StickerSetInner::setScrollBottom(int32 bottom) {
if (bottom == _bottom) return;
QRegion upd = QRect(0, _bottom - st::stickersAddOrShare, width(), st::stickersAddOrShare);
_bottom = bottom;
upd += QRect(0, _bottom - st::stickersAddOrShare, width(), st::stickersAddOrShare);
repaint(upd);
}
bool StickerSetInner::loaded() const {
return _loaded && !_pack.isEmpty();
}
int32 StickerSetInner::notInstalled() const {
return (_loaded && (cStickerSets().constFind(_setId) == cStickerSets().cend())) ? _pack.size() : 0;
}
QString StickerSetInner::title() const {
return _loaded ? (_pack.isEmpty() ? lang(lng_attach_failed) : _title) : lang(lng_contacts_loading);
}
QString StickerSetInner::shortName() const {
return _setShortName;
}
void StickerSetInner::install() {
if (_installRequest) return;
_installRequest = MTP::send(MTPmessages_InstallStickerSet(_input), rpcDone(&StickerSetInner::installDone), rpcFail(&StickerSetInner::installFailed));
}
StickerSetInner::~StickerSetInner() {
}
StickerSetBox::StickerSetBox(const MTPInputStickerSet &set) : ScrollableBox(st::stickersScroll), _inner(set),
_close(this, st::btnStickersClose),
_addStickers(this, lng_stickers_add_pack(lt_count, 0), st::btnStickersAdd),
_shareStickers(this, lang(lng_stickers_share_pack), st::btnStickersAdd) {
resize(st::stickersWidth, height());
setMaxHeight(st::stickersMaxHeight);
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
init(&_inner, 0, st::boxFont->height + st::newGroupNamePadding.top() + st::newGroupNamePadding.bottom());
connect(&_close, SIGNAL(clicked()), this, SLOT(onClose()));
connect(&_addStickers, SIGNAL(clicked()), this, SLOT(onAddStickers()));
connect(&_shareStickers, SIGNAL(clicked()), this, SLOT(onShareStickers()));
connect(&_inner, SIGNAL(updateButtons()), this, SLOT(onUpdateButtons()));
connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
connect(&_inner, SIGNAL(installed(uint64)), this, SIGNAL(installed(uint64)));
onStickersUpdated();
onScroll();
prepare();
}
void StickerSetBox::onStickersUpdated() {
showAll();
}
void StickerSetBox::onAddStickers() {
_inner.install();
}
void StickerSetBox::onShareStickers() {
QString url = qsl("https://telegram.me/addstickers/") + _inner.shortName();
DEBUG_LOG(("Setting text to clipboard from stickerset box: %1").arg(url));
QApplication::clipboard()->setText(url);
App::wnd()->showLayer(new ConfirmBox(lang(lng_stickers_copied), true), true);
}
void StickerSetBox::onUpdateButtons() {
if (!_close.isHidden()) showAll();
}
void StickerSetBox::onScroll() {
_inner.setScrollBottom(_scroll.scrollTop() + _scroll.height());
}
void StickerSetBox::hideAll() {
ScrollableBox::hideAll();
_close.hide();
_addStickers.hide();
_shareStickers.hide();
}
void StickerSetBox::showAll() {
ScrollableBox::showAll();
_close.show();
int32 cnt = _inner.notInstalled();
if (_inner.loaded()) {
if (_inner.notInstalled()) {
_addStickers.setText(lng_stickers_add_pack(lt_count, cnt));
_addStickers.show();
_addStickers.raise();
_shareStickers.hide();
} else {
_shareStickers.show();
_shareStickers.raise();
_addStickers.hide();
}
} else {
_addStickers.hide();
_shareStickers.hide();
}
update();
}
void StickerSetBox::paintEvent(QPaintEvent *e) {
Painter p(this);
if (paint(p)) return;
paintTitle(p, _inner.title(), false);
}
void StickerSetBox::resizeEvent(QResizeEvent *e) {
ScrollableBox::resizeEvent(e);
_inner.resize(width(), _inner.height());
_close.moveToRight(0, 0, width());
_addStickers.move((width() - _addStickers.width()) / 2, height() - (st::stickersAddOrShare + _addStickers.height()) / 2);
_shareStickers.move((width() - _shareStickers.width()) / 2, height() - (st::stickersAddOrShare + _shareStickers.height()) / 2);
}

View File

@ -0,0 +1,100 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "abstractbox.h"
class StickerSetInner : public QWidget, public RPCSender {
Q_OBJECT
public:
StickerSetInner(const MTPInputStickerSet &set);
void init();
void paintEvent(QPaintEvent *e);
bool loaded() const;
int32 notInstalled() const;
QString title() const;
QString shortName() const;
void setScrollBottom(int32 bottom);
void install();
~StickerSetInner();
signals:
void updateButtons();
void installed(uint64 id);
private:
void gotSet(const MTPmessages_StickerSet &set);
bool failedSet(const RPCError &error);
void installDone(const MTPBool &result);
bool installFailed(const RPCError &error);
StickerPack _pack;
bool _loaded;
uint64 _setId, _setAccess;
QString _title, _setTitle, _setShortName;
int32 _bottom;
MTPInputStickerSet _input;
mtpRequestId _installRequest;
};
class StickerSetBox : public ScrollableBox, public RPCSender {
Q_OBJECT
public:
StickerSetBox(const MTPInputStickerSet &set);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
public slots:
void onStickersUpdated();
void onAddStickers();
void onShareStickers();
void onUpdateButtons();
void onScroll();
signals:
void installed(uint64 id);
protected:
void hideAll();
void showAll();
private:
StickerSetInner _inner;
IconedButton _close;
FlatButton _addStickers, _shareStickers;
};

View File

@ -17,9 +17,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
static const int32 AppVersion = 8013; static const int32 AppVersion = 8014;
static const wchar_t *AppVersionStr = L"0.8.13"; static const wchar_t *AppVersionStr = L"0.8.14";
static const bool DevChannel = false; static const bool DevChannel = true;
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)"; static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
static const wchar_t *AppName = L"Telegram Desktop"; static const wchar_t *AppName = L"Telegram Desktop";
@ -101,9 +101,10 @@ enum {
ZoomToScreenLevel = 1024, // just constant ZoomToScreenLevel = 1024, // just constant
PreloadHeightsCount = 3, // when 3 screens to scroll left make a preload request PreloadHeightsCount = 3, // when 3 screens to scroll left make a preload request
EmojiPadPerRow = 7, EmojiPanPerRow = 7,
EmojiPadRowsPerPage = 6, EmojiPanRowsPerPage = 6,
StickerPadPerRow = 3, StickerPanPerRow = 5,
StickerPanRowsPerPage = 4,
StickersUpdateTimeout = 3600000, // update not more than once in an hour StickersUpdateTimeout = 3600000, // update not more than once in an hour
SearchPeopleLimit = 5, SearchPeopleLimit = 5,

View File

@ -1122,7 +1122,7 @@ void DialogsListWidget::saveRecentHashtags(const QString &text) {
} }
} }
if (!found && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) { if (!found && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) {
Local::readRecentStickers(); Local::readRecentHashtags();
recent = cRecentSearchHashtags(); recent = cRecentSearchHashtags();
} }
found = true; found = true;

File diff suppressed because it is too large Load Diff

View File

@ -193,6 +193,8 @@ private:
}; };
static const int32 SwitcherSelected = (INT_MAX / 2);
class EmojiPanInner : public TWidget, public Animated { class EmojiPanInner : public TWidget, public Animated {
Q_OBJECT Q_OBJECT
@ -218,7 +220,6 @@ public:
DBIEmojiTab currentTab(int yOffset) const; DBIEmojiTab currentTab(int yOffset) const;
void refreshStickers();
void refreshRecent(); void refreshRecent();
void setScrollTop(int top); void setScrollTop(int top);
@ -234,30 +235,27 @@ public slots:
signals: signals:
void emojiSelected(EmojiPtr emoji); void selected(EmojiPtr emoji);
void stickerSelected(DocumentData *sticker);
void switchToStickers();
void scrollToY(int y); void scrollToY(int y);
void disableScroll(bool dis); void disableScroll(bool dis);
private: private:
int countHeight(); int32 countHeight();
void selectEmoji(EmojiPtr emoji); void selectEmoji(EmojiPtr emoji);
typedef QMap<int32, uint64> EmojiAnimations; // index - showing, -index - hiding typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
EmojiAnimations _emojiAnimations; Animations _animations;
int _top; int32 _top, _counts[emojiTabCount];
int _counts[emojiTabCount], _count;
StickerPack _stickers;
QVector<bool> _isUserGen;
QVector<EmojiPtr> _emojis[emojiTabCount]; QVector<EmojiPtr> _emojis[emojiTabCount];
QVector<float64> _hovers[emojiTabCount + 1]; // + stickers hovers and stickers-x hovers QVector<float64> _hovers[emojiTabCount];
float64 _stickerWidth; int32 _esize;
int32 _esize, _stickerSize;
int32 _selected, _pressedSel, _pickerSel; int32 _selected, _pressedSel, _pickerSel;
QPoint _lastMousePos; QPoint _lastMousePos;
@ -267,6 +265,74 @@ private:
EmojiColorPicker _picker; EmojiColorPicker _picker;
QTimer _showPickerTimer; QTimer _showPickerTimer;
float64 _switcherHover;
int32 _stickersWidth;
};
class StickerPanInner : public TWidget, public Animated {
Q_OBJECT
public:
StickerPanInner(QWidget *parent = 0);
void paintEvent(QPaintEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void leaveEvent(QEvent *e);
void leaveToChildEvent(QEvent *e);
void enterFromChildEvent(QEvent *e);
bool animStep(float64 ms);
void showStickerSet(uint64 setId);
void clearSelection(bool fast = false);
void refreshStickers();
void refreshRecent(bool resize = true);
void setScrollTop(int top);
void preloadImages();
public slots:
void updateSelected();
signals:
void selected(DocumentData *sticker);
void removing(uint64 setId);
void switchToEmoji();
void scrollToY(int y);
void disableScroll(bool dis);
private:
void appendSet(StickerSets::const_iterator it);
int32 countHeight();
void selectEmoji(EmojiPtr emoji);
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
Animations _animations;
int32 _top;
QList<QString> _titles;
QList<uint64> _setIds;
QList<StickerPack> _sets;
QList<QVector<float64> > _hovers;
int32 _selected, _pressedSel;
QPoint _lastMousePos;
float64 _switcherHover;
int32 _emojiWidth;
}; };
class EmojiPan : public TWidget, public Animated { class EmojiPan : public TWidget, public Animated {
@ -291,11 +357,12 @@ public:
bool animStep(float64 ms); bool animStep(float64 ms);
bool eventFilter(QObject *obj, QEvent *e); bool eventFilter(QObject *obj, QEvent *e);
void stickersInstalled(uint64 setId);
void refreshStickers();
public slots: public slots:
void refreshStickers();
void hideStart(); void hideStart();
void hideFinish(); void hideFinish();
@ -304,6 +371,11 @@ public slots:
void onTabChange(); void onTabChange();
void onScroll(); void onScroll();
void onSwitch();
void onRemoveSet(uint64 setId);
void onRemoveSetSure();
void onDelayedHide();
signals: signals:
@ -313,6 +385,8 @@ signals:
private: private:
void prepareTab(int32 &left, int32 top, int32 _width, FlatRadiobutton &tab);
void showAll(); void showAll();
void hideAll(); void hideAll();
@ -328,11 +402,20 @@ private:
BoxShadow _shadow; BoxShadow _shadow;
FlatRadiobutton _recent, _people, _nature, _food, _celebration, _activity, _travel, _objects, _stickers; FlatRadiobutton _recent, _people, _nature, _food, _celebration, _activity, _travel, _objects;
int32 _emojiPack; bool _stickersShown;
ScrollArea _scroll; QPixmap _fromCache, _toCache;
EmojiPanInner _inner; anim::ivalue a_fromCoord, a_toCoord;
anim::fvalue a_fromAlpha, a_toAlpha;
uint64 _moveStart;
ScrollArea e_scroll;
EmojiPanInner e_inner;
ScrollArea s_scroll;
StickerPanInner s_inner;
uint64 _removingSetId;
}; };

View File

@ -38,7 +38,7 @@ void FileUploader::uploadMedia(MsgId msgId, const ReadyLocalMedia &media) {
} }
document->status = FileUploading; document->status = FileUploading;
if (!media.file.isEmpty()) { if (!media.file.isEmpty()) {
document->location = FileLocation(mtpc_storage_filePartial, media.file); document->location = FileLocation(StorageFilePartial, media.file);
} }
} }
queue.insert(msgId, File(media)); queue.insert(msgId, File(media));

View File

@ -19,6 +19,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include "gui/images.h" #include "gui/images.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "localstorage.h"
namespace { namespace {
typedef QMap<QString, LocalImage*> LocalImages; typedef QMap<QString, LocalImage*> LocalImages;
@ -43,7 +44,7 @@ ImagePtr::ImagePtr() : Parent(blank()) {
} }
ImagePtr::ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def) : ImagePtr::ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def) :
Parent((location.type() == mtpc_fileLocation) ? (Image*)(getImage(width, height, location.c_fileLocation().vdc_id.v, location.c_fileLocation().vvolume_id.v, location.c_fileLocation().vlocal_id.v, location.c_fileLocation().vsecret.v)) : def.v()) { Parent((location.type() == mtpc_fileLocation) ? (Image*)(getImage(StorageImageLocation(width, height, location.c_fileLocation()))) : def.v()) {
} }
const QPixmap &Image::pix(int32 w, int32 h) const { const QPixmap &Image::pix(int32 w, int32 h) const {
@ -517,11 +518,14 @@ int64 imageCacheSize() {
return globalAquiredSize; return globalAquiredSize;
} }
StorageImage::StorageImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size) : w(width), h(height), loader(new mtpFileLoader(dc, volume, local, secret, size)) { StorageImage::StorageImage(const StorageImageLocation &location, int32 size) : w(location.width), h(location.height), loader(new mtpFileLoader(location.dc, location.volume, location.local, location.secret, size)) {
} }
StorageImage::StorageImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, QByteArray &bytes) : w(width), h(height), loader(0) { StorageImage::StorageImage(const StorageImageLocation &location, QByteArray &bytes) : w(location.width), h(location.height), loader(0) {
setData(bytes); setData(bytes);
if (location.dc) {
Local::writeImage(storageKey(location.dc, location.volume, location.local), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
}
} }
const QPixmap &StorageImage::pixData() const { const QPixmap &StorageImage::pixData() const {
@ -608,24 +612,27 @@ bool StorageImage::loaded() const {
return check(); return check();
} }
StorageImage *getImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size) { StorageImage *getImage(const StorageImageLocation &location, int32 size) {
StorageKey key(storageKey(dc, volume, local)); StorageKey key(storageKey(location.dc, location.volume, location.local));
StorageImages::const_iterator i = storageImages.constFind(key); StorageImages::const_iterator i = storageImages.constFind(key);
if (i == storageImages.cend()) { if (i == storageImages.cend()) {
i = storageImages.insert(key, new StorageImage(width, height, dc, volume, local, secret, size)); i = storageImages.insert(key, new StorageImage(location, size));
} }
return i.value(); return i.value();
} }
StorageImage *getImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, const QByteArray &bytes) { StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes) {
StorageKey key(storageKey(dc, volume, local)); StorageKey key(storageKey(location.dc, location.volume, location.local));
StorageImages::const_iterator i = storageImages.constFind(key); StorageImages::const_iterator i = storageImages.constFind(key);
if (i == storageImages.cend()) { if (i == storageImages.cend()) {
QByteArray bytesArr(bytes); QByteArray bytesArr(bytes);
i = storageImages.insert(key, new StorageImage(width, height, dc, volume, local, secret, bytesArr)); i = storageImages.insert(key, new StorageImage(location, bytesArr));
} else if (!i.value()->loaded()) { } else if (!i.value()->loaded()) {
QByteArray bytesArr(bytes); QByteArray bytesArr(bytes);
i.value()->setData(bytesArr); i.value()->setData(bytesArr);
if (location.dc) {
Local::writeImage(storageKey(location.dc, location.volume, location.local), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
}
} }
return i.value(); return i.value();
} }

View File

@ -21,6 +21,20 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
QImage imageBlur(QImage img); QImage imageBlur(QImage img);
struct StorageImageLocation {
StorageImageLocation() : width(0), height(0), dc(0), volume(0), local(0), secret(0) {
}
StorageImageLocation(int32 width, int32 height, int32 dc, const uint64 &volume, int32 local, const uint64 &secret) : width(width), height(height), dc(dc), volume(volume), local(local), secret(secret) {
}
StorageImageLocation(int32 width, int32 height, const MTPDfileLocation &location) : width(width), height(height), dc(location.vdc_id.v), volume(location.vvolume_id.v), local(location.vlocal_id.v), secret(location.vsecret.v) {
}
int32 width, height;
int32 dc;
uint64 volume;
int32 local;
uint64 secret;
};
class Image { class Image {
public: public:
@ -123,25 +137,66 @@ typedef QPair<uint64, uint64> StorageKey;
inline uint64 storageMix32To64(int32 a, int32 b) { inline uint64 storageMix32To64(int32 a, int32 b) {
return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b)); return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b));
} }
inline StorageKey storageKey(int32 dc, const int64 &volume, int32 local) { inline StorageKey storageKey(int32 dc, const uint64 &volume, int32 local) {
return StorageKey(storageMix32To64(dc, local), volume); return StorageKey(storageMix32To64(dc, local), volume);
} }
inline StorageKey storageKey(const MTPDfileLocation &location) { inline StorageKey storageKey(const MTPDfileLocation &location) {
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v); return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
} }
enum StorageFileType {
StorageFileUnknown = 0xaa963b05, // mtpc_storage_fileUnknown
StorageFileJpeg = 0x7efe0e, // mtpc_storage_fileJpeg
StorageFileGif = 0xcae1aadf, // mtpc_storage_fileGif
StorageFilePng = 0xa4f63c0, // mtpc_storage_filePng
StorageFilePdf = 0xae1e508d, // mtpc_storage_filePdf
StorageFileMp3 = 0x528a0677, // mtpc_storage_fileMp3
StorageFileMov = 0x4b09ebbc, // mtpc_storage_fileMov
StorageFilePartial = 0x40bc6f52, // mtpc_storage_filePartial
StorageFileMp4 = 0xb3cea0e4, // mtpc_storage_fileMp4
StorageFileWebp = 0x1081464c, // mtpc_storage_fileWebp
};
inline StorageFileType mtpToStorageType(mtpTypeId type) {
switch (type) {
case mtpc_storage_fileJpeg: return StorageFileJpeg;
case mtpc_storage_fileGif: return StorageFileGif;
case mtpc_storage_filePng: return StorageFilePng;
case mtpc_storage_filePdf: return StorageFilePdf;
case mtpc_storage_fileMp3: return StorageFileMp3;
case mtpc_storage_fileMov: return StorageFileMov;
case mtpc_storage_filePartial: return StorageFilePartial;
case mtpc_storage_fileMp4: return StorageFileMp4;
case mtpc_storage_fileWebp: return StorageFileWebp;
case mtpc_storage_fileUnknown:
default: return StorageFileUnknown;
}
}
inline mtpTypeId mtpFromStorageType(StorageFileType type) {
switch (type) {
case StorageFileGif: return mtpc_storage_fileGif;
case StorageFilePng: return mtpc_storage_filePng;
case StorageFilePdf: return mtpc_storage_filePdf;
case StorageFileMp3: return mtpc_storage_fileMp3;
case StorageFileMov: return mtpc_storage_fileMov;
case StorageFilePartial: return mtpc_storage_filePartial;
case StorageFileMp4: return mtpc_storage_fileMp4;
case StorageFileWebp: return mtpc_storage_fileWebp;
case StorageFileUnknown:
default: return mtpc_storage_fileUnknown;
}
}
struct StorageImageSaved { struct StorageImageSaved {
StorageImageSaved() : type(mtpc_storage_fileUnknown) { StorageImageSaved() : type(StorageFileUnknown) {
} }
StorageImageSaved(mtpTypeId type, const QByteArray &data) : type(type), data(data) { StorageImageSaved(StorageFileType type, const QByteArray &data) : type(type), data(data) {
} }
mtpTypeId type; StorageFileType type;
QByteArray data; QByteArray data;
}; };
class StorageImage : public Image { class StorageImage : public Image {
public: public:
StorageImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size = 0); StorageImage(const StorageImageLocation &location, int32 size = 0);
StorageImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, QByteArray &bytes); StorageImage(const StorageImageLocation &location, QByteArray &bytes);
int32 width() const; int32 width() const;
int32 height() const; int32 height() const;
@ -188,8 +243,8 @@ private:
mutable mtpFileLoader *loader; mutable mtpFileLoader *loader;
}; };
StorageImage *getImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size = 0); StorageImage *getImage(const StorageImageLocation &location, int32 size = 0);
StorageImage *getImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, const QByteArray &bytes); StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes);
Image *getImage(int32 width, int32 height, const MTPFileLocation &location); Image *getImage(int32 width, int32 height, const MTPFileLocation &location);
class ImagePtr : public ManagedPtr<Image> { class ImagePtr : public ManagedPtr<Image> {
@ -201,9 +256,9 @@ public:
} }
ImagePtr(const QPixmap &pixmap, QByteArray format) : Parent(getImage(pixmap, format)) { ImagePtr(const QPixmap &pixmap, QByteArray format) : Parent(getImage(pixmap, format)) {
} }
ImagePtr(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size = 0) : Parent(getImage(width, height, dc, volume, local, secret, size)) { ImagePtr(const StorageImageLocation &location, int32 size = 0) : Parent(getImage(location, size)) {
} }
ImagePtr(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, const QByteArray &bytes) : Parent(getImage(width, height, dc, volume, local, secret, bytes)) { ImagePtr(const StorageImageLocation &location, const QByteArray &bytes) : Parent(getImage(location, bytes)) {
} }
ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def = ImagePtr()); ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def = ImagePtr());
}; };
@ -213,16 +268,16 @@ void clearAllImages();
int64 imageCacheSize(); int64 imageCacheSize();
struct FileLocation { struct FileLocation {
FileLocation(mtpTypeId type, const QString &name, const QDateTime &modified, qint32 size) : type(type), name(name), modified(modified), size(size) { FileLocation(StorageFileType 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) { FileLocation(StorageFileType type, const QString &name) : type(type), name(name) {
QFileInfo f(name); QFileInfo f(name);
if (f.exists()) { if (f.exists()) {
qint64 s = f.size(); qint64 s = f.size();
if (s > INT_MAX) { if (s > INT_MAX) {
this->name = QString(); this->name = QString();
size = 0; size = 0;
type = mtpc_storage_fileUnknown; type = StorageFileUnknown;
} else { } else {
modified = f.lastModified(); modified = f.lastModified();
size = qint32(s); size = qint32(s);
@ -230,7 +285,7 @@ struct FileLocation {
} else { } else {
this->name = QString(); this->name = QString();
size = 0; size = 0;
type = mtpc_storage_fileUnknown; type = StorageFileUnknown;
} }
} }
FileLocation() : size(0) { FileLocation() : size(0) {
@ -245,7 +300,7 @@ struct FileLocation {
return (f.lastModified() == modified) && (qint32(s) == size); return (f.lastModified() == modified) && (qint32(s) == size);
} }
mtpTypeId type; StorageFileType type;
QString name; QString name;
QDateTime modified; QDateTime modified;
qint32 size; qint32 size;
@ -257,11 +312,34 @@ inline bool operator!=(const FileLocation &a, const FileLocation &b) {
return !(a == b); return !(a == b);
} }
enum LocationType {
UnknownFileLocation = 0,
DocumentFileLocation = 0x4e45abe9, // mtpc_inputDocumentFileLocation
AudioFileLocation = 0x74dc404d, // mtpc_inputAudioFileLocation
VideoFileLocation = 0x3d0364ec, // mtpc_inputVideoFileLocation
};
inline LocationType mtpToLocationType(mtpTypeId type) {
switch (type) {
case mtpc_inputDocumentFileLocation: return DocumentFileLocation;
case mtpc_inputAudioFileLocation: return AudioFileLocation;
case mtpc_inputVideoFileLocation: return VideoFileLocation;
default: return UnknownFileLocation;
}
}
inline mtpTypeId mtpFromLocationType(LocationType type) {
switch (type) {
case DocumentFileLocation: return mtpc_inputDocumentFileLocation;
case AudioFileLocation: return mtpc_inputAudioFileLocation;
case VideoFileLocation: return mtpc_inputVideoFileLocation;
case UnknownFileLocation:
default: return 0;
}
}
typedef QPair<uint64, uint64> MediaKey; typedef QPair<uint64, uint64> MediaKey;
inline uint64 mediaMix32To64(mtpTypeId a, int32 b) { inline uint64 mediaMix32To64(int32 a, int32 b) {
return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b)); return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b));
} }
inline MediaKey mediaKey(mtpTypeId type, int32 dc, const int64 &id) { inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id) {
return MediaKey(mediaMix32To64(type, dc), id); return MediaKey(mediaMix32To64(type, dc), id);
} }
inline StorageKey mediaKey(const MTPDfileLocation &location) { inline StorageKey mediaKey(const MTPDfileLocation &location) {

View File

@ -54,7 +54,7 @@ ScrollBar::ScrollBar(ScrollArea *parent, bool vert, const style::flatScroll *st)
} }
void ScrollBar::recountSize() { void ScrollBar::recountSize() {
setGeometry(_vertical ? QRect(rtl() ? 0 : (_area->width() - _st->width), 0, _st->width, _area->height()) : QRect(0, _area->height() - _st->width, _area->width(), _st->width)); setGeometry(_vertical ? QRect(rtl() ? 0 : (_area->width() - _st->width), _st->deltat, _st->width, _area->height() - _st->deltat - _st->deltab) : QRect(_st->deltat, _area->height() - _st->width, _area->width() - _st->deltat - _st->deltab, _st->width));
} }
void ScrollBar::updateBar(bool force) { void ScrollBar::updateBar(bool force) {
@ -65,7 +65,7 @@ void ScrollBar::updateBar(bool force) {
_area->rangeChanged(oldMax, newMax, _vertical); _area->rangeChanged(oldMax, newMax, _vertical);
} }
if (_vertical) { if (_vertical) {
int sh = _area->scrollHeight(), rh = height() - 2 * _st->deltay, h = sh ? int32((rh * int64(_area->height())) / sh) : 0; int sh = _area->scrollHeight(), rh = height(), h = sh ? int32((rh * int64(_area->height())) / sh) : 0;
if (h >= rh || !_area->scrollTopMax() || rh < _st->minHeight) { if (h >= rh || !_area->scrollTopMax() || rh < _st->minHeight) {
if (!isHidden()) hide(); if (!isHidden()) hide();
bool newTopSh = (_st->topsh < 0), newBottomSh = (_st->bottomsh < 0); bool newTopSh = (_st->topsh < 0), newBottomSh = (_st->bottomsh < 0);
@ -78,9 +78,9 @@ void ScrollBar::updateBar(bool force) {
int stm = _area->scrollTopMax(), y = stm ? int32(((rh - h) * int64(_area->scrollTop())) / stm) : 0; int stm = _area->scrollTopMax(), y = stm ? int32(((rh - h) * int64(_area->scrollTop())) / stm) : 0;
if (y > rh - h) y = rh - h; if (y > rh - h) y = rh - h;
newBar = QRect(_st->deltax, y + _st->deltay, width() - 2 * _st->deltax, h); newBar = QRect(_st->deltax, y, width() - 2 * _st->deltax, h);
} else { } else {
int sw = _area->scrollWidth(), rw = width() - 2 * _st->deltay, w = sw ? int32((rw * int64(_area->width())) / sw) : 0; int sw = _area->scrollWidth(), rw = width(), w = sw ? int32((rw * int64(_area->width())) / sw) : 0;
if (w >= rw || !_area->scrollLeftMax() || rw < _st->minHeight) { if (w >= rw || !_area->scrollLeftMax() || rw < _st->minHeight) {
if (!isHidden()) hide(); if (!isHidden()) hide();
return; return;
@ -90,11 +90,11 @@ void ScrollBar::updateBar(bool force) {
int slm = _area->scrollLeftMax(), x = slm ? int32(((rw - w) * int64(_area->scrollLeft())) / slm) : 0; int slm = _area->scrollLeftMax(), x = slm ? int32(((rw - w) * int64(_area->scrollLeft())) / slm) : 0;
if (x > rw - w) x = rw - w; if (x > rw - w) x = rw - w;
newBar = QRect(x + _st->deltay, _st->deltax, w, height() - 2 * _st->deltax); newBar = QRect(x, _st->deltax, w, height() - 2 * _st->deltax);
} }
if (newBar != _bar) { if (newBar != _bar) {
_bar = newBar; _bar = newBar;
parentWidget()->update(geometry()); update();// parentWidget()->update(geometry());
} }
if (_vertical) { if (_vertical) {
bool newTopSh = (_st->topsh < 0) || (_area->scrollTop() > _st->topsh), newBottomSh = (_st->bottomsh < 0) || (_area->scrollTop() < _area->scrollTopMax() - _st->bottomsh); bool newTopSh = (_st->topsh < 0) || (_area->scrollTop() > _st->topsh), newBottomSh = (_st->bottomsh < 0) || (_area->scrollTop() < _area->scrollTopMax() - _st->bottomsh);
@ -119,15 +119,16 @@ void ScrollBar::paintEvent(QPaintEvent *e) {
if (!a_bg.current().alpha() && !a_bar.current().alpha()) return; if (!a_bg.current().alpha() && !a_bar.current().alpha()) return;
QPainter p(this); QPainter p(this);
int32 deltax = _vertical ? _st->deltax : _st->deltay, deltay = _vertical ? _st->deltay : _st->deltax; int32 deltal = _vertical ? _st->deltax : 0, deltar = _vertical ? _st->deltax : 0;
int32 deltat = _vertical ? 0 : _st->deltax, deltab = _vertical ? 0 : _st->deltax;
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
if (_st->round) { if (_st->round) {
p.setBrush(a_bg.current()); p.setBrush(a_bg.current());
p.drawRoundedRect(QRect(deltax, deltay, width() - 2 * deltax, height() - 2 * deltay), _st->round, _st->round); p.drawRoundedRect(QRect(deltal, deltat, width() - deltal - deltar, height() - deltat - deltab), _st->round, _st->round);
p.setBrush(a_bar.current()); p.setBrush(a_bar.current());
p.drawRoundedRect(_bar, _st->round, _st->round); p.drawRoundedRect(_bar, _st->round, _st->round);
} else { } else {
p.fillRect(QRect(deltax, deltay, width() - 2 * deltax, height() - 2 * deltay), a_bg.current()); p.fillRect(QRect(deltal, deltat, width() - deltal - deltar, height() - deltat - deltab), a_bg.current());
p.fillRect(_bar, a_bar.current()); p.fillRect(_bar, a_bar.current());
} }
} }
@ -143,7 +144,7 @@ bool ScrollBar::animStep(float64 ms) {
a_bg.update(dt, anim::linear); a_bg.update(dt, anim::linear);
a_bar.update(dt, anim::linear); a_bar.update(dt, anim::linear);
} }
parentWidget()->update(geometry()); update();// parentWidget()->update(geometry());
return res; return res;
} }
@ -176,6 +177,8 @@ void ScrollBar::leaveEvent(QEvent *e) {
anim::start(this); anim::start(this);
if (_hideIn >= 0) { if (_hideIn >= 0) {
_hideTimer.start(_hideIn); _hideTimer.start(_hideIn);
} else if (_st->hiding) {
hideTimeout(_st->hiding);
} }
} }
_over = _overbar = false; _over = _overbar = false;
@ -193,7 +196,7 @@ void ScrollBar::mouseMoveEvent(QMouseEvent *e) {
} }
if (_moving) { if (_moving) {
int delta = 0, barDelta = _vertical ? (_area->height() - _bar.height()) : (_area->width() - _bar.width()); int delta = 0, barDelta = _vertical ? (_area->height() - _bar.height()) : (_area->width() - _bar.width());
if (barDelta) { if (barDelta > 0) {
QPoint d = (e->globalPos() - _dragStart); QPoint d = (e->globalPos() - _dragStart);
delta = int32((_vertical ? (d.y() * int64(_area->scrollTopMax())) : (d.x() * int64(_area->scrollLeftMax()))) / barDelta); delta = int32((_vertical ? (d.y() * int64(_area->scrollTopMax())) : (d.x() * int64(_area->scrollLeftMax()))) / barDelta);
} }
@ -209,7 +212,10 @@ void ScrollBar::mousePressEvent(QMouseEvent *e) {
if (_overbar) { if (_overbar) {
_startFrom = _connected->value(); _startFrom = _connected->value();
} else { } else {
_startFrom = _vertical ? int32((e->pos().y() * int64(_area->scrollTopMax())) / height()) : ((e->pos().x() * int64(_area->scrollLeftMax())) / width()); int32 val = _vertical ? e->pos().y() : e->pos().x(), div = _vertical ? height() : width();
val = (val <= _st->deltat) ? 0 : (val - _st->deltat);
div = (div <= _st->deltat + _st->deltab) ? 1 : (div - _st->deltat - _st->deltab);
_startFrom = _vertical ? int32((val * int64(_area->scrollTopMax())) / div) : ((val * int64(_area->scrollLeftMax())) / div);
_connected->setValue(_startFrom); _connected->setValue(_startFrom);
if (!_overbar) { if (!_overbar) {
_overbar = true; _overbar = true;

View File

@ -736,10 +736,13 @@ void TextLink::onClick(Qt::MouseButton button) const {
QString url = TextLink::encoded(); QString url = TextLink::encoded();
QRegularExpressionMatch telegramMeUser = QRegularExpression(qsl("^https?://telegram\\.me/([a-zA-Z0-9\\.\\_]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url); QRegularExpressionMatch telegramMeUser = QRegularExpression(qsl("^https?://telegram\\.me/([a-zA-Z0-9\\.\\_]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url);
QRegularExpressionMatch telegramMeGroup = QRegularExpression(qsl("^https?://telegram\\.me/joinchat/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url); QRegularExpressionMatch telegramMeGroup = QRegularExpression(qsl("^https?://telegram\\.me/joinchat/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url);
QRegularExpressionMatch telegramMeStickers = QRegularExpression(qsl("^https?://telegram\\.me/addstickers/([a-zA-Z0-9\\.\\_]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url);
if (telegramMeUser.hasMatch()) { if (telegramMeUser.hasMatch()) {
App::openUserByName(telegramMeUser.captured(1)); App::openUserByName(telegramMeUser.captured(1));
} else if (telegramMeGroup.hasMatch()) { } else if (telegramMeGroup.hasMatch()) {
App::joinGroupByHash(telegramMeGroup.captured(1)); App::joinGroupByHash(telegramMeGroup.captured(1));
} else if (telegramMeStickers.hasMatch()) {
App::stickersBox(telegramMeStickers.captured(1));
} else if (QRegularExpression(qsl("^tg://[a-zA-Z0-9]+"), QRegularExpression::CaseInsensitiveOption).match(url).hasMatch()) { } else if (QRegularExpression(qsl("^tg://[a-zA-Z0-9]+"), QRegularExpression::CaseInsensitiveOption).match(url).hasMatch()) {
App::openLocalUrl(url); App::openLocalUrl(url);
} else { } else {

View File

@ -701,6 +701,13 @@ void HistoryList::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu->addAction(lang(lng_context_reply_msg), historyWidget, SLOT(onReplyToMessage())); _menu->addAction(lang(lng_context_reply_msg), historyWidget, SLOT(onReplyToMessage()));
} }
if (item && !isUponSelected && !_contextMenuLnk) { if (item && !isUponSelected && !_contextMenuLnk) {
if (HistorySticker *sticker = dynamic_cast<HistorySticker*>(msg->getMedia())) {
DocumentData *doc = sticker->document();
if (doc && doc->sticker && doc->sticker->set.type() != mtpc_inputStickerSetEmpty) {
if (!_menu) _menu = new ContextMenu(this);
_menu->addAction(lang(lng_context_pack_info), historyWidget, SLOT(onStickerPackInfo()));
}
}
QString contextMenuText = item->selectedText(FullItemSel); QString contextMenuText = item->selectedText(FullItemSel);
if (!contextMenuText.isEmpty() && (!msg || !msg->getMedia() || msg->getMedia()->type() != MediaTypeSticker)) { if (!contextMenuText.isEmpty() && (!msg || !msg->getMedia() || msg->getMedia()->type() != MediaTypeSticker)) {
if (!_menu) _menu = new ContextMenu(this); if (!_menu) _menu = new ContextMenu(this);
@ -771,7 +778,9 @@ void HistoryList::onMenuDestroy(QObject *obj) {
} }
void HistoryList::copySelectedText() { void HistoryList::copySelectedText() {
QApplication::clipboard()->setText(getSelectedText()); QString sel = getSelectedText();
DEBUG_LOG(("Setting selected text to clipboard: %1").arg(sel));
QApplication::clipboard()->setText(sel);
} }
void HistoryList::openContextUrl() { void HistoryList::openContextUrl() {
@ -784,6 +793,7 @@ void HistoryList::openContextUrl() {
void HistoryList::copyContextUrl() { void HistoryList::copyContextUrl() {
QString enc = _contextMenuLnk->encoded(); QString enc = _contextMenuLnk->encoded();
if (!enc.isEmpty()) { if (!enc.isEmpty()) {
DEBUG_LOG(("Setting text to clipboard from context url: %1").arg(enc));
QApplication::clipboard()->setText(enc); QApplication::clipboard()->setText(enc);
} }
} }
@ -857,6 +867,7 @@ void HistoryList::copyContextText() {
QString contextMenuText = item->selectedText(FullItemSel); QString contextMenuText = item->selectedText(FullItemSel);
if (!contextMenuText.isEmpty()) { if (!contextMenuText.isEmpty()) {
DEBUG_LOG(("Setting text to clipboard from context menu: %1").arg(contextMenuText));
QApplication::clipboard()->setText(contextMenuText); QApplication::clipboard()->setText(contextMenuText);
} }
} }
@ -1569,7 +1580,6 @@ HistoryWidget::HistoryWidget(QWidget *parent) : QWidget(parent)
, _previewCancelled(false) , _previewCancelled(false)
, _replyForwardPressed(false) , _replyForwardPressed(false)
, _replyReturn(0) , _replyReturn(0)
, _lastStickersUpdate(0)
, _stickersUpdateRequest(0) , _stickersUpdateRequest(0)
, _loadingMessages(false) , _loadingMessages(false)
, histRequestsCount(0) , histRequestsCount(0)
@ -1687,6 +1697,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : QWidget(parent)
} }
void HistoryWidget::start() { void HistoryWidget::start() {
connect(App::main(), SIGNAL(stickersUpdated()), &_emojiPan, SLOT(refreshStickers()));
updateRecentStickers(); updateRecentStickers();
connect(App::api(), SIGNAL(fullPeerLoaded(PeerData*)), this, SLOT(onPeerLoaded(PeerData*))); connect(App::api(), SIGNAL(fullPeerLoaded(PeerData*)), this, SLOT(onPeerLoaded(PeerData*)));
} }
@ -1766,6 +1777,10 @@ void HistoryWidget::updateRecentStickers() {
_emojiPan.refreshStickers(); _emojiPan.refreshStickers();
} }
void HistoryWidget::stickersInstalled(uint64 setId) {
_emojiPan.stickersInstalled(setId);
}
void HistoryWidget::typingDone(const MTPBool &result, mtpRequestId req) { void HistoryWidget::typingDone(const MTPBool &result, mtpRequestId req) {
if (_typingRequest == req) { if (_typingRequest == req) {
_typingRequest = 0; _typingRequest = 0;
@ -1795,116 +1810,210 @@ void HistoryWidget::activate() {
} }
void HistoryWidget::updateStickers() { void HistoryWidget::updateStickers() {
if (_lastStickersUpdate && getms(true) < _lastStickersUpdate + StickersUpdateTimeout) return; if (cLastStickersUpdate() && getms(true) < cLastStickersUpdate() + StickersUpdateTimeout) return;
if (_stickersUpdateRequest) return; if (_stickersUpdateRequest) return;
_stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_string(cStickersHash())), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed)); _stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_string(cStickersHash())), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed));
} }
void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) { void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
_lastStickersUpdate = getms(true); cSetLastStickersUpdate(getms(true));
_stickersUpdateRequest = 0; _stickersUpdateRequest = 0;
if (stickers.type() == mtpc_messages_allStickers) { if (stickers.type() != mtpc_messages_allStickers) return;
const MTPDmessages_allStickers &d(stickers.c_messages_allStickers()); const MTPDmessages_allStickers &d(stickers.c_messages_allStickers());
EmojiStickersMap map;
AllStickers all; const QVector<MTPDocument> &d_docs(d.vdocuments.c_vector().v);
EmojiStickersMap map; const QVector<MTPStickerSet> &d_sets(d.vsets.c_vector().v);
const QVector<MTPDocument> &docs(d.vdocuments.c_vector().v); QByteArray wasHash = cStickersHash();
cSetStickersHash(qba(d.vhash));
QSet<DocumentData*> found; StickerSets &sets(cRefStickerSets());
const RecentStickerPack &recent(cRecentStickers()); StickerSets::iterator def = sets.find(DefaultStickerSetId);
RecentStickerPack add; if (def == sets.cend()) {
add.reserve(docs.size()); def = sets.insert(DefaultStickerSetId, StickerSet(DefaultStickerSetId, 0, qsl("Great Minds"), QString()));
ushort addValue = recent.isEmpty() ? 1 : qAbs(recent.front().second); }
for (int32 i = 0, l = docs.size(); i < l; ++i) { for (int32 i = 0; i < d_sets.size(); ++i) {
DocumentData *doc = App::feedDocument(docs.at(i)); if (d_sets.at(i).type() == mtpc_stickerSet) {
if (!doc) continue; const MTPDstickerSet &set(d_sets.at(i).c_stickerSet());
int32 j = 0, s = recent.size(); StickerSets::iterator i = sets.find(set.vid.v);
for (; j < s; ++j) { if (i == sets.cend()) {
if (doc == recent.at(j).first) { i = sets.insert(set.vid.v, StickerSet(set.vid.v, set.vaccess_hash.v, qs(set.vtitle), qs(set.vshort_name)));
} else {
i->access = set.vaccess_hash.v;
i->title = qs(set.vtitle);
i->shortName = qs(set.vshort_name);
}
}
}
StickerSets::iterator custom = sets.find(CustomStickerSetId);
bool added = false, removed = false;
QSet<DocumentData*> found;
QMap<uint64, int32> wasCount;
for (int32 i = 0, l = d_docs.size(); i < l; ++i) {
DocumentData *doc = App::feedDocument(d_docs.at(i));
if (!doc || !doc->sticker) continue;
switch (doc->sticker->set.type()) {
case mtpc_inputStickerSetEmpty: { // default set - great minds
if (!wasCount.contains(DefaultStickerSetId)) wasCount.insert(DefaultStickerSetId, def->stickers.size());
if (def->stickers.indexOf(doc) < 0) {
def->stickers.push_back(doc);
added = true;
} else {
found.insert(doc);
}
} break;
case mtpc_inputStickerSetID: {
StickerSets::iterator it = sets.find(doc->sticker->set.c_inputStickerSetID().vid.v);
if (it == sets.cend()) {
LOG(("Sticker Set not found by ID: %1").arg(doc->sticker->set.c_inputStickerSetID().vid.v));
} else {
if (!wasCount.contains(it->id)) wasCount.insert(it->id, it->stickers.size());
if (it->stickers.indexOf(doc) < 0) {
it->stickers.push_back(doc);
added = true;
} else {
found.insert(doc); found.insert(doc);
}
}
} break;
case mtpc_inputStickerSetShortName: {
QString name = qs(doc->sticker->set.c_inputStickerSetShortName().vshort_name).toLower().trimmed();
StickerSets::iterator it = sets.begin();
for (; it != sets.cend(); ++it) {
if (it->shortName.toLower().trimmed() == name) {
break; break;
} }
} }
if (j < s) continue; if (it == sets.cend()) {
add.push_back(qMakePair(doc, addValue)); LOG(("Sticker Set not found by name: %1").arg(name));
} else {
if (!wasCount.contains(it->id)) wasCount.insert(it->id, it->stickers.size());
if (it->stickers.indexOf(doc) < 0) {
it->stickers.push_back(doc);
added = true;
} else {
found.insert(doc);
}
}
} break;
} }
bool needRemove = false; if (custom != sets.cend()) {
for (int32 i = 0, l = recent.size(); i < l; ++i) { int32 index = custom->stickers.indexOf(doc);
if (recent.at(i).second > 0 && !found.contains(recent.at(i).first)) { if (index >= 0) {
needRemove = true; custom->stickers.removeAt(index);
break; removed = true;
} }
} }
if (!add.isEmpty() || needRemove) { }
if (needRemove) { if (custom != sets.cend() && custom->stickers.isEmpty()) {
for (int32 i = 0, l = recent.size(); i < l; ++i) { sets.erase(custom);
if (recent.at(i).second <= 0 || found.contains(recent.at(i).first)) { custom = sets.end();
add.push_back(recent.at(i)); }
bool writeRecent = false;
RecentStickerPack &recent(cGetRecentStickers());
for (StickerSets::iterator it = sets.begin(); it != sets.cend();) {
if (it->id == CustomStickerSetId || it->id == RecentStickerSetId) {
++it;
continue;
}
QMap<uint64, int32>::const_iterator was = wasCount.constFind(it->id);
if (was == wasCount.cend()) { // no such stickers added
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0) {
i = recent.erase(i);
writeRecent = true;
} else {
++i;
}
}
it = sets.erase(it);
removed = true;
} else {
for (int32 j = 0, l = was.value(); j < l;) {
if (found.contains(it->stickers.at(j))) {
++j;
} else {
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
if (it->stickers.at(j) == i->first) {
i = recent.erase(i);
writeRecent = true;
} else {
++i;
}
}
it->stickers.removeAt(j);
--l;
removed = true;
}
}
if (it->stickers.isEmpty()) {
it = sets.erase(it);
} else {
++it;
}
}
}
if (added || removed || cStickersHash() != wasHash) {
Local::writeStickers();
}
if (writeRecent) {
Local::writeUserSettings();
}
const QVector<MTPStickerPack> &packs(d.vpacks.c_vector().v);
for (int32 i = 0, l = packs.size(); i < l; ++i) {
if (packs.at(i).type() == mtpc_stickerPack) {
const MTPDstickerPack &p(packs.at(i).c_stickerPack());
QString emoticon(qs(p.vemoticon));
EmojiPtr e = 0;
for (const QChar *ch = emoticon.constData(), *end = emoticon.constEnd(); ch != end; ++ch) {
int len = 0;
e = emojiFromText(ch, end, len);
if (e) break;
if (ch + 1 < end && ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) ++ch;
}
if (e) {
const QVector<MTPlong> docs(p.vdocuments.c_vector().v);
if (!docs.isEmpty()) {
for (int32 j = 0, s = docs.size(); j < s; ++j) {
DocumentData *doc = App::document(docs.at(j).v);
map.insert(doc, e);
} }
} }
} else { } else {
add += recent; LOG(("Sticker Error: Could not find emoji for string: %1").arg(emoticon));
}
cSetRecentStickers(add);
Local::writeRecentStickers();
}
const QVector<MTPStickerPack> &packs(d.vpacks.c_vector().v);
for (int32 i = 0, l = packs.size(); i < l; ++i) {
if (packs.at(i).type() == mtpc_stickerPack) {
const MTPDstickerPack &p(packs.at(i).c_stickerPack());
QString emoticon(qs(p.vemoticon));
EmojiPtr e = 0;
for (const QChar *ch = emoticon.constData(), *end = emoticon.constEnd(); ch != end; ++ch) {
int len = 0;
e = emojiFromText(ch, end, len);
if (e) break;
if (ch + 1 < end && ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) ++ch;
}
if (e) {
const QVector<MTPlong> docs(p.vdocuments.c_vector().v);
if (!docs.isEmpty()) {
StickerPack &pack(all[e]);
pack.reserve(pack.size() + docs.size());
for (int32 j = 0, s = docs.size(); j < s; ++j) {
DocumentData *doc = App::document(docs.at(j).v);
pack.push_back(doc);
map.insert(doc, e);
}
}
} else {
LOG(("Sticker Error: Could not find emoji for string: %1").arg(emoticon));
}
} }
} }
cSetStickers(all);
cSetStickersHash(qba(d.vhash));
cSetEmojiStickers(map);
const DocumentItems &items(App::documentItems());
for (EmojiStickersMap::const_iterator i = map.cbegin(), e = map.cend(); i != e; ++i) {
DocumentItems::const_iterator j = items.constFind(i.key());
if (j != items.cend()) {
for (HistoryItemsMap::const_iterator k = j->cbegin(), end = j->cend(); k != end; ++k) {
k.key()->updateStickerEmoji();
}
}
}
// updateStickerPan();
_emojiPan.refreshStickers();
} }
cSetEmojiStickers(map);
const DocumentItems &items(App::documentItems());
for (EmojiStickersMap::const_iterator i = map.cbegin(), e = map.cend(); i != e; ++i) {
DocumentItems::const_iterator j = items.constFind(i.key());
if (j != items.cend()) {
for (HistoryItemsMap::const_iterator k = j->cbegin(), end = j->cend(); k != end; ++k) {
k.key()->updateStickerEmoji();
}
}
}
// updateStickerPan();
if (App::main()) emit App::main()->stickersUpdated();
} }
bool HistoryWidget::stickersFailed(const RPCError &error) { bool HistoryWidget::stickersFailed(const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false; if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
_lastStickersUpdate = getms(true); cSetLastStickersUpdate(getms(true));
_stickersUpdateRequest = 0; _stickersUpdateRequest = 0;
return true; return true;
} }
@ -3683,6 +3792,16 @@ void HistoryWidget::onReplyForwardPreviewCancel() {
} }
} }
void HistoryWidget::onStickerPackInfo() {
if (HistoryMessage *item = dynamic_cast<HistoryMessage*>(App::contextItem())) {
if (HistorySticker *sticker = dynamic_cast<HistorySticker*>(item->getMedia())) {
if (sticker->document() && sticker->document()->sticker && sticker->document()->sticker->set.type() != mtpc_inputStickerSetEmpty) {
App::main()->stickersBox(sticker->document()->sticker->set);
}
}
}
}
void HistoryWidget::previewCancel() { void HistoryWidget::previewCancel() {
MTP::cancel(_previewRequest); MTP::cancel(_previewRequest);
_previewRequest = 0; _previewRequest = 0;

View File

@ -298,6 +298,7 @@ public:
void updateTyping(bool typing = true); void updateTyping(bool typing = true);
// void updateStickerPan(); // void updateStickerPan();
void updateRecentStickers(); void updateRecentStickers();
void stickersInstalled(uint64 setId);
void typingDone(const MTPBool &result, mtpRequestId req); void typingDone(const MTPBool &result, mtpRequestId req);
void destroyData(); void destroyData();
@ -379,6 +380,8 @@ public slots:
void onReplyToMessage(); void onReplyToMessage();
void onReplyForwardPreviewCancel(); void onReplyForwardPreviewCancel();
void onStickerPackInfo();
void onPreviewParse(); void onPreviewParse();
void onPreviewCheck(); void onPreviewCheck();
void onPreviewTimeout(); void onPreviewTimeout();
@ -473,7 +476,6 @@ private:
void stickersGot(const MTPmessages_AllStickers &stickers); void stickersGot(const MTPmessages_AllStickers &stickers);
bool stickersFailed(const RPCError &error); bool stickersFailed(const RPCError &error);
uint64 _lastStickersUpdate;
mtpRequestId _stickersUpdateRequest; mtpRequestId _stickersUpdateRequest;
void writeDraft(MsgId *replyTo = 0, const QString *text = 0, const MessageCursor *cursor = 0, bool *previewCancelled = 0); void writeDraft(MsgId *replyTo = 0, const QString *text = 0, const MessageCursor *cursor = 0, bool *previewCancelled = 0);

View File

@ -21,6 +21,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include "lang.h" #include "lang.h"
namespace { namespace {
enum StickerSetType {
StickerSetTypeEmpty = 0,
StickerSetTypeID = 1,
StickerSetTypeShortName = 2,
};
typedef quint64 FileKey; typedef quint64 FileKey;
@ -140,6 +145,10 @@ namespace {
return sizeof(quint32) + str.size() * sizeof(ushort); return sizeof(quint32) + str.size() * sizeof(ushort);
} }
uint32 _bytearraySize(const QByteArray &arr) {
return sizeof(quint32) + arr.size();
}
QByteArray _settingsSalt, _passKeySalt, _passKeyEncrypted; QByteArray _settingsSalt, _passKeySalt, _passKeyEncrypted;
mtpAuthKey _oldKey, _settingsKey, _passKey, _localKey; mtpAuthKey _oldKey, _settingsKey, _passKey, _localKey;
@ -484,17 +493,18 @@ namespace {
FileKey _dataNameKey = 0; FileKey _dataNameKey = 0;
enum { // Local Storage Keys enum { // Local Storage Keys
lskUserMap = 0, lskUserMap = 0x00,
lskDraft, // data: PeerId peer lskDraft = 0x01, // data: PeerId peer
lskDraftPosition, // data: PeerId peer lskDraftPosition = 0x02, // data: PeerId peer
lskImages, // data: StorageKey location lskImages = 0x03, // data: StorageKey location
lskLocations, // no data lskLocations = 0x04, // no data
lskStickers, // data: StorageKey location lskStickerImages = 0x05, // data: StorageKey location
lskAudios, // data: StorageKey location lskAudios = 0x06, // data: StorageKey location
lskRecentStickers, // no data lskRecentStickersOld = 0x07, // no data
lskBackground, // no data lskBackground = 0x08, // no data
lskUserSettings, // no data lskUserSettings = 0x09, // no data
lskRecentHashtags, // no data lskRecentHashtags = 0x0a, // no data
lskStickers = 0x0b, // no data
}; };
typedef QMap<PeerId, FileKey> DraftsMap; typedef QMap<PeerId, FileKey> DraftsMap;
@ -509,7 +519,7 @@ namespace {
FileLocationPairs _fileLocationPairs; FileLocationPairs _fileLocationPairs;
FileKey _locationsKey = 0; FileKey _locationsKey = 0;
FileKey _recentStickersKey = 0; FileKey _recentStickersKeyOld = 0, _stickersKey = 0;
FileKey _backgroundKey = 0; FileKey _backgroundKey = 0;
bool _backgroundWasRead = false; bool _backgroundWasRead = false;
@ -520,7 +530,7 @@ namespace {
typedef QPair<FileKey, qint32> FileDesc; // file, size typedef QPair<FileKey, qint32> FileDesc; // file, size
typedef QMap<StorageKey, FileDesc> StorageMap; typedef QMap<StorageKey, FileDesc> StorageMap;
StorageMap _imagesMap, _stickersMap, _audiosMap; StorageMap _imagesMap, _stickerImagesMap, _audiosMap;
int32 _storageImagesSize = 0, _storageStickersSize = 0, _storageAudiosSize = 0; int32 _storageImagesSize = 0, _storageStickersSize = 0, _storageAudiosSize = 0;
bool _mapChanged = false; bool _mapChanged = false;
@ -585,7 +595,7 @@ namespace {
locations.stream >> first >> second >> type >> loc.name >> loc.modified >> loc.size; locations.stream >> first >> second >> type >> loc.name >> loc.modified >> loc.size;
MediaKey key(first, second); MediaKey key(first, second);
loc.type = type; loc.type = StorageFileType(type);
if (loc.check()) { if (loc.check()) {
_fileLocations.insert(key, loc); _fileLocations.insert(key, loc);
@ -953,6 +963,14 @@ namespace {
cSetRecentEmojisPreload(v); cSetRecentEmojisPreload(v);
} break; } break;
case dbiRecentStickers: {
RecentStickerPreload v;
stream >> v;
if (!_checkStreamStatus(stream)) return false;
cSetRecentStickersPreload(v);
} break;
case dbiEmojiVariants: { case dbiEmojiVariants: {
EmojiColorVariants v; EmojiColorVariants v;
stream >> v; stream >> v;
@ -1192,8 +1210,9 @@ namespace {
uint32 size = 11 * (sizeof(quint32) + sizeof(qint32)); uint32 size = 11 * (sizeof(quint32) + sizeof(qint32));
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath()); size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath());
size += sizeof(quint32) + sizeof(qint32) + cGetRecentEmojis().size() * (sizeof(uint64) + sizeof(ushort)); size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort));
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64)); size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
size += sizeof(quint32) + sizeof(qint32) + (cRecentStickersPreload().isEmpty() ? cGetRecentStickers().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort));
size += sizeof(quint32) + _stringSize(cDialogLastPath()); size += sizeof(quint32) + _stringSize(cDialogLastPath());
EncryptedDescriptor data(size); EncryptedDescriptor data(size);
@ -1211,14 +1230,27 @@ namespace {
data.stream << quint32(dbiEmojiTab) << qint32(cEmojiTab()); data.stream << quint32(dbiEmojiTab) << qint32(cEmojiTab());
data.stream << quint32(dbiDialogLastPath) << cDialogLastPath(); data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
RecentEmojisPreload v; {
v.reserve(cGetRecentEmojis().size()); RecentEmojisPreload v(cRecentEmojisPreload());
for (RecentEmojiPack::const_iterator i = cGetRecentEmojis().cbegin(), e = cGetRecentEmojis().cend(); i != e; ++i) { if (v.isEmpty()) {
v.push_back(qMakePair(emojiKey(i->first), i->second)); v.reserve(cGetRecentEmojis().size());
for (RecentEmojiPack::const_iterator i = cGetRecentEmojis().cbegin(), e = cGetRecentEmojis().cend(); i != e; ++i) {
v.push_back(qMakePair(emojiKey(i->first), i->second));
}
}
data.stream << quint32(dbiRecentEmojis) << v;
} }
data.stream << quint32(dbiRecentEmojis) << v;
data.stream << quint32(dbiEmojiVariants) << cEmojiVariants(); data.stream << quint32(dbiEmojiVariants) << cEmojiVariants();
{
RecentStickerPreload v(cRecentStickersPreload());
if (v.isEmpty()) {
v.reserve(cGetRecentStickers().size());
for (RecentStickerPack::const_iterator i = cGetRecentStickers().cbegin(), e = cGetRecentStickers().cend(); i != e; ++i) {
v.push_back(qMakePair(i->first->id, i->second));
}
}
data.stream << quint32(dbiRecentStickers) << v;
}
FileWriteDescriptor file(_userSettingsKey); FileWriteDescriptor file(_userSettingsKey);
file.writeEncrypted(data); file.writeEncrypted(data);
@ -1340,9 +1372,9 @@ namespace {
DraftsMap draftsMap, draftsPositionsMap; DraftsMap draftsMap, draftsPositionsMap;
DraftsNotReadMap draftsNotReadMap; DraftsNotReadMap draftsNotReadMap;
StorageMap imagesMap, stickersMap, audiosMap; StorageMap imagesMap, stickerImagesMap, audiosMap;
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0; qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
quint64 locationsKey = 0, recentStickersKey = 0, backgroundKey = 0, userSettingsKey = 0, recentHashtagsKey = 0; quint64 locationsKey = 0, recentStickersKeyOld = 0, stickersKey = 0, backgroundKey = 0, userSettingsKey = 0, recentHashtagsKey = 0;
while (!map.stream.atEnd()) { while (!map.stream.atEnd()) {
quint32 keyType; quint32 keyType;
map.stream >> keyType; map.stream >> keyType;
@ -1380,7 +1412,7 @@ namespace {
storageImagesSize += size; storageImagesSize += size;
} }
} break; } break;
case lskStickers: { case lskStickerImages: {
quint32 count = 0; quint32 count = 0;
map.stream >> count; map.stream >> count;
for (quint32 i = 0; i < count; ++i) { for (quint32 i = 0; i < count; ++i) {
@ -1388,7 +1420,7 @@ namespace {
quint64 first, second; quint64 first, second;
qint32 size; qint32 size;
map.stream >> key >> first >> second >> size; map.stream >> key >> first >> second >> size;
stickersMap.insert(StorageKey(first, second), FileDesc(key, size)); stickerImagesMap.insert(StorageKey(first, second), FileDesc(key, size));
storageStickersSize += size; storageStickersSize += size;
} }
} break; } break;
@ -1407,8 +1439,8 @@ namespace {
case lskLocations: { case lskLocations: {
map.stream >> locationsKey; map.stream >> locationsKey;
} break; } break;
case lskRecentStickers: { case lskRecentStickersOld: {
map.stream >> recentStickersKey; map.stream >> recentStickersKeyOld;
} break; } break;
case lskBackground: { case lskBackground: {
map.stream >> backgroundKey; map.stream >> backgroundKey;
@ -1419,6 +1451,9 @@ namespace {
case lskRecentHashtags: { case lskRecentHashtags: {
map.stream >> recentHashtagsKey; map.stream >> recentHashtagsKey;
} break; } break;
case lskStickers: {
map.stream >> stickersKey;
} break;
default: default:
LOG(("App Error: unknown key type in encrypted map: %1").arg(keyType)); LOG(("App Error: unknown key type in encrypted map: %1").arg(keyType));
return Local::ReadMapFailed; return Local::ReadMapFailed;
@ -1434,13 +1469,14 @@ namespace {
_imagesMap = imagesMap; _imagesMap = imagesMap;
_storageImagesSize = storageImagesSize; _storageImagesSize = storageImagesSize;
_stickersMap = stickersMap; _stickerImagesMap = stickerImagesMap;
_storageStickersSize = storageStickersSize; _storageStickersSize = storageStickersSize;
_audiosMap = audiosMap; _audiosMap = audiosMap;
_storageAudiosSize = storageAudiosSize; _storageAudiosSize = storageAudiosSize;
_locationsKey = locationsKey; _locationsKey = locationsKey;
_recentStickersKey = recentStickersKey; _recentStickersKeyOld = recentStickersKeyOld;
_stickersKey = stickersKey;
_backgroundKey = backgroundKey; _backgroundKey = backgroundKey;
_userSettingsKey = userSettingsKey; _userSettingsKey = userSettingsKey;
_recentHashtagsKey = recentHashtagsKey; _recentHashtagsKey = recentHashtagsKey;
@ -1500,10 +1536,11 @@ namespace {
if (!_draftsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftsMap.size() * sizeof(quint64) * 2; 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 (!_draftsPositionsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftsPositionsMap.size() * sizeof(quint64) * 2;
if (!_imagesMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _imagesMap.size() * (sizeof(quint64) * 3 + sizeof(qint32)); if (!_imagesMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _imagesMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
if (!_stickersMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _stickersMap.size() * (sizeof(quint64) * 3 + sizeof(qint32)); if (!_stickerImagesMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _stickerImagesMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
if (!_audiosMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _audiosMap.size() * (sizeof(quint64) * 3 + sizeof(qint32)); if (!_audiosMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _audiosMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_recentStickersKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_recentStickersKeyOld) mapSize += sizeof(quint32) + sizeof(quint64);
if (_stickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_userSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_userSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_recentHashtagsKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_recentHashtagsKey) mapSize += sizeof(quint32) + sizeof(quint64);
@ -1526,9 +1563,9 @@ namespace {
mapData.stream << quint64(i.value().first) << quint64(i.key().first) << quint64(i.key().second) << qint32(i.value().second); mapData.stream << quint64(i.value().first) << quint64(i.key().first) << quint64(i.key().second) << qint32(i.value().second);
} }
} }
if (!_stickersMap.isEmpty()) { if (!_stickerImagesMap.isEmpty()) {
mapData.stream << quint32(lskStickers) << quint32(_stickersMap.size()); mapData.stream << quint32(lskStickerImages) << quint32(_stickerImagesMap.size());
for (StorageMap::const_iterator i = _stickersMap.cbegin(), e = _stickersMap.cend(); i != e; ++i) { for (StorageMap::const_iterator i = _stickerImagesMap.cbegin(), e = _stickerImagesMap.cend(); i != e; ++i) {
mapData.stream << quint64(i.value().first) << quint64(i.key().first) << quint64(i.key().second) << qint32(i.value().second); mapData.stream << quint64(i.value().first) << quint64(i.key().first) << quint64(i.key().second) << qint32(i.value().second);
} }
} }
@ -1541,8 +1578,11 @@ namespace {
if (_locationsKey) { if (_locationsKey) {
mapData.stream << quint32(lskLocations) << quint64(_locationsKey); mapData.stream << quint32(lskLocations) << quint64(_locationsKey);
} }
if (_recentStickersKey) { if (_recentStickersKeyOld) {
mapData.stream << quint32(lskRecentStickers) << quint64(_recentStickersKey); mapData.stream << quint32(lskRecentStickersOld) << quint64(_recentStickersKeyOld);
}
if (_stickersKey) {
mapData.stream << quint32(lskStickers) << quint64(_stickersKey);
} }
if (_backgroundKey) { if (_backgroundKey) {
mapData.stream << quint32(lskBackground) << quint64(_backgroundKey); mapData.stream << quint32(lskBackground) << quint64(_backgroundKey);
@ -1786,9 +1826,9 @@ namespace Local {
_draftsPositionsMap.clear(); _draftsPositionsMap.clear();
_imagesMap.clear(); _imagesMap.clear();
_draftsNotReadMap.clear(); _draftsNotReadMap.clear();
_stickersMap.clear(); _stickerImagesMap.clear();
_audiosMap.clear(); _audiosMap.clear();
_locationsKey = _recentStickersKey = _backgroundKey = _userSettingsKey = _recentHashtagsKey = 0; _locationsKey = _recentStickersKeyOld = _stickersKey = _backgroundKey = _userSettingsKey = _recentHashtagsKey = 0;
_mapChanged = true; _mapChanged = true;
_writeMap(WriteMapNow); _writeMap(WriteMapNow);
@ -1996,13 +2036,13 @@ namespace Local {
if (_imagesMap.constFind(location) != _imagesMap.cend()) return; if (_imagesMap.constFind(location) != _imagesMap.cend()) return;
QByteArray fmt = image->savedFormat(); QByteArray fmt = image->savedFormat();
mtpTypeId format = 0; StorageFileType format = StorageFileUnknown;
if (fmt == "JPG") { if (fmt == "JPG") {
format = mtpc_storage_fileJpeg; format = StorageFileJpeg;
} else if (fmt == "PNG") { } else if (fmt == "PNG") {
format = mtpc_storage_filePng; format = StorageFilePng;
} else if (fmt == "GIF") { } else if (fmt == "GIF") {
format = mtpc_storage_fileGif; format = StorageFileGif;
} }
if (format) { if (format) {
image->forget(); image->forget();
@ -2052,7 +2092,7 @@ namespace Local {
quint32 imageType; quint32 imageType;
draft.stream >> locFirst >> locSecond >> imageType >> imageData; draft.stream >> locFirst >> locSecond >> imageType >> imageData;
return (locFirst == location.first && locSecond == location.second) ? StorageImageSaved(imageType, imageData) : StorageImageSaved(); return (locFirst == location.first && locSecond == location.second) ? StorageImageSaved(StorageFileType(imageType), imageData) : StorageImageSaved();
} }
int32 hasImages() { int32 hasImages() {
@ -2063,13 +2103,13 @@ namespace Local {
return _storageImagesSize; return _storageImagesSize;
} }
void writeSticker(const StorageKey &location, const QByteArray &sticker, bool overwrite) { void writeStickerImage(const StorageKey &location, const QByteArray &sticker, bool overwrite) {
if (!_working()) return; if (!_working()) return;
qint32 size = _storageStickerSize(sticker.size()); qint32 size = _storageStickerSize(sticker.size());
StorageMap::const_iterator i = _stickersMap.constFind(location); StorageMap::const_iterator i = _stickerImagesMap.constFind(location);
if (i == _stickersMap.cend()) { if (i == _stickerImagesMap.cend()) {
i = _stickersMap.insert(location, FileDesc(genKey(UserPath), size)); i = _stickerImagesMap.insert(location, FileDesc(genKey(UserPath), size));
_storageStickersSize += size; _storageStickersSize += size;
_mapChanged = true; _mapChanged = true;
_writeMap(); _writeMap();
@ -2083,20 +2123,20 @@ namespace Local {
if (i.value().second != size) { if (i.value().second != size) {
_storageStickersSize += size; _storageStickersSize += size;
_storageStickersSize -= i.value().second; _storageStickersSize -= i.value().second;
_stickersMap[location].second = size; _stickerImagesMap[location].second = size;
} }
} }
QByteArray readSticker(const StorageKey &location) { QByteArray readStickerImage(const StorageKey &location) {
StorageMap::iterator j = _stickersMap.find(location); StorageMap::iterator j = _stickerImagesMap.find(location);
if (j == _stickersMap.cend()) { if (j == _stickerImagesMap.cend()) {
return QByteArray(); return QByteArray();
} }
FileReadDescriptor draft; FileReadDescriptor draft;
if (!readEncryptedFile(draft, j.value().first, UserPath)) { if (!readEncryptedFile(draft, j.value().first, UserPath)) {
clearKey(j.value().first, UserPath); clearKey(j.value().first, UserPath);
_storageStickersSize -= j.value().second; _storageStickersSize -= j.value().second;
_stickersMap.erase(j); _stickerImagesMap.erase(j);
return QByteArray(); return QByteArray();
} }
@ -2108,7 +2148,7 @@ namespace Local {
} }
int32 hasStickers() { int32 hasStickers() {
return _stickersMap.size(); return _stickerImagesMap.size();
} }
qint64 storageStickersSize() { qint64 storageStickersSize() {
@ -2167,56 +2207,91 @@ namespace Local {
return _storageAudiosSize; return _storageAudiosSize;
} }
void writeRecentStickers() { void writeStickers() {
if (!_working()) return; if (!_working()) return;
const RecentStickerPack &recent(cRecentStickers()); const StickerSets &sets(cStickerSets());
if (recent.isEmpty()) { if (sets.isEmpty()) {
if (_recentStickersKey) { if (_stickersKey) {
clearKey(_recentStickersKey); clearKey(_stickersKey);
_recentStickersKey = 0; _stickersKey = 0;
_mapChanged = true; _mapChanged = true;
} }
_writeMap(); _writeMap();
} else { } else {
if (!_recentStickersKey) { if (!_stickersKey) {
_recentStickersKey = genKey(); _stickersKey = genKey();
_mapChanged = true; _mapChanged = true;
_writeMap(WriteMapFast); _writeMap(WriteMapFast);
} }
quint32 size = 0; quint32 size = sizeof(quint32) + _bytearraySize(cStickersHash());
for (RecentStickerPack::const_iterator i = recent.cbegin(); i != recent.cend(); ++i) { for (StickerSets::const_iterator i = sets.cbegin(); i != sets.cend(); ++i) {
DocumentData *doc = i->first; if (i->stickers.isEmpty()) continue;
if (doc->status == FileFailed) continue;
// id + value + access + date + namelen + name + mimelen + mime + dc + size + width + height + type + alt // id + access + title + shortName + stickersCount
size += sizeof(quint64) + sizeof(qint16) + sizeof(quint64) + sizeof(qint32) + _stringSize(doc->name) + _stringSize(doc->mime) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + _stringSize(doc->sticker ? doc->sticker->alt : QString()); size += sizeof(quint64) * 2 + _stringSize(i->title) + _stringSize(i->shortName) + sizeof(quint32);
for (StickerPack::const_iterator j = i->stickers.cbegin(), e = i->stickers.cend(); j != e; ++j) {
DocumentData *doc = *j;
// id + access + date + namelen + name + mimelen + mime + dc + size + width + height + type + alt + type-of-set
size += sizeof(quint64) + sizeof(quint64) + sizeof(qint32) + _stringSize(doc->name) + _stringSize(doc->mime) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + _stringSize(doc->sticker->alt) + sizeof(qint32);
// thumb-width + thumb-height + thumb-dc + thumb-volume + thumb-local + thumb-secret
size += sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(quint64) + sizeof(qint32) + sizeof(quint64);
}
} }
EncryptedDescriptor data(size); EncryptedDescriptor data(size);
for (RecentStickerPack::const_iterator i = recent.cbegin(); i != recent.cend(); ++i) { data.stream << quint32(sets.size()) << cStickersHash();
DocumentData *doc = i->first; for (StickerSets::const_iterator i = sets.cbegin(); i != sets.cend(); ++i) {
if (doc->status == FileFailed) continue; if (i->stickers.isEmpty()) continue;
data.stream << quint64(doc->id) << qint16(i->second) << quint64(doc->access) << qint32(doc->date) << doc->name << doc->mime << qint32(doc->dc) << qint32(doc->size) << qint32(doc->dimensions.width()) << qint32(doc->dimensions.height()) << qint32(doc->type) << (doc->sticker ? doc->sticker->alt : QString()); data.stream << quint64(i->id) << quint64(i->access) << i->title << i->shortName << quint32(i->stickers.size());
for (StickerPack::const_iterator j = i->stickers.cbegin(), e = i->stickers.cend(); j != e; ++j) {
DocumentData *doc = *j;
data.stream << quint64(doc->id) << quint64(doc->access) << qint32(doc->date) << doc->name << doc->mime << qint32(doc->dc) << qint32(doc->size) << qint32(doc->dimensions.width()) << qint32(doc->dimensions.height()) << qint32(doc->type) << doc->sticker->alt;
switch (doc->sticker->set.type()) {
case mtpc_inputStickerSetID: {
data.stream << qint32(StickerSetTypeID);
} break;
case mtpc_inputStickerSetShortName: {
data.stream << qint32(StickerSetTypeShortName);
} break;
case mtpc_inputStickerSetEmpty:
default: {
data.stream << qint32(StickerSetTypeEmpty);
} break;
}
const StorageImageLocation &loc(doc->sticker->loc);
data.stream << qint32(loc.width) << qint32(loc.height) << qint32(loc.dc) << quint64(loc.volume) << qint32(loc.local) << quint64(loc.secret);
}
} }
FileWriteDescriptor file(_recentStickersKey); FileWriteDescriptor file(_stickersKey);
file.writeEncrypted(data); file.writeEncrypted(data);
} }
} }
void readRecentStickers() { void importOldRecentStickers() {
if (!_recentStickersKey) return; if (!_recentStickersKeyOld) return;
FileReadDescriptor stickers; FileReadDescriptor stickers;
if (!readEncryptedFile(stickers, _recentStickersKey)) { if (!readEncryptedFile(stickers, _recentStickersKeyOld)) {
clearKey(_recentStickersKey); clearKey(_recentStickersKeyOld);
_recentStickersKey = 0; _recentStickersKeyOld = 0;
_writeMap(); _writeMap();
return; return;
} }
StickerSets &sets(cRefStickerSets());
sets.clear();
RecentStickerPack &recent(cRefRecentStickers());
recent.clear();
cSetStickersHash(QByteArray());
StickerSet &def(sets.insert(DefaultStickerSetId, StickerSet(DefaultStickerSetId, 0, qsl("Great Minds"), QString())).value());
StickerSet &custom(sets.insert(CustomStickerSetId, StickerSet(CustomStickerSetId, 0, lang(lng_custom_stickers), QString())).value());
QMap<uint64, bool> read; QMap<uint64, bool> read;
RecentStickerPack recent;
while (!stickers.stream.atEnd()) { while (!stickers.stream.atEnd()) {
quint64 id, access; quint64 id, access;
QString name, mime, alt; QString name, mime, alt;
@ -2226,7 +2301,7 @@ namespace Local {
if (stickers.version >= 7021) { if (stickers.version >= 7021) {
stickers.stream >> alt; stickers.stream >> alt;
} }
if (read.contains(id)) continue; if (!value || read.contains(id)) continue;
read.insert(id, true); read.insert(id, true);
QVector<MTPDocumentAttribute> attributes; QVector<MTPDocumentAttribute> attributes;
@ -2240,10 +2315,109 @@ namespace Local {
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height))); attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));
} }
recent.push_back(qMakePair(App::document(id, 0, access, date, attributes, mime, ImagePtr(), dc, size), value)); DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, ImagePtr(), dc, size, StorageImageLocation());
if (!doc->sticker) continue;
if (value > 0) {
def.stickers.push_back(doc);
} else {
custom.stickers.push_back(doc);
}
if (recent.size() < StickerPanPerRow * StickerPanRowsPerPage && qAbs(value) > 1) recent.push_back(qMakePair(doc, qAbs(value)));
}
if (def.stickers.isEmpty()) sets.remove(DefaultStickerSetId);
if (custom.stickers.isEmpty()) sets.remove(CustomStickerSetId);
writeStickers();
writeUserSettings();
clearKey(_recentStickersKeyOld);
_recentStickersKeyOld = 0;
_writeMap();
}
void readStickers() {
if (!_stickersKey) {
return importOldRecentStickers();
} }
cSetRecentStickers(recent); FileReadDescriptor stickers;
if (!readEncryptedFile(stickers, _stickersKey)) {
clearKey(_stickersKey);
_stickersKey = 0;
_writeMap();
return;
}
StickerSets &sets(cRefStickerSets());
sets.clear();
quint32 cnt;
QByteArray hash;
stickers.stream >> cnt >> hash;
for (int32 i = 0; i < cnt; ++i) {
quint64 setId = 0, setAccess = 0;
QString setTitle, setShortName;
quint32 scnt = 0;
stickers.stream >> setId >> setAccess >> setTitle >> setShortName >> scnt;
if (setId == DefaultStickerSetId) {
setTitle = qsl("Great Minds");
} else if (setId == CustomStickerSetId) {
setTitle = lang(lng_custom_stickers);
}
StickerSet &set(sets.insert(setId, StickerSet(setId, setAccess, setTitle, setShortName)).value());
set.stickers.reserve(scnt);
QMap<uint64, bool> read;
for (int32 j = 0; j < scnt; ++j) {
quint64 id, access;
QString name, mime, alt;
qint32 date, dc, size, width, height, type, typeOfSet;
stickers.stream >> id >> access >> date >> name >> mime >> dc >> size >> width >> height >> type >> alt >> typeOfSet;
qint32 thumbWidth, thumbHeight, thumbDc, thumbLocal;
quint64 thumbVolume, thumbSecret;
stickers.stream >> thumbWidth >> thumbHeight >> thumbDc >> thumbVolume >> thumbLocal >> thumbSecret;
if (read.contains(id)) continue;
read.insert(id, true);
if (setId == DefaultStickerSetId || setId == CustomStickerSetId) {
typeOfSet = StickerSetTypeEmpty;
}
QVector<MTPDocumentAttribute> attributes;
if (!name.isEmpty()) attributes.push_back(MTP_documentAttributeFilename(MTP_string(name)));
if (type == AnimatedDocument) {
attributes.push_back(MTP_documentAttributeAnimated());
} else if (type == StickerDocument) {
switch (typeOfSet) {
case StickerSetTypeID: {
attributes.push_back(MTP_documentAttributeSticker(MTP_string(alt), MTP_inputStickerSetID(MTP_long(setId), MTP_long(setAccess))));
} break;
case StickerSetTypeShortName: {
attributes.push_back(MTP_documentAttributeSticker(MTP_string(alt), MTP_inputStickerSetShortName(MTP_string(setShortName))));
} break;
case StickerSetTypeEmpty:
default: {
attributes.push_back(MTP_documentAttributeSticker(MTP_string(alt), MTP_inputStickerSetEmpty()));
} break;
}
}
if (width > 0 && height > 0) {
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));
}
StorageImageLocation thumb(thumbWidth, thumbHeight, thumbDc, thumbVolume, thumbLocal, thumbSecret);
DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, thumb.dc ? ImagePtr(thumb) : ImagePtr(), dc, size, thumb);
if (!doc->sticker) continue;
set.stickers.push_back(doc);
}
}
cSetStickersHash(hash);
} }
void writeBackground(int32 id, const QImage &img) { void writeBackground(int32 id, const QImage &img) {
@ -2412,8 +2586,8 @@ namespace Local {
_storageImagesSize = 0; _storageImagesSize = 0;
_mapChanged = true; _mapChanged = true;
} }
if (!_stickersMap.isEmpty()) { if (!_stickerImagesMap.isEmpty()) {
_stickersMap.clear(); _stickerImagesMap.clear();
_storageStickersSize = 0; _storageStickersSize = 0;
_mapChanged = true; _mapChanged = true;
} }
@ -2434,8 +2608,12 @@ namespace Local {
_locationsKey = 0; _locationsKey = 0;
_mapChanged = true; _mapChanged = true;
} }
if (_recentStickersKey) { if (_recentStickersKeyOld) {
_recentStickersKey = 0; _recentStickersKeyOld = 0;
_mapChanged = true;
}
if (_stickersKey) {
_stickersKey = 0;
_mapChanged = true; _mapChanged = true;
} }
if (_recentHashtagsKey) { if (_recentHashtagsKey) {
@ -2462,9 +2640,9 @@ namespace Local {
_mapChanged = true; _mapChanged = true;
} }
if (data->stickers.isEmpty()) { if (data->stickers.isEmpty()) {
data->stickers = _stickersMap; data->stickers = _stickerImagesMap;
} else { } else {
for (StorageMap::const_iterator i = _stickersMap.cbegin(), e = _stickersMap.cend(); i != e; ++i) { for (StorageMap::const_iterator i = _stickerImagesMap.cbegin(), e = _stickerImagesMap.cend(); i != e; ++i) {
StorageKey k = i.key(); StorageKey k = i.key();
while (data->stickers.constFind(k) != data->stickers.cend()) { while (data->stickers.constFind(k) != data->stickers.cend()) {
++k.second; ++k.second;
@ -2472,8 +2650,8 @@ namespace Local {
data->stickers.insert(k, i.value()); data->stickers.insert(k, i.value());
} }
} }
if (!_stickersMap.isEmpty()) { if (!_stickerImagesMap.isEmpty()) {
_stickersMap.clear(); _stickerImagesMap.clear();
_storageStickersSize = 0; _storageStickersSize = 0;
_mapChanged = true; _mapChanged = true;
} }

View File

@ -122,8 +122,8 @@ namespace Local {
int32 hasImages(); int32 hasImages();
qint64 storageImagesSize(); qint64 storageImagesSize();
void writeSticker(const StorageKey &location, const QByteArray &data, bool overwrite = true); void writeStickerImage(const StorageKey &location, const QByteArray &data, bool overwrite = true);
QByteArray readSticker(const StorageKey &location); QByteArray readStickerImage(const StorageKey &location);
int32 hasStickers(); int32 hasStickers();
qint64 storageStickersSize(); qint64 storageStickersSize();
@ -132,8 +132,8 @@ namespace Local {
int32 hasAudios(); int32 hasAudios();
qint64 storageAudiosSize(); qint64 storageAudiosSize();
void writeRecentStickers(); void writeStickers();
void readRecentStickers(); void readStickers();
void writeBackground(int32 id, const QImage &img); void writeBackground(int32 id, const QImage &img);
bool readBackground(); bool readBackground();

View File

@ -25,6 +25,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include "settingswidget.h" #include "settingswidget.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "boxes/confirmbox.h" #include "boxes/confirmbox.h"
#include "boxes/stickersetbox.h"
#include "localstorage.h" #include "localstorage.h"
@ -549,6 +550,10 @@ void MainWidget::updateMutedIn(int32 seconds) {
_updateMutedTimer.start(ms); _updateMutedTimer.start(ms);
} }
void MainWidget::updateStickers() {
history.updateStickers();
}
void MainWidget::onUpdateMuted() { void MainWidget::onUpdateMuted() {
App::updateMuted(); App::updateMuted();
} }
@ -977,7 +982,7 @@ void MainWidget::saveRecentHashtags(const QString &text) {
} }
} }
if (!found && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) { if (!found && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) {
Local::readRecentStickers(); Local::readRecentHashtags();
recent = cRecentWriteHashtags(); recent = cRecentWriteHashtags();
} }
found = true; found = true;
@ -2473,7 +2478,7 @@ void MainWidget::start(const MTPUser &user) {
} }
_started = true; _started = true;
App::wnd()->sendServiceHistoryRequest(); App::wnd()->sendServiceHistoryRequest();
Local::readRecentStickers(); Local::readStickers();
history.start(); history.start();
} }
@ -2493,6 +2498,11 @@ void MainWidget::openLocalUrl(const QString &url) {
if (m.hasMatch()) { if (m.hasMatch()) {
joinGroupByHash(m.captured(1)); joinGroupByHash(m.captured(1));
} }
} else if (u.startsWith(QLatin1String("tg://addstickers"), Qt::CaseInsensitive)) {
QRegularExpressionMatch m = QRegularExpression(qsl("^tg://addstickers/?\\?set=([a-zA-Z0-9\\.\\_]+)$"), QRegularExpression::CaseInsensitiveOption).match(u);
if (m.hasMatch()) {
stickersBox(MTP_inputStickerSetShortName(MTP_string(m.captured(1))));
}
} }
} }
@ -2513,6 +2523,17 @@ void MainWidget::joinGroupByHash(const QString &hash) {
MTP::send(MTPmessages_CheckChatInvite(MTP_string(hash)), rpcDone(&MainWidget::inviteCheckDone, hash), rpcFail(&MainWidget::inviteCheckFail)); MTP::send(MTPmessages_CheckChatInvite(MTP_string(hash)), rpcDone(&MainWidget::inviteCheckDone, hash), rpcFail(&MainWidget::inviteCheckFail));
} }
void MainWidget::stickersBox(const MTPInputStickerSet &set) {
StickerSetBox *box = new StickerSetBox(set);
connect(box, SIGNAL(installed(uint64)), this, SLOT(onStickersInstalled(uint64)));
App::wnd()->showLayer(box);
}
void MainWidget::onStickersInstalled(uint64 setId) {
emit stickersUpdated();
history.stickersInstalled(setId);
}
void MainWidget::usernameResolveDone(bool toProfile, const MTPUser &user) { void MainWidget::usernameResolveDone(bool toProfile, const MTPUser &user) {
App::wnd()->hideLayer(); App::wnd()->hideLayer();
UserData *u = App::feedUsers(MTP_vector<MTPUser>(1, user)); UserData *u = App::feedUsers(MTP_vector<MTPUser>(1, user));
@ -2733,28 +2754,24 @@ void MainWidget::updateNotifySetting(PeerData *peer, bool enabled) {
} }
void MainWidget::incrementSticker(DocumentData *sticker) { void MainWidget::incrementSticker(DocumentData *sticker) {
RecentStickerPack recent(cRecentStickers()); if (!sticker || !sticker->sticker) return;
RecentStickerPack &recent(cGetRecentStickers());
RecentStickerPack::iterator i = recent.begin(), e = recent.end(); RecentStickerPack::iterator i = recent.begin(), e = recent.end();
for (; i != e; ++i) { for (; i != e; ++i) {
if (i->first == sticker) { if (i->first == sticker) {
if (i->second > 0) { ++i->second;
++i->second; if (i->second > 0x8000) {
} else {
--i->second;
}
if (qAbs(i->second) > 0x4000) {
for (RecentStickerPack::iterator j = recent.begin(); j != e; ++j) { for (RecentStickerPack::iterator j = recent.begin(); j != e; ++j) {
if (qAbs(j->second) > 1) { if (j->second > 1) {
j->second /= 2; j->second /= 2;
} else if (j->second > 0) {
j->second = 1;
} else { } else {
j->second = -1; j->second = 1;
} }
} }
} }
for (; i != recent.begin(); --i) { for (; i != recent.begin(); --i) {
if (qAbs((i - 1)->second) > qAbs(i->second)) { if ((i - 1)->second > i->second) {
break; break;
} }
qSwap(*i, *(i - 1)); qSwap(*i, *(i - 1));
@ -2763,11 +2780,45 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
} }
} }
if (i == e) { if (i == e) {
recent.push_front(qMakePair(sticker, -(recent.isEmpty() ? 1 : qAbs(recent.front().second)))); while (recent.size() >= StickerPanPerRow * StickerPanRowsPerPage) recent.pop_back();
recent.push_back(qMakePair(sticker, 1));
for (i = recent.end() - 1; i != recent.begin(); --i) {
if ((i - 1)->second > i->second) {
break;
}
qSwap(*i, *(i - 1));
}
} }
cSetRecentStickers(recent);
Local::writeRecentStickers();
Local::writeUserSettings();
bool found = false;
uint64 setId = 0;
QString setName;
switch (sticker->sticker->set.type()) {
case mtpc_inputStickerSetID: setId = sticker->sticker->set.c_inputStickerSetID().vid.v; break;
case mtpc_inputStickerSetShortName: setName = qs(sticker->sticker->set.c_inputStickerSetShortName().vshort_name).toLower().trimmed(); break;
}
StickerSets &sets(cRefStickerSets());
for (StickerSets::const_iterator i = sets.cbegin(); i != sets.cend(); ++i) {
if (i->id == CustomStickerSetId || (setId && i->id == setId) || (!setName.isEmpty() && i->shortName.toLower().trimmed() == setName) || (!setId && setName.isEmpty() && i->id == DefaultStickerSetId)) {
for (int32 j = 0, l = i->stickers.size(); j < l; ++j) {
if (i->stickers.at(j) == sticker) {
found = true;
break;
}
}
if (found) break;
}
}
if (!found) {
StickerSets::iterator it = sets.find(CustomStickerSetId);
if (it == sets.cend()) {
it = sets.insert(CustomStickerSetId, StickerSet(CustomStickerSetId, 0, lang(lng_custom_stickers), QString()));
}
it->stickers.push_back(sticker);
Local::writeStickers();
}
history.updateRecentStickers(); history.updateRecentStickers();
} }

View File

@ -185,9 +185,12 @@ public:
bool animStep(float64 ms); bool animStep(float64 ms);
void start(const MTPUser &user); void start(const MTPUser &user);
void openLocalUrl(const QString &str); void openLocalUrl(const QString &str);
void openUserByName(const QString &name, bool toProfile = false); void openUserByName(const QString &name, bool toProfile = false);
void joinGroupByHash(const QString &hash); void joinGroupByHash(const QString &hash);
void stickersBox(const MTPInputStickerSet &set);
void startFull(const MTPVector<MTPUser> &users); void startFull(const MTPVector<MTPUser> &users);
bool started(); bool started();
void applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNotifySettings &settings, History *history = 0); void applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNotifySettings &settings, History *history = 0);
@ -341,6 +344,8 @@ public:
void webPageUpdated(WebPageData *page); void webPageUpdated(WebPageData *page);
void updateMutedIn(int32 seconds); void updateMutedIn(int32 seconds);
void updateStickers();
~MainWidget(); ~MainWidget();
signals: signals:
@ -352,6 +357,7 @@ signals:
void dialogToTop(const History::DialogLinks &links); void dialogToTop(const History::DialogLinks &links);
void dialogsUpdated(); void dialogsUpdated();
void showPeerAsync(quint64 peer, qint32 msgId, bool back, bool force); void showPeerAsync(quint64 peer, qint32 msgId, bool back, bool force);
void stickersUpdated();
public slots: public slots:
@ -402,6 +408,8 @@ public slots:
void onUpdateMuted(); void onUpdateMuted();
void onStickersInstalled(uint64 setId);
private: private:
void partWasRead(PeerData *peer, const MTPmessages_AffectedHistory &result); void partWasRead(PeerData *peer, const MTPmessages_AffectedHistory &result);

View File

@ -44,7 +44,7 @@ namespace {
LoaderQueues queues; LoaderQueues queues;
} }
mtpFileLoader::mtpFileLoader(int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size) : prev(0), next(0), mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &volume, int32 local, const uint64 &secret, int32 size) : prev(0), next(0),
priority(0), inQueue(false), complete(false), triedLocal(false), skippedBytes(0), nextRequestOffset(0), lastComplete(false), priority(0), inQueue(false), complete(false), triedLocal(false), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
dc(dc), locationType(0), volume(volume), local(local), secret(secret), dc(dc), locationType(0), volume(volume), local(local), secret(secret),
id(0), access(0), fileIsOpen(false), size(size), type(mtpc_storage_fileUnknown) { id(0), access(0), fileIsOpen(false), size(size), type(mtpc_storage_fileUnknown) {
@ -247,23 +247,24 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
psPostprocessFile(QFileInfo(file).absoluteFilePath()); psPostprocessFile(QFileInfo(file).absoluteFilePath());
} }
removeFromQueue(); removeFromQueue();
App::wnd()->update();
App::wnd()->notifyUpdateAllPhotos(); emit App::wnd()->imageLoaded();
if (!queue->queries) { if (!queue->queries) {
App::app()->killDownloadSessionsStart(dc); App::app()->killDownloadSessionsStart(dc);
} }
if (!locationType && triedLocal && (fname.isEmpty() || duplicateInData)) { if (!locationType && triedLocal && (fname.isEmpty() || duplicateInData)) {
Local::writeImage(storageKey(dc, volume, local), StorageImageSaved(type, data)); Local::writeImage(storageKey(dc, volume, local), StorageImageSaved(mtpToStorageType(type), data));
} else if (locationType && triedLocal) { } else if (locationType && triedLocal) {
if (!fname.isEmpty()) { if (!fname.isEmpty()) {
Local::writeFileLocation(mediaKey(locationType, dc, id), FileLocation(type, fname)); Local::writeFileLocation(mediaKey(mtpToLocationType(locationType), dc, id), FileLocation(mtpToStorageType(type), fname));
} }
if (duplicateInData) { if (duplicateInData) {
if (locationType == mtpc_inputDocumentFileLocation) { if (locationType == mtpc_inputDocumentFileLocation) {
Local::writeSticker(mediaKey(locationType, dc, id), data); Local::writeStickerImage(mediaKey(mtpToLocationType(locationType), dc, id), data);
} else if (locationType == mtpc_inputAudioFileLocation) { } else if (locationType == mtpc_inputAudioFileLocation) {
Local::writeAudio(mediaKey(locationType, dc, id), data); Local::writeAudio(mediaKey(mtpToLocationType(locationType), dc, id), data);
} }
} }
} }
@ -308,9 +309,9 @@ void mtpFileLoader::start(bool loadFirst, bool prior) {
if (!locationType) { if (!locationType) {
triedLocal = true; triedLocal = true;
StorageImageSaved cached = Local::readImage(storageKey(dc, volume, local)); StorageImageSaved cached = Local::readImage(storageKey(dc, volume, local));
if (cached.type != mtpc_storage_fileUnknown) { if (cached.type != StorageFileUnknown) {
data = cached.data; data = cached.data;
type = cached.type; type = mtpFromStorageType(cached.type);
} }
} else if (locationType) { } else if (locationType) {
if (!fname.isEmpty()) { if (!fname.isEmpty()) {
@ -319,11 +320,11 @@ void mtpFileLoader::start(bool loadFirst, bool prior) {
if (duplicateInData) { if (duplicateInData) {
if (locationType == mtpc_inputDocumentFileLocation) { if (locationType == mtpc_inputDocumentFileLocation) {
triedLocal = true; triedLocal = true;
data = Local::readSticker(mediaKey(locationType, dc, id)); data = Local::readStickerImage(mediaKey(mtpToLocationType(locationType), dc, id));
if (!data.isEmpty()) type = mtpc_storage_filePartial; if (!data.isEmpty()) type = mtpc_storage_filePartial;
} else if (locationType == mtpc_inputAudioFileLocation) { } else if (locationType == mtpc_inputAudioFileLocation) {
triedLocal = true; triedLocal = true;
data = Local::readAudio(mediaKey(locationType, dc, id)); data = Local::readAudio(mediaKey(mtpToLocationType(locationType), dc, id));
if (!data.isEmpty()) type = mtpc_storage_filePartial; if (!data.isEmpty()) type = mtpc_storage_filePartial;
} }
} }
@ -344,8 +345,7 @@ void mtpFileLoader::start(bool loadFirst, bool prior) {
fileIsOpen = false; fileIsOpen = false;
psPostprocessFile(QFileInfo(file).absoluteFilePath()); psPostprocessFile(QFileInfo(file).absoluteFilePath());
} }
App::wnd()->update(); emit App::wnd()->imageLoaded();
App::wnd()->notifyUpdateAllPhotos();
emit progress(this); emit progress(this);
return loadNext(); return loadNext();
} }

View File

@ -27,7 +27,7 @@ class mtpFileLoader : public QObject, public RPCSender {
public: public:
mtpFileLoader(int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size = 0); mtpFileLoader(int32 dc, const uint64 &volume, int32 local, const uint64 &secret, int32 size = 0);
mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size); mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size);
mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size, bool todata); mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size, bool todata);
bool done() const; bool done() const;
@ -82,9 +82,9 @@ private:
int32 dc; int32 dc;
mtpTypeId locationType; // 0 or mtpc_inputVideoFileLocation / mtpc_inputAudioFileLocation / mtpc_inputDocumentFileLocation mtpTypeId locationType; // 0 or mtpc_inputVideoFileLocation / mtpc_inputAudioFileLocation / mtpc_inputDocumentFileLocation
int64 volume; // for photo locations uint64 volume; // for photo locations
int32 local; int32 local;
int64 secret; uint64 secret;
uint64 id; // for other locations uint64 id; // for other locations
uint64 access; uint64 access;

View File

@ -256,6 +256,7 @@ void ProfileInner::onMediaAudios() {
} }
void ProfileInner::onInvitationLink() { void ProfileInner::onInvitationLink() {
DEBUG_LOG(("Setting text to clipboard from invite url: %1").arg(_peerChat->invitationUrl));
QApplication::clipboard()->setText(_peerChat->invitationUrl); QApplication::clipboard()->setText(_peerChat->invitationUrl);
App::wnd()->showLayer(new ConfirmBox(lang(lng_group_invite_copied), true)); App::wnd()->showLayer(new ConfirmBox(lang(lng_group_invite_copied), true));
} }
@ -769,10 +770,12 @@ void ProfileInner::onMenuDestroy(QObject *obj) {
} }
void ProfileInner::onCopyPhone() { void ProfileInner::onCopyPhone() {
DEBUG_LOG(("Setting text to clipboard from user phone: %1").arg(_phoneText));
QApplication::clipboard()->setText(_phoneText); QApplication::clipboard()->setText(_phoneText);
} }
void ProfileInner::onCopyUsername() { void ProfileInner::onCopyUsername() {
DEBUG_LOG(("Setting text to clipboard from username: @%1").arg(_peerUser->username));
QApplication::clipboard()->setText('@' + _peerUser->username); QApplication::clipboard()->setText('@' + _peerUser->username);
} }

View File

@ -89,12 +89,15 @@ RecentEmojiPack gRecentEmojis;
RecentEmojisPreload gRecentEmojisPreload; RecentEmojisPreload gRecentEmojisPreload;
EmojiColorVariants gEmojiVariants; EmojiColorVariants gEmojiVariants;
AllStickers gStickers;
QByteArray gStickersHash; QByteArray gStickersHash;
EmojiStickersMap gEmojiStickers; EmojiStickersMap gEmojiStickers;
RecentStickerPreload gRecentStickersPreload;
RecentStickerPack gRecentStickers; RecentStickerPack gRecentStickers;
StickerSets gStickerSets;
uint64 gLastStickersUpdate = 0;
RecentHashtagPack gRecentWriteHashtags, gRecentSearchHashtags; RecentHashtagPack gRecentWriteHashtags, gRecentSearchHashtags;
@ -249,7 +252,7 @@ RecentEmojiPack &cGetRecentEmojis() {
0xD83DDE15LLU, 0xD83DDE15LLU,
}; };
for (int32 i = 0, s = sizeof(defaultRecent) / sizeof(defaultRecent[0]); i < s; ++i) { for (int32 i = 0, s = sizeof(defaultRecent) / sizeof(defaultRecent[0]); i < s; ++i) {
if (r.size() >= EmojiPadPerRow * EmojiPadRowsPerPage) break; if (r.size() >= EmojiPanPerRow * EmojiPanRowsPerPage) break;
EmojiPtr ep(emojiGet(defaultRecent[i])); EmojiPtr ep(emojiGet(defaultRecent[i]));
if (!ep || ep == TwoSymbolEmoji) continue; if (!ep || ep == TwoSymbolEmoji) continue;
@ -268,3 +271,20 @@ RecentEmojiPack &cGetRecentEmojis() {
} }
return cRefRecentEmojis(); return cRefRecentEmojis();
} }
RecentStickerPack &cGetRecentStickers() {
if (cRecentStickers().isEmpty() && !cRecentStickersPreload().isEmpty()) {
RecentStickerPreload p(cRecentStickersPreload());
cSetRecentStickersPreload(RecentStickerPreload());
RecentStickerPack &recent(cRefRecentStickers());
recent.reserve(p.size());
for (RecentStickerPreload::const_iterator i = p.cbegin(), e = p.cend(); i != e; ++i) {
DocumentData *doc = App::document(i->first);
if (!doc || !doc->sticker) continue;
recent.push_back(qMakePair(doc, i->second));
}
}
return cRefRecentStickers();
}

View File

@ -183,15 +183,31 @@ RecentEmojiPack &cGetRecentEmojis();
struct DocumentData; struct DocumentData;
typedef QVector<DocumentData*> StickerPack; typedef QVector<DocumentData*> StickerPack;
typedef QMap<EmojiPtr, StickerPack> AllStickers;
DeclareSetting(AllStickers, Stickers);
DeclareSetting(QByteArray, StickersHash); DeclareSetting(QByteArray, StickersHash);
typedef QMap<DocumentData*, EmojiPtr> EmojiStickersMap; typedef QMap<DocumentData*, EmojiPtr> EmojiStickersMap;
DeclareSetting(EmojiStickersMap, EmojiStickers); DeclareSetting(EmojiStickersMap, EmojiStickers);
typedef QList<QPair<DocumentData*, int16> > RecentStickerPack; typedef QList<QPair<DocumentData*, int16> > RecentStickerPackOld;
DeclareSetting(RecentStickerPack, RecentStickers); typedef QVector<QPair<uint64, ushort> > RecentStickerPreload;
typedef QVector<QPair<DocumentData*, ushort> > RecentStickerPack;
DeclareSetting(RecentStickerPreload, RecentStickersPreload);
DeclareRefSetting(RecentStickerPack, RecentStickers);
RecentStickerPack &cGetRecentStickers();
DeclareSetting(uint64, LastStickersUpdate);
static const uint64 DefaultStickerSetId = 0, CustomStickerSetId = 0xFFFFFFFFFFFFFFFFLLU, RecentStickerSetId = 0xFFFFFFFFFFFFFFFELLU;
struct StickerSet {
StickerSet(uint64 id, uint64 access, const QString &title, const QString &shortName) : id(id), access(access), title(title), shortName(shortName) {
}
uint64 id, access;
QString title, shortName;
StickerPack stickers;
};
typedef QMap<uint64, StickerSet> StickerSets;
DeclareRefSetting(StickerSets, StickerSets);
typedef QList<QPair<QString, ushort> > RecentHashtagPack; typedef QList<QPair<QString, ushort> > RecentHashtagPack;
DeclareSetting(RecentHashtagPack, RecentWriteHashtags); DeclareSetting(RecentHashtagPack, RecentWriteHashtags);

View File

@ -348,7 +348,7 @@ void VideoCancelLink::onClick(Qt::MouseButton button) const {
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) : 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) { 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)); location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
} }
void VideoData::save(const QString &toFile) { void VideoData::save(const QString &toFile) {
@ -361,7 +361,7 @@ void VideoData::save(const QString &toFile) {
QString VideoData::already(bool check) { QString VideoData::already(bool check) {
if (!check) return location.name; if (!check) return location.name;
if (!location.check()) location = Local::readFileLocation(mediaKey(mtpc_inputVideoFileLocation, dc, id)); if (!location.check()) location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
return location.name; return location.name;
} }
@ -442,7 +442,7 @@ void AudioCancelLink::onClick(Qt::MouseButton button) const {
AudioData::AudioData(const AudioId &id, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) : AudioData::AudioData(const AudioId &id, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) :
id(id), access(access), user(user), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) { id(id), access(access), user(user), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
location = Local::readFileLocation(mediaKey(mtpc_inputAudioFileLocation, dc, id)); location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
} }
void AudioData::save(const QString &toFile) { void AudioData::save(const QString &toFile) {
@ -455,7 +455,7 @@ void AudioData::save(const QString &toFile) {
QString AudioData::already(bool check) { QString AudioData::already(bool check) {
if (!check) return location.name; if (!check) return location.name;
if (!location.check()) location = Local::readFileLocation(mediaKey(mtpc_inputAudioFileLocation, dc, id)); if (!location.check()) location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
return location.name; return location.name;
} }
@ -560,7 +560,7 @@ void DocumentCancelLink::onClick(Qt::MouseButton button) const {
DocumentData::DocumentData(const DocumentId &id, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size) : DocumentData::DocumentData(const DocumentId &id, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size) :
id(id), type(FileDocument), duration(0), access(access), date(date), mime(mime), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0), sticker(0) { id(id), type(FileDocument), duration(0), access(access), date(date), mime(mime), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0), sticker(0) {
setattributes(attributes); setattributes(attributes);
location = Local::readFileLocation(mediaKey(mtpc_inputDocumentFileLocation, dc, id)); location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id));
} }
void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) { void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) {
@ -607,7 +607,7 @@ void DocumentData::save(const QString &toFile) {
QString DocumentData::already(bool check) { QString DocumentData::already(bool check) {
if (!check) return location.name; if (!check) return location.name;
if (!location.check()) location = Local::readFileLocation(mediaKey(mtpc_inputDocumentFileLocation, dc, id)); if (!location.check()) location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id));
return location.name; return location.name;
} }

View File

@ -253,7 +253,7 @@ struct VideoData {
void finish() { void finish() {
if (loader->done()) { if (loader->done()) {
location = FileLocation(loader->fileType(), loader->fileName()); location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
} }
loader->deleteLater(); loader->deleteLater();
loader->rpcInvalidate(); loader->rpcInvalidate();
@ -339,7 +339,7 @@ struct AudioData {
void finish() { void finish() {
if (loader->done()) { if (loader->done()) {
location = FileLocation(loader->fileType(), loader->fileName()); location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
data = loader->bytes(); data = loader->bytes();
} }
loader->deleteLater(); loader->deleteLater();
@ -409,6 +409,7 @@ struct StickerData {
QString alt; QString alt;
MTPInputStickerSet set; MTPInputStickerSet set;
StorageImageLocation loc; // doc thumb location
}; };
enum DocumentType { enum DocumentType {
@ -446,7 +447,7 @@ struct DocumentData {
void finish() { void finish() {
if (loader->done()) { if (loader->done()) {
location = FileLocation(loader->fileType(), loader->fileName()); location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
data = loader->bytes(); data = loader->bytes();
} }
loader->deleteLater(); loader->deleteLater();

View File

@ -225,51 +225,52 @@ QString translitRusEng(const QString &rus);
QString rusKeyboardLayoutSwitch(const QString &from); QString rusKeyboardLayoutSwitch(const QString &from);
enum DataBlockId { enum DataBlockId {
dbiKey = 0, dbiKey = 0x00,
dbiUser = 1, dbiUser = 0x01,
dbiDcOption = 2, dbiDcOption = 0x02,
dbiMaxGroupCount = 3, dbiMaxGroupCount = 0x03,
dbiMutePeer = 4, dbiMutePeer = 0x04,
dbiSendKey = 5, dbiSendKey = 0x05,
dbiAutoStart = 6, dbiAutoStart = 0x06,
dbiStartMinimized = 7, dbiStartMinimized = 0x07,
dbiSoundNotify = 8, dbiSoundNotify = 0x08,
dbiWorkMode = 9, dbiWorkMode = 0x09,
dbiSeenTrayTooltip = 10, dbiSeenTrayTooltip = 0x0a,
dbiDesktopNotify = 11, dbiDesktopNotify = 0x0b,
dbiAutoUpdate = 12, dbiAutoUpdate = 0x0c,
dbiLastUpdateCheck = 13, dbiLastUpdateCheck = 0x0d,
dbiWindowPosition = 14, dbiWindowPosition = 0x0e,
dbiConnectionType = 15, dbiConnectionType = 0x0f,
// 16 reserved // 16 reserved
dbiDefaultAttach = 17, dbiDefaultAttach = 0x11,
dbiCatsAndDogs = 18, dbiCatsAndDogs = 0x12,
dbiReplaceEmojis = 19, dbiReplaceEmojis = 0x13,
dbiAskDownloadPath = 20, dbiAskDownloadPath = 0x14,
dbiDownloadPath = 21, dbiDownloadPath = 0x15,
dbiScale = 22, dbiScale = 0x16,
dbiEmojiTab = 23, dbiEmojiTab = 0x17,
dbiRecentEmojisOld = 24, dbiRecentEmojisOld = 0x18,
dbiLoggedPhoneNumber = 25, dbiLoggedPhoneNumber = 0x19,
dbiMutedPeers = 26, dbiMutedPeers = 0x1a,
// 27 reserved // 27 reserved
dbiNotifyView = 28, dbiNotifyView = 0x1c,
dbiSendToMenu = 29, dbiSendToMenu = 0x1d,
dbiCompressPastedImage = 30, dbiCompressPastedImage = 0x1e,
dbiLang = 31, dbiLang = 0x1f,
dbiLangFile = 32, dbiLangFile = 0x20,
dbiTileBackground = 33, dbiTileBackground = 0x21,
dbiAutoLock = 34, dbiAutoLock = 0x22,
dbiDialogLastPath = 35, dbiDialogLastPath = 0x23,
dbiRecentEmojis = 36, dbiRecentEmojis = 0x24,
dbiEmojiVariants = 37, dbiEmojiVariants = 0x25,
dbiRecentStickers = 0x26,
dbiEncryptedWithSalt = 333, dbiEncryptedWithSalt = 333,
dbiEncrypted = 444, dbiEncrypted = 444,
// 500-600 reserved // 500-600 reserved
dbiVersion = 666, dbiVersion = 666,
}; };
enum DBISendKey { enum DBISendKey {

View File

@ -381,6 +381,9 @@ _connecting(0), _clearManager(0), dragging(false), _inactivePress(false), _shoul
connect(&_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActive())); connect(&_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActive()));
connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock())); connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock()));
connect(this, SIGNAL(imageLoaded()), this, SLOT(update()));
connect(this, SIGNAL(imageLoaded()), this, SLOT(notifyUpdateAllPhotos()));
} }
void Window::inactivePress(bool inactive) { void Window::inactivePress(bool inactive) {
@ -609,7 +612,7 @@ void Window::sendServiceHistoryRequest() {
} }
void Window::setupMain(bool anim, const MTPUser *self) { void Window::setupMain(bool anim, const MTPUser *self) {
Local::readRecentStickers(); Local::readStickers();
QPixmap bg = anim ? myGrab(this, QRect(0, st::titleHeight, width(), height() - st::titleHeight)) : QPixmap(); QPixmap bg = anim ? myGrab(this, QRect(0, st::titleHeight, width(), height() - st::titleHeight)) : QPixmap();
clearWidgets(); clearWidgets();

View File

@ -219,7 +219,6 @@ public:
void notifyItemRemoved(HistoryItem *item); void notifyItemRemoved(HistoryItem *item);
void notifyStopHiding(); void notifyStopHiding();
void notifyStartHiding(); void notifyStartHiding();
void notifyUpdateAllPhotos();
void notifyUpdateAll(); void notifyUpdateAll();
void notifyActivateAll(); void notifyActivateAll();
@ -270,6 +269,8 @@ public slots:
QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon); QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon);
void notifyUpdateAllPhotos();
signals: signals:
void resized(const QSize &size); void resized(const QSize &size);
@ -277,6 +278,8 @@ signals:
void tempDirClearFailed(int task); void tempDirClearFailed(int task);
void newAuthorization(); void newAuthorization();
void imageLoaded();
private: private:
void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color); void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color);

Binary file not shown.

View File

@ -377,6 +377,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="GeneratedFiles\Debug\moc_stickersetbox.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="GeneratedFiles\Debug\moc_switcher.cpp"> <ClCompile Include="GeneratedFiles\Debug\moc_switcher.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@ -635,6 +639,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="GeneratedFiles\Deploy\moc_stickersetbox.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="GeneratedFiles\Deploy\moc_switcher.cpp"> <ClCompile Include="GeneratedFiles\Deploy\moc_switcher.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@ -918,6 +926,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="GeneratedFiles\Release\moc_stickersetbox.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="GeneratedFiles\Release\moc_switcher.cpp"> <ClCompile Include="GeneratedFiles\Release\moc_switcher.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@ -966,6 +978,7 @@
<ClCompile Include="SourceFiles\boxes\photocropbox.cpp" /> <ClCompile Include="SourceFiles\boxes\photocropbox.cpp" />
<ClCompile Include="SourceFiles\boxes\photosendbox.cpp" /> <ClCompile Include="SourceFiles\boxes\photosendbox.cpp" />
<ClCompile Include="SourceFiles\boxes\sessionsbox.cpp" /> <ClCompile Include="SourceFiles\boxes\sessionsbox.cpp" />
<ClCompile Include="SourceFiles\boxes\stickersetbox.cpp" />
<ClCompile Include="SourceFiles\boxes\usernamebox.cpp" /> <ClCompile Include="SourceFiles\boxes\usernamebox.cpp" />
<ClCompile Include="SourceFiles\dialogswidget.cpp" /> <ClCompile Include="SourceFiles\dialogswidget.cpp" />
<ClCompile Include="SourceFiles\dropdown.cpp" /> <ClCompile Include="SourceFiles\dropdown.cpp" />
@ -1355,6 +1368,20 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/abstractbox.h" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui"</Command> <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/abstractbox.h" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui"</Command>
</CustomBuild> </CustomBuild>
<CustomBuild Include="SourceFiles\boxes\stickersetbox.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">Moc%27ing stickersetbox.h...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/stickersetbox.h" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing stickersetbox.h...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/stickersetbox.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Moc%27ing stickersetbox.h...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/stickersetbox.h" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui"</Command>
</CustomBuild>
<ClInclude Include="SourceFiles\config.h" /> <ClInclude Include="SourceFiles\config.h" />
<CustomBuild Include="SourceFiles\gui\animation.h"> <CustomBuild Include="SourceFiles\gui\animation.h">
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing animation.h...</Message> <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing animation.h...</Message>

View File

@ -879,6 +879,18 @@
<ClCompile Include="SourceFiles\structs.cpp"> <ClCompile Include="SourceFiles\structs.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="GeneratedFiles\Deploy\moc_stickersetbox.cpp">
<Filter>Generated Files\Deploy</Filter>
</ClCompile>
<ClCompile Include="GeneratedFiles\Debug\moc_stickersetbox.cpp">
<Filter>Generated Files\Debug</Filter>
</ClCompile>
<ClCompile Include="GeneratedFiles\Release\moc_stickersetbox.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
<ClCompile Include="SourceFiles\boxes\stickersetbox.cpp">
<Filter>boxes</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="SourceFiles\stdafx.h"> <ClInclude Include="SourceFiles\stdafx.h">
@ -1168,6 +1180,9 @@
<CustomBuild Include="SourceFiles\intro\intropwdcheck.h"> <CustomBuild Include="SourceFiles\intro\intropwdcheck.h">
<Filter>intro</Filter> <Filter>intro</Filter>
</CustomBuild> </CustomBuild>
<CustomBuild Include="SourceFiles\boxes\stickersetbox.h">
<Filter>boxes</Filter>
</CustomBuild>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="SourceFiles\art\icon256.ico" /> <Image Include="SourceFiles\art\icon256.ico" />