mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
saved gifs done
This commit is contained in:
parent
dcbdd0b0a5
commit
9a1798f043
49 changed files with 2456 additions and 592 deletions
|
@ -582,6 +582,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_media_auto_gif" = "Automatic GIF download";
|
||||
"lng_media_auto_private_chats" = "Private chats";
|
||||
"lng_media_auto_groups" = "Groups and channels";
|
||||
"lng_media_auto_play" = "Autoplay";
|
||||
|
||||
"lng_emoji_category0" = "Frequently used";
|
||||
"lng_emoji_category1" = "People";
|
||||
|
@ -596,6 +597,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_switch_stickers_gifs" = "GIFs & Stickers";
|
||||
"lng_switch_emoji" = "Emoji";
|
||||
|
||||
"lng_saved_gifs" = "Saved GIFs";
|
||||
|
||||
"lng_box_remove" = "Remove";
|
||||
|
||||
"lng_custom_stickers" = "Custom stickers";
|
||||
|
@ -724,6 +727,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_context_delete_file" = "Delete File";
|
||||
"lng_context_close_file" = "Close File";
|
||||
"lng_context_copy_text" = "Copy Text";
|
||||
"lng_context_save_gif" = "Save GIF";
|
||||
"lng_context_to_msg" = "Go To Message";
|
||||
"lng_context_reply_msg" = "Reply";
|
||||
"lng_context_forward_msg" = "Forward Message";
|
||||
|
|
|
@ -1865,6 +1865,8 @@ emojiObjectsActive: sprite(308px, 264px, 21px, 22px);
|
|||
emojiSymbolsOver: sprite(84px, 196px, 21px, 22px);
|
||||
emojiSymbolsActive: sprite(287px, 286px, 21px, 22px);
|
||||
stickersSettings: sprite(140px, 124px, 21px, 22px);
|
||||
savedGifsOver: sprite(329px, 286px, 21px, 22px);
|
||||
savedGifsActive: sprite(350px, 286px, 21px, 22px);
|
||||
|
||||
emojiPanCategories: #f7f7f7;
|
||||
|
||||
|
@ -1989,6 +1991,11 @@ stickerPreviewDuration: 150;
|
|||
stickerPreviewBg: #FFFFFFB0;
|
||||
stickerPreviewMin: 0.1;
|
||||
|
||||
savedGifsLeft: 15px;
|
||||
savedGifsSkip: 3px;
|
||||
savedGifHeight: 96px;
|
||||
savedGifMinWidth: 64px;
|
||||
|
||||
verifiedCheckProfile: sprite(285px, 235px, 18px, 18px);
|
||||
verifiedCheckProfilePos: point(7px, 6px);
|
||||
verifiedCheck: sprite(285px, 221px, 14px, 14px);
|
||||
|
@ -2020,7 +2027,7 @@ botKbScroll: flatScroll(solidScroll) {
|
|||
width: 10px;
|
||||
}
|
||||
|
||||
minPhotoSize: 104px;
|
||||
minPhotoSize: 100px;
|
||||
maxMediaSize: 420px;
|
||||
maxStickerSize: 256px;
|
||||
maxGifSize: 320px;
|
||||
|
|
|
@ -915,5 +915,5 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &msgs
|
|||
}
|
||||
|
||||
ApiWrap::~ApiWrap() {
|
||||
App::deinitMedia(false);
|
||||
App::clearHistories();
|
||||
}
|
||||
|
|
|
@ -45,21 +45,14 @@ namespace {
|
|||
typedef QMap<PeerData*, bool> UpdatedPeers;
|
||||
UpdatedPeers updatedPeers;
|
||||
|
||||
typedef QHash<PhotoId, PhotoData*> PhotosData;
|
||||
PhotosData photosData;
|
||||
|
||||
typedef QHash<VideoId, VideoData*> VideosData;
|
||||
VideosData videosData;
|
||||
|
||||
typedef QHash<AudioId, AudioData*> AudiosData;
|
||||
AudiosData audiosData;
|
||||
DocumentsData documentsData;
|
||||
|
||||
typedef QHash<QString, ImageLinkData*> ImageLinksData;
|
||||
ImageLinksData imageLinksData;
|
||||
|
||||
typedef QHash<DocumentId, DocumentData*> DocumentsData;
|
||||
DocumentsData documentsData;
|
||||
|
||||
typedef QHash<WebPageId, WebPageData*> WebPagesData;
|
||||
WebPagesData webPagesData;
|
||||
|
||||
|
@ -918,11 +911,41 @@ namespace App {
|
|||
|
||||
existing->setViewsCount(m.has_views() ? m.vviews.v : -1);
|
||||
|
||||
return !existing->detached();
|
||||
if (!existing->detached()) {
|
||||
App::checkSavedGif(existing);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void addSavedGif(DocumentData *doc) {
|
||||
SavedGifs &saved(cRefSavedGifs());
|
||||
int32 index = saved.indexOf(doc);
|
||||
if (index) {
|
||||
if (index > 0) saved.remove(index);
|
||||
saved.push_front(doc);
|
||||
if (saved.size() > cSavedGifsLimit()) saved.pop_back();
|
||||
Local::writeSavedGifs();
|
||||
|
||||
if (App::main()) emit App::main()->savedGifsUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
void checkSavedGif(HistoryItem *item) {
|
||||
if (!item->toHistoryForwarded() && item->out()) {
|
||||
if (HistoryMedia *media = item->getMedia()) {
|
||||
if (DocumentData *doc = media->getDocument()) {
|
||||
if (doc->type == AnimatedDocument && doc->mime.toLower() == qstr("video/mp4")) {
|
||||
addSavedGif(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type) {
|
||||
QMap<uint64, int32> msgsIds;
|
||||
for (int32 i = 0, l = msgs.size(); i < l; ++i) {
|
||||
|
@ -1417,9 +1440,9 @@ namespace App {
|
|||
}
|
||||
|
||||
PhotoData *photo(const PhotoId &photo) {
|
||||
PhotosData::const_iterator i = photosData.constFind(photo);
|
||||
if (i == photosData.cend()) {
|
||||
i = photosData.insert(photo, new PhotoData(photo));
|
||||
PhotosData::const_iterator i = ::photosData.constFind(photo);
|
||||
if (i == ::photosData.cend()) {
|
||||
i = ::photosData.insert(photo, new PhotoData(photo));
|
||||
}
|
||||
return i.value();
|
||||
}
|
||||
|
@ -1427,9 +1450,9 @@ namespace App {
|
|||
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) {
|
||||
if (convert) {
|
||||
if (convert->id != photo) {
|
||||
PhotosData::iterator i = photosData.find(convert->id);
|
||||
if (i != photosData.cend() && i.value() == convert) {
|
||||
photosData.erase(i);
|
||||
PhotosData::iterator i = ::photosData.find(convert->id);
|
||||
if (i != ::photosData.cend() && i.value() == convert) {
|
||||
::photosData.erase(i);
|
||||
}
|
||||
convert->id = photo;
|
||||
delete convert->uploadingData;
|
||||
|
@ -1443,16 +1466,16 @@ namespace App {
|
|||
convert->full = full;
|
||||
}
|
||||
}
|
||||
PhotosData::const_iterator i = photosData.constFind(photo);
|
||||
PhotosData::const_iterator i = ::photosData.constFind(photo);
|
||||
PhotoData *result;
|
||||
LastPhotosMap::iterator inLastIter = lastPhotosMap.end();
|
||||
if (i == photosData.cend()) {
|
||||
if (i == ::photosData.cend()) {
|
||||
if (convert) {
|
||||
result = convert;
|
||||
} else {
|
||||
result = new PhotoData(photo, access, date, thumb, medium, full);
|
||||
}
|
||||
photosData.insert(photo, result);
|
||||
::photosData.insert(photo, result);
|
||||
} else {
|
||||
result = i.value();
|
||||
if (result != convert && !result->date && date) {
|
||||
|
@ -1479,9 +1502,9 @@ namespace App {
|
|||
}
|
||||
|
||||
VideoData *video(const VideoId &video) {
|
||||
VideosData::const_iterator i = videosData.constFind(video);
|
||||
if (i == videosData.cend()) {
|
||||
i = videosData.insert(video, new VideoData(video));
|
||||
VideosData::const_iterator i = ::videosData.constFind(video);
|
||||
if (i == ::videosData.cend()) {
|
||||
i = ::videosData.insert(video, new VideoData(video));
|
||||
}
|
||||
return i.value();
|
||||
}
|
||||
|
@ -1489,9 +1512,9 @@ namespace App {
|
|||
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) {
|
||||
if (convert) {
|
||||
if (convert->id != video) {
|
||||
VideosData::iterator i = videosData.find(convert->id);
|
||||
if (i != videosData.cend() && i.value() == convert) {
|
||||
videosData.erase(i);
|
||||
VideosData::iterator i = ::videosData.find(convert->id);
|
||||
if (i != ::videosData.cend() && i.value() == convert) {
|
||||
::videosData.erase(i);
|
||||
}
|
||||
convert->id = video;
|
||||
convert->status = FileReady;
|
||||
|
@ -1507,15 +1530,15 @@ namespace App {
|
|||
convert->size = size;
|
||||
}
|
||||
}
|
||||
VideosData::const_iterator i = videosData.constFind(video);
|
||||
VideosData::const_iterator i = ::videosData.constFind(video);
|
||||
VideoData *result;
|
||||
if (i == videosData.cend()) {
|
||||
if (i == ::videosData.cend()) {
|
||||
if (convert) {
|
||||
result = convert;
|
||||
} else {
|
||||
result = new VideoData(video, access, date, duration, w, h, thumb, dc, size);
|
||||
}
|
||||
videosData.insert(video, result);
|
||||
::videosData.insert(video, result);
|
||||
} else {
|
||||
result = i.value();
|
||||
if (result != convert && !result->date && date) {
|
||||
|
@ -1533,9 +1556,9 @@ namespace App {
|
|||
}
|
||||
|
||||
AudioData *audio(const AudioId &audio) {
|
||||
AudiosData::const_iterator i = audiosData.constFind(audio);
|
||||
if (i == audiosData.cend()) {
|
||||
i = audiosData.insert(audio, new AudioData(audio));
|
||||
AudiosData::const_iterator i = ::audiosData.constFind(audio);
|
||||
if (i == ::audiosData.cend()) {
|
||||
i = ::audiosData.insert(audio, new AudioData(audio));
|
||||
}
|
||||
return i.value();
|
||||
}
|
||||
|
@ -1543,9 +1566,9 @@ namespace App {
|
|||
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) {
|
||||
if (convert) {
|
||||
if (convert->id != audio) {
|
||||
AudiosData::iterator i = audiosData.find(convert->id);
|
||||
if (i != audiosData.cend() && i.value() == convert) {
|
||||
audiosData.erase(i);
|
||||
AudiosData::iterator i = ::audiosData.find(convert->id);
|
||||
if (i != ::audiosData.cend() && i.value() == convert) {
|
||||
::audiosData.erase(i);
|
||||
}
|
||||
convert->id = audio;
|
||||
convert->status = FileReady;
|
||||
|
@ -1559,15 +1582,15 @@ namespace App {
|
|||
convert->size = size;
|
||||
}
|
||||
}
|
||||
AudiosData::const_iterator i = audiosData.constFind(audio);
|
||||
AudiosData::const_iterator i = ::audiosData.constFind(audio);
|
||||
AudioData *result;
|
||||
if (i == audiosData.cend()) {
|
||||
if (i == ::audiosData.cend()) {
|
||||
if (convert) {
|
||||
result = convert;
|
||||
} else {
|
||||
result = new AudioData(audio, access, date, mime, duration, dc, size);
|
||||
}
|
||||
audiosData.insert(audio, result);
|
||||
::audiosData.insert(audio, result);
|
||||
} else {
|
||||
result = i.value();
|
||||
if (result != convert && !result->date && date) {
|
||||
|
@ -1583,9 +1606,9 @@ namespace App {
|
|||
}
|
||||
|
||||
DocumentData *document(const DocumentId &document) {
|
||||
DocumentsData::const_iterator i = documentsData.constFind(document);
|
||||
if (i == documentsData.cend()) {
|
||||
i = documentsData.insert(document, new DocumentData(document));
|
||||
DocumentsData::const_iterator i = ::documentsData.constFind(document);
|
||||
if (i == ::documentsData.cend()) {
|
||||
i = ::documentsData.insert(document, new DocumentData(document));
|
||||
}
|
||||
return i.value();
|
||||
}
|
||||
|
@ -1594,9 +1617,9 @@ namespace App {
|
|||
bool sentSticker = false;
|
||||
if (convert) {
|
||||
if (convert->id != document) {
|
||||
DocumentsData::iterator i = documentsData.find(convert->id);
|
||||
if (i != documentsData.cend() && i.value() == convert) {
|
||||
documentsData.erase(i);
|
||||
DocumentsData::iterator i = ::documentsData.find(convert->id);
|
||||
if (i != ::documentsData.cend() && i.value() == convert) {
|
||||
::documentsData.erase(i);
|
||||
}
|
||||
convert->id = document;
|
||||
convert->status = FileReady;
|
||||
|
@ -1636,9 +1659,9 @@ namespace App {
|
|||
Local::writeFileLocation(mediaKey(DocumentFileLocation, convert->dc, convert->id), loc);
|
||||
}
|
||||
}
|
||||
DocumentsData::const_iterator i = documentsData.constFind(document);
|
||||
DocumentsData::const_iterator i = ::documentsData.constFind(document);
|
||||
DocumentData *result;
|
||||
if (i == documentsData.cend()) {
|
||||
if (i == ::documentsData.cend()) {
|
||||
if (convert) {
|
||||
result = convert;
|
||||
} else {
|
||||
|
@ -1646,7 +1669,7 @@ namespace App {
|
|||
result->recountIsImage();
|
||||
if (result->sticker()) result->sticker()->loc = thumbLocation;
|
||||
}
|
||||
documentsData.insert(document, result);
|
||||
::documentsData.insert(document, result);
|
||||
} else {
|
||||
result = i.value();
|
||||
if (result != convert) {
|
||||
|
@ -1776,16 +1799,16 @@ namespace App {
|
|||
void forgetMedia() {
|
||||
lastPhotos.clear();
|
||||
lastPhotosMap.clear();
|
||||
for (PhotosData::const_iterator i = photosData.cbegin(), e = photosData.cend(); i != e; ++i) {
|
||||
for (PhotosData::const_iterator i = ::photosData.cbegin(), e = ::photosData.cend(); i != e; ++i) {
|
||||
i.value()->forget();
|
||||
}
|
||||
for (VideosData::const_iterator i = videosData.cbegin(), e = videosData.cend(); i != e; ++i) {
|
||||
for (VideosData::const_iterator i = ::videosData.cbegin(), e = ::videosData.cend(); i != e; ++i) {
|
||||
i.value()->forget();
|
||||
}
|
||||
for (AudiosData::const_iterator i = audiosData.cbegin(), e = audiosData.cend(); i != e; ++i) {
|
||||
for (AudiosData::const_iterator i = ::audiosData.cbegin(), e = ::audiosData.cend(); i != e; ++i) {
|
||||
i.value()->forget();
|
||||
}
|
||||
for (DocumentsData::const_iterator i = documentsData.cbegin(), e = documentsData.cend(); i != e; ++i) {
|
||||
for (DocumentsData::const_iterator i = ::documentsData.cbegin(), e = ::documentsData.cend(); i != e; ++i) {
|
||||
i.value()->forget();
|
||||
}
|
||||
for (ImageLinksData::const_iterator i = imageLinksData.cbegin(), e = imageLinksData.cend(); i != e; ++i) {
|
||||
|
@ -1933,32 +1956,33 @@ namespace App {
|
|||
delete *i;
|
||||
}
|
||||
peersData.clear();
|
||||
for (PhotosData::const_iterator i = photosData.cbegin(), e = photosData.cend(); i != e; ++i) {
|
||||
for (PhotosData::const_iterator i = ::photosData.cbegin(), e = ::photosData.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
photosData.clear();
|
||||
for (VideosData::const_iterator i = videosData.cbegin(), e = videosData.cend(); i != e; ++i) {
|
||||
::photosData.clear();
|
||||
for (VideosData::const_iterator i = ::videosData.cbegin(), e = ::videosData.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
videosData.clear();
|
||||
for (AudiosData::const_iterator i = audiosData.cbegin(), e = audiosData.cend(); i != e; ++i) {
|
||||
::videosData.clear();
|
||||
for (AudiosData::const_iterator i = ::audiosData.cbegin(), e = ::audiosData.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
audiosData.clear();
|
||||
for (DocumentsData::const_iterator i = documentsData.cbegin(), e = documentsData.cend(); i != e; ++i) {
|
||||
::audiosData.clear();
|
||||
for (DocumentsData::const_iterator i = ::documentsData.cbegin(), e = ::documentsData.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
documentsData.clear();
|
||||
::documentsData.clear();
|
||||
for (WebPagesData::const_iterator i = webPagesData.cbegin(), e = webPagesData.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
webPagesData.clear();
|
||||
if (api()) api()->clearWebPageRequests();
|
||||
cSetRecentStickers(RecentStickerPack());
|
||||
cSetStickersHash(0);
|
||||
cSetStickerSets(StickerSets());
|
||||
cSetStickerSetsOrder(StickerSetsOrder());
|
||||
cSetLastStickersUpdate(0);
|
||||
cSetSavedGifs(SavedGifs());
|
||||
cSetLastSavedGifsUpdate(0);
|
||||
cSetReportSpamStatuses(ReportSpamStatuses());
|
||||
::photoItems.clear();
|
||||
::videoItems.clear();
|
||||
|
@ -2057,7 +2081,6 @@ namespace App {
|
|||
}
|
||||
|
||||
void initMedia() {
|
||||
deinitMedia(false);
|
||||
audioInit();
|
||||
|
||||
if (!::monofont) {
|
||||
|
@ -2119,48 +2142,47 @@ namespace App {
|
|||
prepareCorners(MessageInSelectedCorners, st::msgRadius, st::msgInBgSelected, &st::msgInShadowSelected);
|
||||
prepareCorners(MessageOutCorners, st::msgRadius, st::msgOutBg, &st::msgOutShadow);
|
||||
prepareCorners(MessageOutSelectedCorners, st::msgRadius, st::msgOutBgSelected, &st::msgOutShadowSelected);
|
||||
|
||||
}
|
||||
|
||||
void deinitMedia(bool completely) {
|
||||
void clearHistories() {
|
||||
textlnkOver(TextLinkPtr());
|
||||
textlnkDown(TextLinkPtr());
|
||||
|
||||
histories().clear();
|
||||
|
||||
if (completely) {
|
||||
audioFinish();
|
||||
|
||||
delete ::sprite;
|
||||
::sprite = 0;
|
||||
delete ::emoji;
|
||||
::emoji = 0;
|
||||
delete ::emojiLarge;
|
||||
::emojiLarge = 0;
|
||||
for (int32 j = 0; j < 4; ++j) {
|
||||
for (int32 i = 0; i < RoundCornersCount; ++i) {
|
||||
delete ::corners[i].p[j]; ::corners[i].p[j] = 0;
|
||||
}
|
||||
delete ::cornersMask[j]; ::cornersMask[j] = 0;
|
||||
}
|
||||
for (CornersMap::const_iterator i = ::cornersMap.cbegin(), e = ::cornersMap.cend(); i != e; ++i) {
|
||||
for (int32 j = 0; j < 4; ++j) {
|
||||
delete i->p[j];
|
||||
}
|
||||
}
|
||||
::cornersMap.clear();
|
||||
mainEmojiMap.clear();
|
||||
otherEmojiMap.clear();
|
||||
|
||||
clearAllImages();
|
||||
} else {
|
||||
clearStorageImages();
|
||||
cSetServerBackgrounds(WallPapers());
|
||||
}
|
||||
|
||||
clearStorageImages();
|
||||
cSetServerBackgrounds(WallPapers());
|
||||
|
||||
serviceImageCacheSize = imageCacheSize();
|
||||
}
|
||||
|
||||
void deinitMedia() {
|
||||
audioFinish();
|
||||
|
||||
delete ::sprite;
|
||||
::sprite = 0;
|
||||
delete ::emoji;
|
||||
::emoji = 0;
|
||||
delete ::emojiLarge;
|
||||
::emojiLarge = 0;
|
||||
for (int32 j = 0; j < 4; ++j) {
|
||||
for (int32 i = 0; i < RoundCornersCount; ++i) {
|
||||
delete ::corners[i].p[j]; ::corners[i].p[j] = 0;
|
||||
}
|
||||
delete ::cornersMask[j]; ::cornersMask[j] = 0;
|
||||
}
|
||||
for (CornersMap::const_iterator i = ::cornersMap.cbegin(), e = ::cornersMap.cend(); i != e; ++i) {
|
||||
for (int32 j = 0; j < 4; ++j) {
|
||||
delete i->p[j];
|
||||
}
|
||||
}
|
||||
::cornersMap.clear();
|
||||
mainEmojiMap.clear();
|
||||
otherEmojiMap.clear();
|
||||
|
||||
clearAllImages();
|
||||
}
|
||||
|
||||
void hoveredItem(HistoryItem *item) {
|
||||
::hoveredItem = item;
|
||||
}
|
||||
|
@ -2362,6 +2384,10 @@ namespace App {
|
|||
return ::photoItems;
|
||||
}
|
||||
|
||||
const PhotosData &photosData() {
|
||||
return ::photosData;
|
||||
}
|
||||
|
||||
void regVideoItem(VideoData *data, HistoryItem *item) {
|
||||
::videoItems[data].insert(item, NullType());
|
||||
}
|
||||
|
@ -2374,6 +2400,10 @@ namespace App {
|
|||
return ::videoItems;
|
||||
}
|
||||
|
||||
const VideosData &videosData() {
|
||||
return ::videosData;
|
||||
}
|
||||
|
||||
void regAudioItem(AudioData *data, HistoryItem *item) {
|
||||
::audioItems[data].insert(item, NullType());
|
||||
}
|
||||
|
@ -2386,6 +2416,10 @@ namespace App {
|
|||
return ::audioItems;
|
||||
}
|
||||
|
||||
const AudiosData &audiosData() {
|
||||
return ::audiosData;
|
||||
}
|
||||
|
||||
void regDocumentItem(DocumentData *data, HistoryItem *item) {
|
||||
::documentItems[data].insert(item, NullType());
|
||||
}
|
||||
|
@ -2398,6 +2432,10 @@ namespace App {
|
|||
return ::documentItems;
|
||||
}
|
||||
|
||||
const DocumentsData &documentsData() {
|
||||
return ::documentsData;
|
||||
}
|
||||
|
||||
void regWebPageItem(WebPageData *data, HistoryItem *item) {
|
||||
::webPageItems[data].insert(item, NullType());
|
||||
}
|
||||
|
@ -2436,9 +2474,10 @@ namespace App {
|
|||
|
||||
void stopGifItems() {
|
||||
if (!::gifItems.isEmpty()) {
|
||||
if (HistoryItem *playing = ::gifItems.begin().value()) {
|
||||
if (playing->getMedia()) {
|
||||
playing->getMedia()->stopInline(playing);
|
||||
GifItems gifs = ::gifItems;
|
||||
for (GifItems::const_iterator i = gifs.cbegin(), e = gifs.cend(); i != e; ++i) {
|
||||
if (HistoryMedia *media = i.value()->getMedia()) {
|
||||
media->stopInline(i.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,13 +35,19 @@ class FileUploader;
|
|||
#include "layout.h"
|
||||
|
||||
typedef QMap<HistoryItem*, NullType> HistoryItemsMap;
|
||||
typedef QMap<PhotoData*, HistoryItemsMap> PhotoItems;
|
||||
typedef QMap<VideoData*, HistoryItemsMap> VideoItems;
|
||||
typedef QMap<AudioData*, HistoryItemsMap> AudioItems;
|
||||
typedef QMap<DocumentData*, HistoryItemsMap> DocumentItems;
|
||||
typedef QMap<WebPageData*, HistoryItemsMap> WebPageItems;
|
||||
typedef QMap<int32, HistoryItemsMap> SharedContactItems;
|
||||
typedef QMap<ClipReader*, HistoryItem*> GifItems;
|
||||
typedef QHash<PhotoData*, HistoryItemsMap> PhotoItems;
|
||||
typedef QHash<VideoData*, HistoryItemsMap> VideoItems;
|
||||
typedef QHash<AudioData*, HistoryItemsMap> AudioItems;
|
||||
typedef QHash<DocumentData*, HistoryItemsMap> DocumentItems;
|
||||
typedef QHash<WebPageData*, HistoryItemsMap> WebPageItems;
|
||||
typedef QHash<int32, HistoryItemsMap> SharedContactItems;
|
||||
typedef QHash<ClipReader*, HistoryItem*> GifItems;
|
||||
|
||||
typedef QHash<PhotoId, PhotoData*> PhotosData;
|
||||
typedef QHash<VideoId, VideoData*> VideosData;
|
||||
typedef QHash<AudioId, AudioData*> AudiosData;
|
||||
typedef QHash<DocumentId, DocumentData*> DocumentsData;
|
||||
|
||||
struct ReplyMarkup {
|
||||
ReplyMarkup(int32 flags = 0) : flags(flags) {
|
||||
}
|
||||
|
@ -79,6 +85,8 @@ namespace App {
|
|||
void feedChatAdmins(const MTPDupdateChatAdmins &d, bool emitPeerUpdated = true);
|
||||
void feedParticipantAdmin(const MTPDupdateChatParticipantAdmin &d, bool emitPeerUpdated = true);
|
||||
bool checkEntitiesAndViewsUpdate(const MTPDmessage &m); // returns true if item found and it is not detached
|
||||
void addSavedGif(DocumentData *doc);
|
||||
void checkSavedGif(HistoryItem *item);
|
||||
void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type);
|
||||
void feedMsgs(const MTPVector<MTPMessage> &msgs, NewMessageType type);
|
||||
void feedInboxRead(const PeerId &peer, MsgId upTo);
|
||||
|
@ -184,8 +192,10 @@ namespace App {
|
|||
const QPixmap &emojiLarge();
|
||||
const QPixmap &emojiSingle(EmojiPtr emoji, int32 fontHeight);
|
||||
|
||||
void clearHistories();
|
||||
|
||||
void initMedia();
|
||||
void deinitMedia(bool completely = true);
|
||||
void deinitMedia();
|
||||
void playSound();
|
||||
|
||||
void checkImageCacheSize();
|
||||
|
@ -202,18 +212,22 @@ namespace App {
|
|||
void regPhotoItem(PhotoData *data, HistoryItem *item);
|
||||
void unregPhotoItem(PhotoData *data, HistoryItem *item);
|
||||
const PhotoItems &photoItems();
|
||||
const PhotosData &photosData();
|
||||
|
||||
void regVideoItem(VideoData *data, HistoryItem *item);
|
||||
void unregVideoItem(VideoData *data, HistoryItem *item);
|
||||
const VideoItems &videoItems();
|
||||
const VideosData &videosData();
|
||||
|
||||
void regAudioItem(AudioData *data, HistoryItem *item);
|
||||
void unregAudioItem(AudioData*data, HistoryItem *item);
|
||||
const AudioItems &audioItems();
|
||||
const AudiosData &audiosData();
|
||||
|
||||
void regDocumentItem(DocumentData *data, HistoryItem *item);
|
||||
void unregDocumentItem(DocumentData *data, HistoryItem *item);
|
||||
const DocumentItems &documentItems();
|
||||
const DocumentsData &documentsData();
|
||||
|
||||
void regWebPageItem(WebPageData *data, HistoryItem *item);
|
||||
void unregWebPageItem(WebPageData *data, HistoryItem *item);
|
||||
|
@ -276,25 +290,4 @@ namespace App {
|
|||
|
||||
};
|
||||
|
||||
inline int32 stickersCountHash(bool checkOfficial = false) {
|
||||
uint32 acc = 0;
|
||||
bool foundOfficial = false, foundBad = false;;
|
||||
const StickerSets &sets(cStickerSets());
|
||||
const StickerSetsOrder &order(cStickerSetsOrder());
|
||||
for (StickerSetsOrder::const_iterator i = order.cbegin(), e = order.cend(); i != e; ++i) {
|
||||
StickerSets::const_iterator j = sets.constFind(*i);
|
||||
if (j != sets.cend()) {
|
||||
if (j->id == 0) {
|
||||
foundBad = true;
|
||||
} else if (j->flags & MTPDstickerSet::flag_official) {
|
||||
foundOfficial = true;
|
||||
}
|
||||
if (!(j->flags & MTPDstickerSet::flag_disabled)) {
|
||||
acc = (acc * 20261) + j->hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (!checkOfficial || (!foundBad && foundOfficial)) ? int32(acc & 0x7FFFFFFF) : 0;
|
||||
}
|
||||
|
||||
#include "facades.h"
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 177 KiB |
Binary file not shown.
Before Width: | Height: | Size: 237 KiB After Width: | Height: | Size: 240 KiB |
|
@ -226,11 +226,12 @@ AutoDownloadBox::AutoDownloadBox() : AbstractBox(st::boxWidth)
|
|||
, _audioGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadAudio() & dbiadNoGroups))
|
||||
, _gifPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadGif() & dbiadNoPrivate))
|
||||
, _gifGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadGif() & dbiadNoGroups))
|
||||
, _gifPlay(this, lang(lng_media_auto_play), cAutoPlayGif())
|
||||
, _sectionHeight(st::boxTitleHeight + 2 * (st::defaultCheckbox.height + st::setLittleSkip))
|
||||
, _save(this, lang(lng_connection_save), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
|
||||
|
||||
setMaxHeight(3 * _sectionHeight + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom());
|
||||
setMaxHeight(3 * _sectionHeight + st::setLittleSkip + _gifPlay.height() + st::setLittleSkip + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom());
|
||||
|
||||
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
|
@ -245,6 +246,7 @@ void AutoDownloadBox::hideAll() {
|
|||
_audioGroups.hide();
|
||||
_gifPrivate.hide();
|
||||
_gifGroups.hide();
|
||||
_gifPlay.hide();
|
||||
|
||||
_save.hide();
|
||||
_cancel.hide();
|
||||
|
@ -257,6 +259,7 @@ void AutoDownloadBox::showAll() {
|
|||
_audioGroups.show();
|
||||
_gifPrivate.show();
|
||||
_gifGroups.show();
|
||||
_gifPlay.show();
|
||||
|
||||
_save.show();
|
||||
_cancel.show();
|
||||
|
@ -282,15 +285,60 @@ void AutoDownloadBox::resizeEvent(QResizeEvent *e) {
|
|||
|
||||
_gifPrivate.moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + st::boxTitleHeight + st::setLittleSkip);
|
||||
_gifGroups.moveToLeft(st::boxTitlePosition.x(), _gifPrivate.y() + _gifPrivate.height() + st::setLittleSkip);
|
||||
_gifPlay.moveToLeft(st::boxTitlePosition.x(), _gifGroups.y() + _gifGroups.height() + st::setLittleSkip);
|
||||
|
||||
_save.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save.height());
|
||||
_cancel.moveToRight(st::boxButtonPadding.right() + _save.width() + st::boxButtonPadding.left(), _save.y());
|
||||
}
|
||||
|
||||
void AutoDownloadBox::onSave() {
|
||||
cSetAutoDownloadPhoto((_photoPrivate.checked() ? 0 : dbiadNoPrivate) | (_photoGroups.checked() ? 0 : dbiadNoGroups));
|
||||
cSetAutoDownloadAudio((_audioPrivate.checked() ? 0 : dbiadNoPrivate) | (_audioGroups.checked() ? 0 : dbiadNoGroups));
|
||||
cSetAutoDownloadGif((_gifPrivate.checked() ? 0 : dbiadNoPrivate) | (_gifGroups.checked() ? 0 : dbiadNoGroups));
|
||||
Local::writeUserSettings();
|
||||
bool changed = false;
|
||||
int32 autoDownloadPhoto = (_photoPrivate.checked() ? 0 : dbiadNoPrivate) | (_photoGroups.checked() ? 0 : dbiadNoGroups);
|
||||
if (cAutoDownloadPhoto() != autoDownloadPhoto) {
|
||||
bool enabledPrivate = ((cAutoDownloadPhoto() & dbiadNoPrivate) && !(autoDownloadPhoto & dbiadNoPrivate));
|
||||
bool enabledGroups = ((cAutoDownloadPhoto() & dbiadNoGroups) && !(autoDownloadPhoto & dbiadNoGroups));
|
||||
cSetAutoDownloadPhoto(autoDownloadPhoto);
|
||||
if (enabledPrivate || enabledGroups) {
|
||||
const PhotosData &data(App::photosData());
|
||||
for (PhotosData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
int32 autoDownloadAudio = (_audioPrivate.checked() ? 0 : dbiadNoPrivate) | (_audioGroups.checked() ? 0 : dbiadNoGroups);
|
||||
if (cAutoDownloadAudio() != autoDownloadAudio) {
|
||||
bool enabledPrivate = ((cAutoDownloadAudio() & dbiadNoPrivate) && !(autoDownloadAudio & dbiadNoPrivate));
|
||||
bool enabledGroups = ((cAutoDownloadAudio() & dbiadNoGroups) && !(autoDownloadAudio & dbiadNoGroups));
|
||||
cSetAutoDownloadAudio(autoDownloadAudio);
|
||||
if (enabledPrivate || enabledGroups) {
|
||||
const AudiosData &data(App::audiosData());
|
||||
for (AudiosData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
int32 autoDownloadGif = (_gifPrivate.checked() ? 0 : dbiadNoPrivate) | (_gifGroups.checked() ? 0 : dbiadNoGroups);
|
||||
if (cAutoDownloadGif() != autoDownloadGif) {
|
||||
bool enabledPrivate = ((cAutoDownloadGif() & dbiadNoPrivate) && !(autoDownloadGif & dbiadNoPrivate));
|
||||
bool enabledGroups = ((cAutoDownloadGif() & dbiadNoGroups) && !(autoDownloadGif & dbiadNoGroups));
|
||||
cSetAutoDownloadGif(autoDownloadGif);
|
||||
if (enabledPrivate || enabledGroups) {
|
||||
const DocumentsData &data(App::documentsData());
|
||||
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
if (cAutoPlayGif() != _gifPlay.checked()) {
|
||||
cSetAutoPlayGif(_gifPlay.checked());
|
||||
if (!cAutoPlayGif()) {
|
||||
App::stopGifItems();
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
if (changed) Local::writeUserSettings();
|
||||
onClose();
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ private:
|
|||
|
||||
Checkbox _photoPrivate, _photoGroups;
|
||||
Checkbox _audioPrivate, _audioGroups;
|
||||
Checkbox _gifPrivate, _gifGroups;
|
||||
Checkbox _gifPrivate, _gifGroups, _gifPlay;
|
||||
|
||||
int32 _sectionHeight;
|
||||
|
||||
|
|
|
@ -112,7 +112,6 @@ void StickerSetInner::installDone(const MTPBool &result) {
|
|||
sets.erase(custom);
|
||||
}
|
||||
}
|
||||
cSetStickersHash(stickersCountHash());
|
||||
Local::writeStickers();
|
||||
emit installed(_setId);
|
||||
Ui::hideLayer();
|
||||
|
@ -892,7 +891,6 @@ void StickersBox::onSave() {
|
|||
}
|
||||
}
|
||||
|
||||
cSetStickersHash(stickersCountHash());
|
||||
Local::writeStickers();
|
||||
if (writeRecent) Local::writeUserSettings();
|
||||
emit App::main()->stickersUpdated();
|
||||
|
|
|
@ -130,6 +130,7 @@ enum {
|
|||
EmojiPanRowsPerPage = 6,
|
||||
StickerPanPerRow = 5,
|
||||
StickerPanRowsPerPage = 4,
|
||||
SavedGifsMaxPerRow = 4,
|
||||
StickersUpdateTimeout = 3600000, // update not more than once in an hour
|
||||
|
||||
SearchPeopleLimit = 5,
|
||||
|
|
|
@ -28,6 +28,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "window.h"
|
||||
#include "apiwrap.h"
|
||||
#include "mainwidget.h"
|
||||
|
||||
#include "boxes/confirmbox.h"
|
||||
#include "boxes/stickersetbox.h"
|
||||
|
@ -732,9 +733,6 @@ EmojiPanInner::EmojiPanInner() : TWidget()
|
|||
_hovers[i] = QVector<float64>(_counts[i], 0);
|
||||
}
|
||||
|
||||
_saveConfigTimer.setSingleShot(true);
|
||||
connect(&_saveConfigTimer, SIGNAL(timeout()), this, SLOT(onSaveConfig()));
|
||||
|
||||
_showPickerTimer.setSingleShot(true);
|
||||
connect(&_showPickerTimer, SIGNAL(timeout()), this, SLOT(onShowPicker()));
|
||||
connect(&_picker, SIGNAL(emojiSelected(EmojiPtr)), this, SLOT(onColorSelected(EmojiPtr)));
|
||||
|
@ -937,15 +935,11 @@ void EmojiPanInner::selectEmoji(EmojiPtr emoji) {
|
|||
qSwap(*i, *(i - 1));
|
||||
}
|
||||
}
|
||||
_saveConfigTimer.start(SaveRecentEmojisTimeout);
|
||||
emit saveConfigDelayed(SaveRecentEmojisTimeout);
|
||||
|
||||
emit selected(emoji);
|
||||
}
|
||||
|
||||
void EmojiPanInner::onSaveConfig() {
|
||||
Local::writeUserSettings();
|
||||
}
|
||||
|
||||
void EmojiPanInner::onShowPicker() {
|
||||
int tab = (_pickerSel / MatrixRowShift), sel = _pickerSel % MatrixRowShift;
|
||||
if (tab < emojiTabCount && sel < _emojis[tab].size() && _emojis[tab][sel]->color) {
|
||||
|
@ -1219,6 +1213,7 @@ void EmojiPanInner::showEmojiPack(DBIEmojiTab packIndex) {
|
|||
StickerPanInner::StickerPanInner() : TWidget()
|
||||
, _a_selected(animation(this, &StickerPanInner::step_selected))
|
||||
, _top(0)
|
||||
, _showingGifs(cShowingSavedGifs())
|
||||
, _selected(-1)
|
||||
, _pressedSel(-1)
|
||||
, _settings(this, lang(lng_stickers_you_have))
|
||||
|
@ -1234,8 +1229,6 @@ StickerPanInner::StickerPanInner() : TWidget()
|
|||
|
||||
_previewTimer.setSingleShot(true);
|
||||
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
|
||||
|
||||
refreshStickers();
|
||||
}
|
||||
|
||||
void StickerPanInner::setMaxHeight(int32 h) {
|
||||
|
@ -1253,11 +1246,15 @@ void StickerPanInner::setScrollTop(int top) {
|
|||
|
||||
int StickerPanInner::countHeight() {
|
||||
int result = 0, minLastH = _maxHeight - st::rbEmoji.height - st::stickerPanPadding;
|
||||
for (int i = 0; i < _sets.size(); ++i) {
|
||||
int cnt = _sets.at(i).pack.size(), rows = (cnt / StickerPanPerRow) + ((cnt % StickerPanPerRow) ? 1 : 0);
|
||||
int h = st::emojiPanHeader + rows * st::stickerPanSize.height();
|
||||
if (i == _sets.size() - 1 && h < minLastH) h = minLastH;
|
||||
result += h;
|
||||
if (_showingGifs) {
|
||||
result = st::emojiPanHeader + _gifRows.count() * (st::savedGifHeight + st::savedGifsSkip) - st::savedGifsSkip;
|
||||
} else {
|
||||
for (int i = 0; i < _sets.size(); ++i) {
|
||||
int cnt = _sets.at(i).pack.size(), rows = (cnt / StickerPanPerRow) + ((cnt % StickerPanPerRow) ? 1 : 0);
|
||||
int h = st::emojiPanHeader + rows * st::stickerPanSize.height();
|
||||
if (i == _sets.size() - 1 && h < minLastH) h = minLastH;
|
||||
result += h;
|
||||
}
|
||||
}
|
||||
return qMax(minLastH, result) + st::stickerPanPadding;
|
||||
}
|
||||
|
@ -1285,8 +1282,39 @@ void StickerPanInner::paintEvent(QPaintEvent *e) {
|
|||
if (r != rect()) {
|
||||
p.setClipRect(r);
|
||||
}
|
||||
p.fillRect(r, st::white->b);
|
||||
p.fillRect(r, st::white);
|
||||
|
||||
if (_showingGifs) {
|
||||
paintSavedGifs(p, r);
|
||||
} else {
|
||||
paintStickers(p, r);
|
||||
}
|
||||
}
|
||||
|
||||
void StickerPanInner::paintSavedGifs(Painter &p, const QRect &r) {
|
||||
uint64 ms = getms();
|
||||
|
||||
int32 fromrow = floorclamp(r.y() - st::emojiPanHeader, st::savedGifHeight + st::savedGifsSkip, 0, _gifRows.size());
|
||||
int32 torow = ceilclamp(r.y() + r.height() - st::emojiPanHeader - st::savedGifsSkip, st::savedGifHeight + st::savedGifsSkip, 0, _gifRows.size());
|
||||
int32 fromx = rtl() ? (width() - r.x() - r.width()) : r.x(), tox = rtl() ? (width() - r.x()) : (r.x() + r.width());
|
||||
for (int32 row = fromrow; row < torow; ++row) {
|
||||
const GifRow &gifRow(_gifRows.at(row));
|
||||
int32 left = st::savedGifsLeft, top = st::emojiPanHeader + row * (st::savedGifHeight + st::savedGifsSkip);
|
||||
for (int32 col = 0, cols = gifRow.size(); col < cols; ++col) {
|
||||
if (left >= tox) break;
|
||||
|
||||
int32 w = gifRow.at(col)->width();
|
||||
if (left + w > fromx) {
|
||||
p.translate(left, top);
|
||||
gifRow.at(col)->paint(p, _previewShown, ms);
|
||||
p.translate(-left, -top);
|
||||
}
|
||||
left += w + st::savedGifsSkip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StickerPanInner::paintStickers(Painter &p, const QRect &r) {
|
||||
int32 fromcol = floorclamp(r.x() - st::stickerPanPadding, st::stickerPanSize.width(), 0, StickerPanPerRow);
|
||||
int32 tocol = ceilclamp(r.x() + r.width() - st::stickerPanPadding, st::stickerPanSize.width(), 0, StickerPanPerRow);
|
||||
if (rtl()) {
|
||||
|
@ -1382,6 +1410,35 @@ void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
|
|||
}
|
||||
|
||||
if (_selected < 0 || _selected != pressed) return;
|
||||
if (_showingGifs) {
|
||||
int32 row = _selected / MatrixRowShift, col = _selected % MatrixRowShift;
|
||||
bool del = (col >= SavedGifsMaxPerRow);
|
||||
if (del) col -= SavedGifsMaxPerRow;
|
||||
if (row < _gifRows.size() && col < _gifRows.at(row).size()) {
|
||||
DocumentData *doc = _gifRows.at(row).at(col)->document();
|
||||
if (del) {
|
||||
int32 index = cSavedGifs().indexOf(doc);
|
||||
if (index >= 0) {
|
||||
cRefSavedGifs().remove(index);
|
||||
Local::writeSavedGifs();
|
||||
if (App::main()) emit App::main()->savedGifsUpdated();
|
||||
|
||||
MTP::send(MTPmessages_SaveGif(MTP_inputDocument(MTP_long(doc->id), MTP_long(doc->access)), MTP_bool(true)));
|
||||
} else {
|
||||
refreshSavedGifs();
|
||||
}
|
||||
} else {
|
||||
if (doc->loaded()) {
|
||||
emit selected(doc);
|
||||
} else if (doc->loading()) {
|
||||
doc->cancel();
|
||||
} else {
|
||||
DocumentOpenLink::doOpen(doc, ActionOnLoadNone);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (_selected >= MatrixRowShift * _sets.size()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1416,7 +1473,7 @@ void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
|
|||
}
|
||||
}
|
||||
if (refresh) {
|
||||
refreshRecent();
|
||||
refreshRecentStickers();
|
||||
updateSelected();
|
||||
update();
|
||||
}
|
||||
|
@ -1448,6 +1505,20 @@ void StickerPanInner::enterFromChildEvent(QEvent *e) {
|
|||
void StickerPanInner::clearSelection(bool fast) {
|
||||
_lastMousePos = mapToGlobal(QPoint(-10, -10));
|
||||
if (fast) {
|
||||
if (_showingGifs) {
|
||||
if (_selected >= 0) {
|
||||
int32 srow = _selected / MatrixRowShift, scol = _selected % MatrixRowShift;
|
||||
bool sdel = (scol >= SavedGifsMaxPerRow);
|
||||
if (sdel) scol -= SavedGifsMaxPerRow;
|
||||
if (srow < _gifRows.size() && scol < _gifRows.at(srow).size()) {
|
||||
_gifRows.at(srow).at(scol)->notify_over(false);
|
||||
if (sdel) _gifRows.at(srow).at(scol)->notify_deleteOver(false);
|
||||
}
|
||||
setCursor(style::cur_default);
|
||||
}
|
||||
_selected = _pressedSel = -1;
|
||||
return;
|
||||
}
|
||||
for (Animations::const_iterator i = _animations.cbegin(); i != _animations.cend(); ++i) {
|
||||
int index = qAbs(i.key()) - 1, tab = (index / MatrixRowShift), sel = index % MatrixRowShift;
|
||||
_sets[tab].hovers[sel] = 0;
|
||||
|
@ -1476,28 +1547,156 @@ void StickerPanInner::clearSelection(bool fast) {
|
|||
}
|
||||
}
|
||||
|
||||
void StickerPanInner::hideFinish() {
|
||||
clearSavedGifs();
|
||||
for (GifLayouts::const_iterator i = _gifLayouts.cbegin(), e = _gifLayouts.cend(); i != e; ++i) {
|
||||
i.value()->document()->forget();
|
||||
}
|
||||
}
|
||||
|
||||
void StickerPanInner::refreshStickers() {
|
||||
clearSelection(true);
|
||||
|
||||
const StickerSets &sets(cStickerSets());
|
||||
_sets.clear(); _sets.reserve(sets.size() + 1);
|
||||
|
||||
refreshRecent(false);
|
||||
refreshRecentStickers(false);
|
||||
for (StickerSetsOrder::const_iterator i = cStickerSetsOrder().cbegin(), e = cStickerSetsOrder().cend(); i != e; ++i) {
|
||||
appendSet(*i);
|
||||
}
|
||||
|
||||
int32 h = countHeight();
|
||||
if (h != height()) resize(width(), h);
|
||||
if (!_showingGifs) {
|
||||
int32 h = countHeight();
|
||||
if (h != height()) resize(width(), h);
|
||||
|
||||
_settings.setVisible(_sets.isEmpty());
|
||||
} else {
|
||||
_settings.hide();
|
||||
}
|
||||
|
||||
_settings.setVisible(_sets.isEmpty());
|
||||
|
||||
emit refreshIcons();
|
||||
|
||||
updateSelected();
|
||||
}
|
||||
|
||||
void StickerPanInner::refreshSavedGifs() {
|
||||
clearSelection(true);
|
||||
|
||||
clearSavedGifs();
|
||||
if (_showingGifs) {
|
||||
const SavedGifs &saved(cSavedGifs());
|
||||
if (saved.isEmpty()) {
|
||||
showStickerSet(RecentStickerSetId);
|
||||
return;
|
||||
} else {
|
||||
_gifRows.reserve(saved.size());
|
||||
GifRow row;
|
||||
row.reserve(SavedGifsMaxPerRow);
|
||||
int32 maxWidth = width() - st::savedGifsLeft, sumWidth = 0, widths[SavedGifsMaxPerRow] = { 0 };
|
||||
for (SavedGifs::const_iterator i = saved.cbegin(), e = saved.cend(); i != e; ++i) {
|
||||
DocumentData *doc = *i;
|
||||
int32 w = doc->dimensions.width(), h = doc->dimensions.height();
|
||||
if ((w <= 0 || h <= 0) && !doc->thumb->isNull()) {
|
||||
w = doc->thumb->width();
|
||||
h = doc->thumb->height();
|
||||
}
|
||||
if (w <= 0 || h <= 0) continue;
|
||||
|
||||
w = w * st::savedGifHeight / h;
|
||||
widths[row.size()] = w;
|
||||
|
||||
w = qMax(w, int32(st::savedGifMinWidth));
|
||||
sumWidth += w;
|
||||
row.push_back(layoutPrepare(doc, (_gifRows.size() * MatrixRowShift) + row.size(), w));
|
||||
|
||||
if (row.size() >= SavedGifsMaxPerRow || sumWidth >= maxWidth - (row.size() - 1) * st::savedGifsSkip) {
|
||||
_gifRows.push_back(layoutGifRow(row, widths, sumWidth));
|
||||
row.clear();
|
||||
row.reserve(SavedGifsMaxPerRow);
|
||||
sumWidth = 0;
|
||||
memset(widths, 0, sizeof(widths));
|
||||
}
|
||||
}
|
||||
if (!row.isEmpty()) {
|
||||
_gifRows.push_back(row);
|
||||
}
|
||||
}
|
||||
deleteUnusedLayouts();
|
||||
|
||||
int32 h = countHeight();
|
||||
if (h != height()) resize(width(), h);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
emit refreshIcons();
|
||||
|
||||
updateSelected();
|
||||
}
|
||||
|
||||
void StickerPanInner::clearSavedGifs() {
|
||||
for (GifRows::const_iterator i = _gifRows.cbegin(), e = _gifRows.cend(); i != e; ++i) {
|
||||
for (GifRow::const_iterator j = i->cbegin(), end = i->cend(); j != end; ++j) {
|
||||
(*j)->setPosition(-1, 0);
|
||||
}
|
||||
}
|
||||
_gifRows.clear();
|
||||
}
|
||||
|
||||
void StickerPanInner::deleteUnusedLayouts() {
|
||||
if (_gifRows.isEmpty()) { // delete all
|
||||
for (GifLayouts::const_iterator i = _gifLayouts.cbegin(), e = _gifLayouts.cend(); i != e; ++i) {
|
||||
delete i.value();
|
||||
}
|
||||
_gifLayouts.clear();
|
||||
} else {
|
||||
for (GifLayouts::iterator i = _gifLayouts.begin(); i != _gifLayouts.cend();) {
|
||||
if (i.value()->position() < 0) {
|
||||
delete i.value();
|
||||
i = _gifLayouts.erase(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LayoutSavedGif *StickerPanInner::layoutPrepare(DocumentData *doc, int32 position, int32 width) {
|
||||
GifLayouts::const_iterator i = _gifLayouts.constFind(doc);
|
||||
if (i == _gifLayouts.cend()) {
|
||||
i = _gifLayouts.insert(doc, new LayoutSavedGif(doc));
|
||||
}
|
||||
i.value()->setPosition(position, width);
|
||||
return i.value();
|
||||
}
|
||||
|
||||
const StickerPanInner::GifRow &StickerPanInner::layoutGifRow(const GifRow &row, int32 *widths, int32 sumWidth) {
|
||||
int32 count = row.size();
|
||||
t_assert(count <= SavedGifsMaxPerRow);
|
||||
|
||||
int32 availw = width() - st::savedGifsLeft - st::savedGifsSkip * (count - 1);
|
||||
if (sumWidth != availw) {
|
||||
for (int32 i = 0; i < count; ++i) {
|
||||
int32 w = widths[i] * availw / sumWidth;
|
||||
int32 actualw = qMax(w, int32(st::savedGifMinWidth));
|
||||
row.at(i)->setWidth(actualw);
|
||||
|
||||
availw -= actualw;
|
||||
sumWidth -= qMax(widths[i], int32(st::savedGifMinWidth));
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
void StickerPanInner::preloadImages() {
|
||||
if (_showingGifs) {
|
||||
for (int32 row = 0, rows = _gifRows.size(); row < rows; ++row) {
|
||||
for (int32 col = 0, cols = _gifRows.at(row).size(); col < cols; ++col) {
|
||||
_gifRows.at(row).at(col)->preload();
|
||||
}
|
||||
}
|
||||
}
|
||||
uint64 ms = getms();
|
||||
for (int32 i = 0, l = _sets.size(), k = 0; i < l; ++i) {
|
||||
for (int32 j = 0, n = _sets.at(i).pack.size(); j < n; ++j) {
|
||||
|
@ -1518,6 +1717,8 @@ void StickerPanInner::preloadImages() {
|
|||
}
|
||||
|
||||
uint64 StickerPanInner::currentSet(int yOffset) const {
|
||||
if (_showingGifs) return NoneStickerSetId;
|
||||
|
||||
int y, ytill = 0;
|
||||
for (int i = 0, l = _sets.size(); i < l; ++i) {
|
||||
int cnt = _sets.at(i).pack.size();
|
||||
|
@ -1530,6 +1731,33 @@ uint64 StickerPanInner::currentSet(int yOffset) const {
|
|||
return _sets.isEmpty() ? RecentStickerSetId : _sets.back().id;
|
||||
}
|
||||
|
||||
void StickerPanInner::ui_repaintSavedGif(const LayoutSavedGif *layout) {
|
||||
if (!_showingGifs) return;
|
||||
|
||||
int32 position = layout->position();
|
||||
int32 row = position / MatrixRowShift, col = position % MatrixRowShift;
|
||||
t_assert((row < _gifRows.size()) && (col < _gifRows.at(row).size()));
|
||||
|
||||
const GifRow &gifRow(_gifRows.at(row));
|
||||
int32 left = st::savedGifsLeft, top = st::emojiPanHeader + row * (st::savedGifHeight + st::savedGifsSkip);
|
||||
for (int32 i = 0; i < col; ++i) left += gifRow.at(i)->width() + st::savedGifsSkip;
|
||||
|
||||
rtlupdate(left, top, gifRow.at(col)->width(), st::savedGifHeight);
|
||||
}
|
||||
|
||||
bool StickerPanInner::ui_isSavedGifVisible(const LayoutSavedGif *layout) {
|
||||
int32 position = layout->position();
|
||||
int32 row = position / MatrixRowShift, col = position % MatrixRowShift;
|
||||
t_assert((row < _gifRows.size()) && (col < _gifRows.at(row).size()));
|
||||
|
||||
int32 top = st::emojiPanHeader + row * (st::savedGifHeight + st::savedGifsSkip);
|
||||
return (top < _top + _maxHeight) && (top + st::savedGifHeight > _top);
|
||||
}
|
||||
|
||||
bool StickerPanInner::ui_isGifBeingChosen() {
|
||||
return _showingGifs;
|
||||
}
|
||||
|
||||
void StickerPanInner::appendSet(uint64 setId) {
|
||||
const StickerSets &sets(cStickerSets());
|
||||
StickerSets::const_iterator it = sets.constFind(setId);
|
||||
|
@ -1543,7 +1771,15 @@ void StickerPanInner::appendSet(uint64 setId) {
|
|||
_sets.push_back(DisplayedSet(it->id, it->flags, it->title, pack.size() + 1, pack));
|
||||
}
|
||||
|
||||
void StickerPanInner::refreshRecent(bool performResize) {
|
||||
void StickerPanInner::refreshRecent() {
|
||||
if (_showingGifs) {
|
||||
refreshSavedGifs();
|
||||
} else {
|
||||
refreshRecentStickers();
|
||||
}
|
||||
}
|
||||
|
||||
void StickerPanInner::refreshRecentStickers(bool performResize) {
|
||||
_custom.clear();
|
||||
clearSelection(true);
|
||||
StickerSets::const_iterator customIt = cStickerSets().constFind(CustomStickerSetId);
|
||||
|
@ -1580,7 +1816,7 @@ void StickerPanInner::refreshRecent(bool performResize) {
|
|||
}
|
||||
}
|
||||
|
||||
if (performResize) {
|
||||
if (performResize && !_showingGifs) {
|
||||
int32 h = countHeight();
|
||||
if (h != height()) {
|
||||
resize(width(), h);
|
||||
|
@ -1591,14 +1827,15 @@ void StickerPanInner::refreshRecent(bool performResize) {
|
|||
}
|
||||
}
|
||||
|
||||
void StickerPanInner::fillIcons(QVector<StickerIcon> &icons) {
|
||||
void StickerPanInner::fillIcons(QList<StickerIcon> &icons) {
|
||||
icons.clear();
|
||||
if (_sets.isEmpty()) return;
|
||||
icons.reserve(_sets.size() + 1);
|
||||
if (!cSavedGifs().isEmpty()) icons.push_back(StickerIcon(NoneStickerSetId));
|
||||
|
||||
icons.reserve(_sets.size());
|
||||
if (_sets.isEmpty()) return;
|
||||
int32 i = 0;
|
||||
if (_sets.at(0).id == RecentStickerSetId) ++i;
|
||||
if (i > 0) icons.push_back(StickerIcon());
|
||||
if (i > 0) icons.push_back(StickerIcon(RecentStickerSetId));
|
||||
for (int32 l = _sets.size(); i < l; ++i) {
|
||||
DocumentData *s = _sets.at(i).pack.at(0);
|
||||
int32 availw = st::rbEmoji.width - 2 * st::stickerIconPadding, availh = st::rbEmoji.height - 2 * st::stickerIconPadding;
|
||||
|
@ -1622,6 +1859,13 @@ void StickerPanInner::fillPanels(QVector<EmojiPanel*> &panels) {
|
|||
panels.at(i)->deleteLater();
|
||||
}
|
||||
panels.clear();
|
||||
|
||||
if (_showingGifs) {
|
||||
panels.push_back(new EmojiPanel(parentWidget(), lang(lng_saved_gifs), NoneStickerSetId, true, 0));
|
||||
panels.back()->show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_sets.isEmpty()) return;
|
||||
|
||||
int y = 0;
|
||||
|
@ -1637,8 +1881,9 @@ void StickerPanInner::fillPanels(QVector<EmojiPanel*> &panels) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void StickerPanInner::refreshPanels(QVector<EmojiPanel*> &panels) {
|
||||
if (_showingGifs) return;
|
||||
|
||||
if (panels.size() != _sets.size()) return fillPanels(panels);
|
||||
|
||||
int32 y = 0;
|
||||
|
@ -1656,6 +1901,64 @@ void StickerPanInner::updateSelected() {
|
|||
int32 selIndex = -1;
|
||||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
|
||||
if (_showingGifs) {
|
||||
int sx = (rtl() ? width() - p.x() : p.x()) - st::savedGifsLeft, sy = p.y() - st::emojiPanHeader;
|
||||
int32 row = sy / int32(st::savedGifHeight + st::savedGifsSkip), col = 0, sel = -1;
|
||||
bool del = false;
|
||||
if (sx >= 0 && row >= 0 && row < _gifRows.size() && sy < (row + 1) * st::savedGifHeight) {
|
||||
const GifRow &gifRow(_gifRows.at(row));
|
||||
for (int32 left = 0, cols = gifRow.size(); col < cols; ++col) {
|
||||
int32 width = gifRow.at(col)->width();
|
||||
if (sx >= left && sx < left + width) {
|
||||
del = (sx >= left + width - st::stickerPanDelete.pxWidth()) && (sy < row * st::savedGifHeight + st::stickerPanDelete.pxHeight());
|
||||
break;
|
||||
}
|
||||
left += width + st::savedGifsSkip;
|
||||
}
|
||||
if (col < gifRow.size()) {
|
||||
sel = row * MatrixRowShift + col + (del ? SavedGifsMaxPerRow : 0);
|
||||
} else {
|
||||
row = col = -1;
|
||||
}
|
||||
} else {
|
||||
row = col = -1;
|
||||
}
|
||||
if (_selected != sel) {
|
||||
int32 srow = (_selected >= 0) ? (_selected / MatrixRowShift) : -1;
|
||||
int32 scol = (_selected >= 0) ? (_selected % MatrixRowShift) : -1;
|
||||
bool sdel = (scol >= SavedGifsMaxPerRow);
|
||||
if (sdel) scol -= SavedGifsMaxPerRow;
|
||||
if (srow != row || scol != col) {
|
||||
if (srow >= 0 && srow < _gifRows.size()) {
|
||||
if (scol >= 0 && scol < _gifRows.at(srow).size()) {
|
||||
_gifRows.at(srow).at(scol)->notify_over(false);
|
||||
if (sdel) _gifRows.at(srow).at(scol)->notify_deleteOver(false);
|
||||
}
|
||||
}
|
||||
if (row >= 0 && row < _gifRows.size()) {
|
||||
if (col >= 0 && col < _gifRows.at(row).size()) {
|
||||
_gifRows.at(row).at(col)->notify_over(true);
|
||||
if (del) _gifRows.at(row).at(col)->notify_deleteOver(true);
|
||||
}
|
||||
}
|
||||
} else if (sdel != del) {
|
||||
if (sdel) _gifRows.at(srow).at(scol)->notify_deleteOver(false);
|
||||
if (del) _gifRows.at(row).at(col)->notify_deleteOver(true);
|
||||
}
|
||||
if ((_selected >= 0 && sel < 0) || (_selected < 0 && sel >= 0)) {
|
||||
setCursor(sel >= 0 ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
_selected = sel;
|
||||
if (_pressedSel >= 0 && _selected >= 0 && _pressedSel != _selected) {
|
||||
_pressedSel = _selected;
|
||||
if (row >= 0 && col >= 0) {
|
||||
Ui::showStickerPreview(_gifRows.at(row).at(col)->document());
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int y, ytill = 0, sx = (rtl() ? width() - p.x() : p.x()) - st::stickerPanPadding;
|
||||
for (int c = 0, l = _sets.size(); c < l; ++c) {
|
||||
const DisplayedSet &set(_sets.at(c));
|
||||
|
@ -1742,7 +2045,15 @@ void StickerPanInner::onSettings() {
|
|||
}
|
||||
|
||||
void StickerPanInner::onPreview() {
|
||||
if (_pressedSel >= 0 && _pressedSel < MatrixRowShift * _sets.size()) {
|
||||
if (_pressedSel < 0) return;
|
||||
if (_showingGifs) {
|
||||
int32 row = _pressedSel / MatrixRowShift, col = _pressedSel % MatrixRowShift;
|
||||
if (col >= SavedGifsMaxPerRow) col -= SavedGifsMaxPerRow;
|
||||
if (row < _gifRows.size() && col < _gifRows.at(row).size() && _gifRows.at(row).at(col)->document()->loaded()) {
|
||||
Ui::showStickerPreview(_gifRows.at(row).at(col)->document());
|
||||
_previewShown = true;
|
||||
}
|
||||
} else if (_pressedSel < MatrixRowShift * _sets.size()) {
|
||||
int tab = (_pressedSel / MatrixRowShift), sel = _pressedSel % MatrixRowShift;
|
||||
if (sel < _sets.at(tab).pack.size()) {
|
||||
Ui::showStickerPreview(_sets.at(tab).pack.at(sel));
|
||||
|
@ -1765,13 +2076,40 @@ void StickerPanInner::step_selected(uint64 ms, bool timer) {
|
|||
}
|
||||
toUpdate += stickerRect(tab, sel);
|
||||
}
|
||||
if (timer)rtlupdate(toUpdate.boundingRect());
|
||||
if (timer) rtlupdate(toUpdate.boundingRect());
|
||||
if (_animations.isEmpty()) _a_selected.stop();
|
||||
}
|
||||
|
||||
void StickerPanInner::showStickerSet(uint64 setId) {
|
||||
clearSelection(true);
|
||||
|
||||
if (setId == NoneStickerSetId) {
|
||||
if (_gifRows.isEmpty() && !cSavedGifs().isEmpty()) {
|
||||
refreshSavedGifs();
|
||||
}
|
||||
bool wasNotShowingGifs = !_showingGifs;
|
||||
if (wasNotShowingGifs) {
|
||||
_showingGifs = true;
|
||||
cSetShowingSavedGifs(true);
|
||||
emit saveConfigDelayed(SaveRecentEmojisTimeout);
|
||||
}
|
||||
refreshSavedGifs();
|
||||
emit scrollToY(0);
|
||||
emit scrollUpdated();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_showingGifs) {
|
||||
_showingGifs = false;
|
||||
cSetShowingSavedGifs(false);
|
||||
emit saveConfigDelayed(SaveRecentEmojisTimeout);
|
||||
|
||||
Notify::clipStopperHidden(ClipStopperSavedGifsPanel);
|
||||
|
||||
refreshRecentStickers(true);
|
||||
emit refreshIcons();
|
||||
}
|
||||
|
||||
int32 y = 0;
|
||||
for (int c = 0; c < _sets.size(); ++c) {
|
||||
if (_sets.at(c).id == setId) break;
|
||||
|
@ -1780,14 +2118,19 @@ void StickerPanInner::showStickerSet(uint64 setId) {
|
|||
}
|
||||
|
||||
emit scrollToY(y);
|
||||
emit scrollUpdated();
|
||||
|
||||
_lastMousePos = QCursor::pos();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
EmojiPanel::EmojiPanel(QWidget *parent, const QString &text, uint64 setId, bool special, int32 wantedY) : TWidget(parent),
|
||||
_wantedY(wantedY), _setId(setId), _special(special), _deleteVisible(false), _delete(special ? 0 : new IconedButton(this, st::notifyClose)) { // NoneStickerSetId if in emoji
|
||||
EmojiPanel::EmojiPanel(QWidget *parent, const QString &text, uint64 setId, bool special, int32 wantedY) : TWidget(parent)
|
||||
, _wantedY(wantedY)
|
||||
, _setId(setId)
|
||||
, _special(special)
|
||||
, _deleteVisible(false)
|
||||
, _delete(special ? 0 : new IconedButton(this, st::notifyClose)) { // NoneStickerSetId if in emoji
|
||||
resize(st::emojiPanWidth, st::emojiPanHeader);
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
|
@ -1815,7 +2158,7 @@ void EmojiPanel::updateText() {
|
|||
availw -= st::notifyClose.icon.pxWidth() + st::emojiPanHeaderLeft;
|
||||
}
|
||||
} else {
|
||||
QString switchText = lang((_setId != NoneStickerSetId) ? lng_switch_emoji : lng_switch_stickers);
|
||||
QString switchText = lang((_setId != NoneStickerSetId) ? lng_switch_emoji : (cSavedGifs().isEmpty() ? lng_switch_stickers : lng_switch_stickers_gifs));
|
||||
availw -= st::emojiSwitchSkip + st::emojiPanHeaderFont->width(switchText);
|
||||
}
|
||||
_text = st::emojiPanHeaderFont->elided(_fullText, availw);
|
||||
|
@ -1847,11 +2190,17 @@ void EmojiPanel::paintEvent(QPaintEvent *e) {
|
|||
p.drawTextLeft(st::emojiPanHeaderLeft, st::emojiPanHeaderTop, width(), _text);
|
||||
}
|
||||
|
||||
EmojiSwitchButton::EmojiSwitchButton(QWidget *parent, bool toStickers) : Button(parent),
|
||||
_toStickers(toStickers), _text(lang(_toStickers ? lng_switch_stickers : lng_switch_emoji)),
|
||||
_textWidth(st::emojiPanHeaderFont->width(_text)) {
|
||||
int32 w = st::emojiSwitchSkip + _textWidth + (st::emojiSwitchSkip - st::emojiSwitchImgSkip);
|
||||
EmojiSwitchButton::EmojiSwitchButton(QWidget *parent, bool toStickers) : Button(parent)
|
||||
, _toStickers(toStickers) {
|
||||
setCursor(style::cur_pointer);
|
||||
updateText();
|
||||
}
|
||||
|
||||
void EmojiSwitchButton::updateText() {
|
||||
_text = lang(_toStickers ? (cSavedGifs().isEmpty() ? lng_switch_stickers : lng_switch_stickers_gifs) : lng_switch_emoji);
|
||||
_textWidth = st::emojiPanHeaderFont->width(_text);
|
||||
|
||||
int32 w = st::emojiSwitchSkip + _textWidth + (st::emojiSwitchSkip - st::emojiSwitchImgSkip);
|
||||
resize(w, st::emojiPanHeader);
|
||||
}
|
||||
|
||||
|
@ -1947,6 +2296,7 @@ EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent)
|
|||
connect(&e_inner, SIGNAL(disableScroll(bool)), &e_scroll, SLOT(disableScroll(bool)));
|
||||
|
||||
connect(&s_inner, SIGNAL(scrollToY(int)), &s_scroll, SLOT(scrollToY(int)));
|
||||
connect(&s_inner, SIGNAL(scrollUpdated()), this, SLOT(onScroll()));
|
||||
|
||||
connect(&e_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||
connect(&s_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||
|
@ -1964,6 +2314,11 @@ EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent)
|
|||
connect(&e_inner, SIGNAL(needRefreshPanels()), this, SLOT(onRefreshPanels()));
|
||||
connect(&s_inner, SIGNAL(needRefreshPanels()), this, SLOT(onRefreshPanels()));
|
||||
|
||||
_saveConfigTimer.setSingleShot(true);
|
||||
connect(&_saveConfigTimer, SIGNAL(timeout()), this, SLOT(onSaveConfig()));
|
||||
connect(&e_inner, SIGNAL(saveConfigDelayed(int32)), this, SLOT(onSaveConfigDelayed(int32)));
|
||||
connect(&s_inner, SIGNAL(saveConfigDelayed(int32)), this, SLOT(onSaveConfigDelayed(int32)));
|
||||
|
||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged()));
|
||||
}
|
||||
|
@ -2020,6 +2375,14 @@ void EmojiPan::onWndActiveChanged() {
|
|||
}
|
||||
}
|
||||
|
||||
void EmojiPan::onSaveConfig() {
|
||||
Local::writeUserSettings();
|
||||
}
|
||||
|
||||
void EmojiPan::onSaveConfigDelayed(int32 delay) {
|
||||
_saveConfigTimer.start(delay);
|
||||
}
|
||||
|
||||
void EmojiPan::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
|
@ -2040,24 +2403,20 @@ void EmojiPan::paintEvent(QPaintEvent *e) {
|
|||
p.drawSpriteLeft(_iconsLeft + 7 * st::rbEmoji.width + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), st::stickersSettings);
|
||||
|
||||
if (!_icons.isEmpty()) {
|
||||
int32 x = _iconsLeft, i = 0, selxrel = _iconSelX.current(), selx = x + selxrel - _iconsX.current();
|
||||
if (!_icons.at(i).sticker) {
|
||||
if (selxrel > 0) {
|
||||
if (_iconHovers.at(i) < 1) {
|
||||
p.drawSpriteLeft(x + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), st::rbEmojiRecent.imageRect);
|
||||
}
|
||||
if (_iconHovers.at(i) > 0) {
|
||||
p.drawSpriteLeft(x + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), st::rbEmojiRecent.overImageRect);
|
||||
}
|
||||
int32 x = _iconsLeft, i = 0, selxrel = _iconsLeft + _iconSelX.current(), selx = selxrel - _iconsX.current();
|
||||
for (int32 l = _icons.size(); i < l && !_icons.at(i).sticker; ++i) {
|
||||
bool gifs = (_icons.at(i).setId == NoneStickerSetId);
|
||||
if (selxrel != x) {
|
||||
p.drawSpriteLeft(x + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), gifs ? st::savedGifsOver : st::rbEmojiRecent.imageRect);
|
||||
}
|
||||
if (selxrel < st::rbEmoji.width) {
|
||||
p.setOpacity(1 - (selxrel / st::rbEmoji.width));
|
||||
p.drawSpriteLeft(x + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), st::rbEmojiRecent.chkImageRect);
|
||||
if (selxrel < x + st::rbEmoji.width && selxrel > x - st::rbEmoji.width) {
|
||||
p.setOpacity(1 - (qAbs(selxrel - x) / st::rbEmoji.width));
|
||||
p.drawSpriteLeft(x + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), gifs ? st::savedGifsActive : st::rbEmojiRecent.chkImageRect);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
x += st::rbEmoji.width;
|
||||
++i;
|
||||
}
|
||||
int32 skip = i;
|
||||
|
||||
QRect clip(x, _iconsTop, _iconsLeft + 7 * st::rbEmoji.width - x, st::rbEmoji.height);
|
||||
if (rtl()) clip.moveLeft(width() - x - clip.width());
|
||||
|
@ -2065,28 +2424,23 @@ void EmojiPan::paintEvent(QPaintEvent *e) {
|
|||
|
||||
i += _iconsX.current() / int(st::rbEmoji.width);
|
||||
x -= _iconsX.current() % int(st::rbEmoji.width);
|
||||
for (int32 l = qMin(_icons.size(), i + 7 + (_icons.at(0).sticker ? 1 : 0)); i < l; ++i) {
|
||||
for (int32 l = qMin(_icons.size(), i + 8 - skip); i < l; ++i) {
|
||||
const StickerIcon &s(_icons.at(i));
|
||||
s.sticker->thumb->load();
|
||||
QPixmap pix(s.sticker->thumb->pix(s.pixw, s.pixh));
|
||||
//if (_iconSel == i) {
|
||||
// p.setOpacity(1);
|
||||
//} else {
|
||||
// p.setOpacity(1. * _iconHovers.at(i) + st::stickerIconOpacity * (1 - _iconHovers.at(i)));
|
||||
//}
|
||||
|
||||
p.drawPixmapLeft(x + (st::rbEmoji.width - s.pixw) / 2, _iconsTop + (st::rbEmoji.height - s.pixh) / 2, width(), pix);
|
||||
x += st::rbEmoji.width;
|
||||
p.setOpacity(1);
|
||||
}
|
||||
|
||||
if (rtl()) selx = width() - selx - st::rbEmoji.width;
|
||||
p.setOpacity(_icons.at(0).sticker ? 1. : qMax(1., selx / st::rbEmoji.width));
|
||||
p.fillRect(selx, _iconsTop + st::rbEmoji.height - st::stickerIconPadding, st::rbEmoji.width, st::stickerIconSel, st::stickerIconSelColor->b);
|
||||
p.setOpacity(skip ? qMax(1., selx / (skip * st::rbEmoji.width)) : 1.);
|
||||
p.fillRect(selx, _iconsTop + st::rbEmoji.height - st::stickerIconPadding, st::rbEmoji.width, st::stickerIconSel, st::stickerIconSelColor);
|
||||
|
||||
float64 o_left = snap(float64(_iconsX.current()) / st::stickerIconLeft.pxWidth(), 0., 1.);
|
||||
if (o_left > 0) {
|
||||
p.setOpacity(o_left);
|
||||
p.drawSpriteLeft(QRect(_iconsLeft + (_icons.at(0).sticker ? 0 : st::rbEmoji.width), _iconsTop, st::stickerIconLeft.pxWidth(), st::rbEmoji.height), width(), st::stickerIconLeft);
|
||||
p.drawSpriteLeft(QRect(_iconsLeft + skip * st::rbEmoji.width, _iconsTop, st::stickerIconLeft.pxWidth(), st::rbEmoji.height), width(), st::stickerIconLeft);
|
||||
}
|
||||
float64 o_right = snap(float64(_iconsMax - _iconsX.current()) / st::stickerIconRight.pxWidth(), 0., 1.);
|
||||
if (o_right > 0) {
|
||||
|
@ -2181,7 +2535,12 @@ void EmojiPan::mouseMoveEvent(QMouseEvent *e) {
|
|||
_iconsMousePos = e ? e->globalPos() : QCursor::pos();
|
||||
updateSelected();
|
||||
|
||||
if (!_iconsDragging && !_icons.isEmpty() && _iconDown >= (_icons.at(0).sticker ? 0 : 1)) {
|
||||
int32 skip = 0;
|
||||
for (int32 i = 0, l = _icons.size(); i < l; ++i) {
|
||||
if (_icons.at(i).sticker) break;
|
||||
++skip;
|
||||
}
|
||||
if (!_iconsDragging && !_icons.isEmpty() && _iconDown >= skip) {
|
||||
if ((_iconsMousePos - _iconsMouseDown).manhattanLength() >= QApplication::startDragDistance()) {
|
||||
_iconsDragging = true;
|
||||
}
|
||||
|
@ -2226,24 +2585,31 @@ void EmojiPan::mouseReleaseEvent(QMouseEvent *e) {
|
|||
|
||||
bool EmojiPan::event(QEvent *e) {
|
||||
if (e->type() == QEvent::TouchBegin) {
|
||||
int a = 0;
|
||||
} else if (e->type() == QEvent::Wheel && !_icons.isEmpty() && _iconOver >= (_icons.at(0).sticker ? 0 : 1) && _iconOver < _icons.size() && _iconDown < 0) {
|
||||
QWheelEvent *ev = static_cast<QWheelEvent*>(e);
|
||||
bool hor = (ev->angleDelta().x() != 0 || ev->orientation() == Qt::Horizontal);
|
||||
bool ver = (ev->angleDelta().y() != 0 || ev->orientation() == Qt::Vertical);
|
||||
if (hor) _horizontal = true;
|
||||
int32 newX = _iconsX.current();
|
||||
if (/*_horizontal && */hor) {
|
||||
newX = snap(newX - (rtl() ? -1 : 1) * (ev->pixelDelta().x() ? ev->pixelDelta().x() : ev->angleDelta().x()), 0, _iconsMax);
|
||||
} else if (/*!_horizontal && */ver) {
|
||||
newX = snap(newX - (ev->pixelDelta().y() ? ev->pixelDelta().y() : ev->angleDelta().y()), 0, _iconsMax);
|
||||
|
||||
} else if (e->type() == QEvent::Wheel) {
|
||||
int32 skip = 0;
|
||||
for (int32 i = 0, l = _icons.size(); i < l; ++i) {
|
||||
if (_icons.at(i).sticker) break;
|
||||
++skip;
|
||||
}
|
||||
if (newX != _iconsX.current()) {
|
||||
_iconsX = anim::ivalue(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
if (_iconAnimations.isEmpty()) _a_icons.stop();
|
||||
updateSelected();
|
||||
updateIcons();
|
||||
if (!_icons.isEmpty() && _iconOver >= skip && _iconOver < _icons.size() && _iconDown < 0) {
|
||||
QWheelEvent *ev = static_cast<QWheelEvent*>(e);
|
||||
bool hor = (ev->angleDelta().x() != 0 || ev->orientation() == Qt::Horizontal);
|
||||
bool ver = (ev->angleDelta().y() != 0 || ev->orientation() == Qt::Vertical);
|
||||
if (hor) _horizontal = true;
|
||||
int32 newX = _iconsX.current();
|
||||
if (/*_horizontal && */hor) {
|
||||
newX = snap(newX - (rtl() ? -1 : 1) * (ev->pixelDelta().x() ? ev->pixelDelta().x() : ev->angleDelta().x()), 0, _iconsMax);
|
||||
} else if (/*!_horizontal && */ver) {
|
||||
newX = snap(newX - (ev->pixelDelta().y() ? ev->pixelDelta().y() : ev->angleDelta().y()), 0, _iconsMax);
|
||||
}
|
||||
if (newX != _iconsX.current()) {
|
||||
_iconsX = anim::ivalue(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
if (_iconAnimations.isEmpty()) _a_icons.stop();
|
||||
updateSelected();
|
||||
updateIcons();
|
||||
}
|
||||
}
|
||||
}
|
||||
return TWidget::event(e);
|
||||
|
@ -2266,6 +2632,15 @@ void EmojiPan::refreshStickers() {
|
|||
}
|
||||
}
|
||||
|
||||
void EmojiPan::refreshSavedGifs() {
|
||||
e_switch.updateText();
|
||||
e_switch.moveToRight(0, 0, st::emojiPanWidth);
|
||||
s_inner.refreshSavedGifs();
|
||||
if (!_stickersShown) {
|
||||
s_inner.preloadImages();
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPan::onRefreshIcons() {
|
||||
_iconOver = -1;
|
||||
_iconHovers.clear();
|
||||
|
@ -2284,6 +2659,7 @@ void EmojiPan::onRefreshIcons() {
|
|||
}
|
||||
updatePanelsPositions(s_panels, s_scroll.scrollTop());
|
||||
updateSelected();
|
||||
if (_stickersShown) validateSelectedIcon();
|
||||
updateIcons();
|
||||
}
|
||||
|
||||
|
@ -2316,16 +2692,18 @@ void EmojiPan::updateSelected() {
|
|||
newOver = _icons.size();
|
||||
} else if (!_icons.isEmpty()) {
|
||||
if (y >= _iconsTop && y < _iconsTop + st::rbEmoji.height && x >= 0 && x < 7 * st::rbEmoji.width && x < _icons.size() * st::rbEmoji.width) {
|
||||
if (!_icons.at(0).sticker) {
|
||||
int32 skip = 0;
|
||||
for (int32 i = 0, l = _icons.size(); i < l; ++i) {
|
||||
if (x < st::rbEmoji.width) {
|
||||
newOver = 0;
|
||||
} else {
|
||||
x -= st::rbEmoji.width;
|
||||
newOver = i;
|
||||
break;
|
||||
}
|
||||
x -= st::rbEmoji.width;
|
||||
++skip;
|
||||
}
|
||||
if (newOver < 0) {
|
||||
x += _iconsX.current();
|
||||
newOver = qFloor(x / st::rbEmoji.width) + (_icons.at(0).sticker ? 0 : 1);
|
||||
newOver = qFloor(x / st::rbEmoji.width) + skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2459,6 +2837,7 @@ void EmojiPan::hideStart() {
|
|||
void EmojiPan::hideFinish() {
|
||||
hide();
|
||||
e_inner.hideFinish();
|
||||
s_inner.hideFinish();
|
||||
_cache = _toCache = _fromCache = QPixmap();
|
||||
_a_slide.stop();
|
||||
_horizontal = false;
|
||||
|
@ -2478,6 +2857,8 @@ void EmojiPan::hideFinish() {
|
|||
_a_icons.stop();
|
||||
_iconHovers = _icons.isEmpty() ? QVector<float64>() : QVector<float64>(_icons.size(), 0);
|
||||
_iconAnimations.clear();
|
||||
|
||||
Notify::clipStopperHidden(ClipStopperSavedGifsPanel);
|
||||
}
|
||||
|
||||
void EmojiPan::showStart() {
|
||||
|
@ -2543,6 +2924,26 @@ void EmojiPan::stickersInstalled(uint64 setId) {
|
|||
showStart();
|
||||
}
|
||||
|
||||
void EmojiPan::ui_repaintSavedGif(const LayoutSavedGif *layout) {
|
||||
if (_stickersShown && !isHidden()) {
|
||||
s_inner.ui_repaintSavedGif(layout);
|
||||
}
|
||||
}
|
||||
|
||||
bool EmojiPan::ui_isSavedGifVisible(const LayoutSavedGif *layout) {
|
||||
if (_stickersShown && !isHidden()) {
|
||||
return s_inner.ui_isSavedGifVisible(layout);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EmojiPan::ui_isGifBeingChosen() {
|
||||
if (_stickersShown && !isHidden()) {
|
||||
return s_inner.ui_isGifBeingChosen();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EmojiPan::showAll() {
|
||||
if (_stickersShown) {
|
||||
s_scroll.show();
|
||||
|
@ -2636,38 +3037,60 @@ void EmojiPan::onScroll() {
|
|||
st = s_scroll.scrollTop();
|
||||
if (_stickersShown) {
|
||||
updatePanelsPositions(s_panels, st);
|
||||
|
||||
uint64 setId = s_inner.currentSet(st);
|
||||
int32 newSel = 0;
|
||||
for (int32 i = 0, l = _icons.size(); i < l; ++i) {
|
||||
if (_icons.at(i).setId == setId) {
|
||||
newSel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newSel != _iconSel) {
|
||||
_iconSel = newSel;
|
||||
_iconSelX.start(newSel * st::rbEmoji.width);
|
||||
_iconsX.start(snap((2 * newSel - 7 - ((_icons.isEmpty() || _icons.at(0).sticker) ? 0 : 1)) * int(st::rbEmoji.width) / 2, 0, _iconsMax));
|
||||
_iconsStartAnim = getms();
|
||||
_a_icons.start();
|
||||
updateSelected();
|
||||
updateIcons();
|
||||
}
|
||||
validateSelectedIcon(true);
|
||||
}
|
||||
s_inner.setScrollTop(st);
|
||||
}
|
||||
|
||||
void EmojiPan::validateSelectedIcon(bool animated) {
|
||||
uint64 setId = s_inner.currentSet(s_scroll.scrollTop());
|
||||
int32 newSel = 0;
|
||||
for (int32 i = 0, l = _icons.size(); i < l; ++i) {
|
||||
if (_icons.at(i).setId == setId) {
|
||||
newSel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newSel != _iconSel) {
|
||||
_iconSel = newSel;
|
||||
int32 skip = 0;
|
||||
for (int32 i = 0, l = _icons.size(); i < l; ++i) {
|
||||
if (_icons.at(i).sticker) break;
|
||||
++skip;
|
||||
}
|
||||
if (animated) {
|
||||
_iconSelX.start(newSel * st::rbEmoji.width);
|
||||
} else {
|
||||
_iconSelX = anim::ivalue(newSel * st::rbEmoji.width, newSel * st::rbEmoji.width);
|
||||
}
|
||||
_iconsX.start(snap((2 * newSel - 7 - skip) * int(st::rbEmoji.width) / 2, 0, _iconsMax));
|
||||
_iconsStartAnim = getms();
|
||||
_a_icons.start();
|
||||
updateSelected();
|
||||
updateIcons();
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPan::onSwitch() {
|
||||
QPixmap cache = _cache;
|
||||
_fromCache = myGrab(this, rect().marginsRemoved(st::dropdownDef.padding));
|
||||
_stickersShown = !_stickersShown;
|
||||
if (!_stickersShown) {
|
||||
Notify::clipStopperHidden(ClipStopperSavedGifsPanel);
|
||||
}
|
||||
|
||||
if (cShowingSavedGifs() && cSavedGifs().isEmpty()) {
|
||||
s_inner.showStickerSet(DefaultStickerSetId);
|
||||
} else if (!cShowingSavedGifs() && !cSavedGifs().isEmpty() && cStickerSets().isEmpty()) {
|
||||
s_inner.showStickerSet(NoneStickerSetId);
|
||||
}
|
||||
_iconOver = -1;
|
||||
_iconHovers = _icons.isEmpty() ? QVector<float64>() : QVector<float64>(_icons.size(), 0);
|
||||
_iconAnimations.clear();
|
||||
_a_icons.stop();
|
||||
|
||||
validateSelectedIcon();
|
||||
|
||||
_cache = QPixmap();
|
||||
showAll();
|
||||
_toCache = myGrab(this, rect().marginsRemoved(st::dropdownDef.padding));
|
||||
|
@ -2721,7 +3144,6 @@ void EmojiPan::onRemoveSetSure() {
|
|||
cRefStickerSets().erase(it);
|
||||
int32 removeIndex = cStickerSetsOrder().indexOf(_removingSetId);
|
||||
if (removeIndex >= 0) cRefStickerSetsOrder().removeAt(removeIndex);
|
||||
cSetStickersHash(stickersCountHash());
|
||||
refreshStickers();
|
||||
Local::writeStickers();
|
||||
if (writeRecent) Local::writeUserSettings();
|
||||
|
@ -3337,5 +3759,16 @@ bool MentionsDropdown::eventFilter(QObject *obj, QEvent *e) {
|
|||
return QWidget::eventFilter(obj, e);
|
||||
}
|
||||
|
||||
void MentionsDropdown::ui_repaintSavedGif(const LayoutSavedGif *layout) {
|
||||
}
|
||||
|
||||
bool MentionsDropdown::ui_isSavedGifVisible(const LayoutSavedGif *layout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MentionsDropdown::ui_isGifBeingChosen() {
|
||||
return false;
|
||||
}
|
||||
|
||||
MentionsDropdown::~MentionsDropdown() {
|
||||
}
|
||||
|
|
|
@ -258,7 +258,6 @@ public:
|
|||
public slots:
|
||||
|
||||
void updateSelected();
|
||||
void onSaveConfig();
|
||||
|
||||
void onShowPicker();
|
||||
void onPickerHidden();
|
||||
|
@ -276,6 +275,7 @@ signals:
|
|||
void disableScroll(bool dis);
|
||||
|
||||
void needRefreshPanels();
|
||||
void saveConfigDelayed(int32 delay);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -300,14 +300,12 @@ private:
|
|||
int32 _selected, _pressedSel, _pickerSel;
|
||||
QPoint _lastMousePos;
|
||||
|
||||
QTimer _saveConfigTimer;
|
||||
|
||||
EmojiColorPicker _picker;
|
||||
QTimer _showPickerTimer;
|
||||
};
|
||||
|
||||
struct StickerIcon {
|
||||
StickerIcon() : setId(RecentStickerSetId), sticker(0), pixw(0), pixh(0) {
|
||||
StickerIcon(uint64 setId) : setId(setId), sticker(0), pixw(0), pixh(0) {
|
||||
}
|
||||
StickerIcon(uint64 setId, DocumentData *sticker, int32 pixw, int32 pixh) : setId(setId), sticker(sticker), pixw(pixw), pixh(pixh) {
|
||||
}
|
||||
|
@ -335,14 +333,17 @@ public:
|
|||
|
||||
void step_selected(uint64 ms, bool timer);
|
||||
|
||||
void hideFinish();
|
||||
void showStickerSet(uint64 setId);
|
||||
|
||||
void clearSelection(bool fast = false);
|
||||
|
||||
void refreshStickers();
|
||||
void refreshRecent(bool resize = true);
|
||||
void refreshRecentStickers(bool resize = true);
|
||||
void refreshSavedGifs();
|
||||
void refreshRecent();
|
||||
|
||||
void fillIcons(QVector<StickerIcon> &icons);
|
||||
void fillIcons(QList<StickerIcon> &icons);
|
||||
void fillPanels(QVector<EmojiPanel*> &panels);
|
||||
void refreshPanels(QVector<EmojiPanel*> &panels);
|
||||
|
||||
|
@ -351,6 +352,15 @@ public:
|
|||
|
||||
uint64 currentSet(int yOffset) const;
|
||||
|
||||
void ui_repaintSavedGif(const LayoutSavedGif *layout);
|
||||
bool ui_isSavedGifVisible(const LayoutSavedGif *layout);
|
||||
bool ui_isGifBeingChosen();
|
||||
|
||||
~StickerPanInner() {
|
||||
clearSavedGifs();
|
||||
deleteUnusedLayouts();
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
void updateSelected();
|
||||
|
@ -367,11 +377,17 @@ signals:
|
|||
void switchToEmoji();
|
||||
|
||||
void scrollToY(int y);
|
||||
void scrollUpdated();
|
||||
void disableScroll(bool dis);
|
||||
void needRefreshPanels();
|
||||
|
||||
void saveConfigDelayed(int32 delay);
|
||||
|
||||
private:
|
||||
|
||||
void paintSavedGifs(Painter &p, const QRect &r);
|
||||
void paintStickers(Painter &p, const QRect &r);
|
||||
|
||||
int32 _maxHeight;
|
||||
|
||||
void appendSet(uint64 setId);
|
||||
|
@ -398,6 +414,19 @@ private:
|
|||
QList<DisplayedSet> _sets;
|
||||
QList<bool> _custom;
|
||||
|
||||
bool _showingGifs;
|
||||
|
||||
typedef QList<LayoutSavedGif*> GifRow;
|
||||
typedef QList<GifRow> GifRows;
|
||||
GifRows _gifRows;
|
||||
void clearSavedGifs();
|
||||
void deleteUnusedLayouts();
|
||||
|
||||
typedef QMap<DocumentData*, LayoutSavedGif*> GifLayouts;
|
||||
GifLayouts _gifLayouts;
|
||||
LayoutSavedGif *layoutPrepare(DocumentData *doc, int32 position, int32 width);
|
||||
const GifRow &layoutGifRow(const GifRow &row, int32 *widths, int32 sumWidth);
|
||||
|
||||
int32 _selected, _pressedSel;
|
||||
QPoint _lastMousePos;
|
||||
|
||||
|
@ -452,6 +481,7 @@ public:
|
|||
|
||||
EmojiSwitchButton(QWidget *parent, bool toStickers); // otherwise toEmoji
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void updateText();
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -504,9 +534,14 @@ public:
|
|||
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
||||
}
|
||||
|
||||
void ui_repaintSavedGif(const LayoutSavedGif *layout);
|
||||
bool ui_isSavedGifVisible(const LayoutSavedGif *layout);
|
||||
bool ui_isGifBeingChosen();
|
||||
|
||||
public slots:
|
||||
|
||||
void refreshStickers();
|
||||
void refreshSavedGifs();
|
||||
|
||||
void hideStart();
|
||||
void hideFinish();
|
||||
|
@ -525,6 +560,9 @@ public slots:
|
|||
void onRefreshIcons();
|
||||
void onRefreshPanels();
|
||||
|
||||
void onSaveConfig();
|
||||
void onSaveConfigDelayed(int32 delay);
|
||||
|
||||
signals:
|
||||
|
||||
void emojiSelected(EmojiPtr emoji);
|
||||
|
@ -533,6 +571,8 @@ signals:
|
|||
|
||||
private:
|
||||
|
||||
void validateSelectedIcon(bool animated = false);
|
||||
|
||||
int32 _maxHeight;
|
||||
bool _horizontal;
|
||||
|
||||
|
@ -561,7 +601,7 @@ private:
|
|||
BoxShadow _shadow;
|
||||
|
||||
FlatRadiobutton _recent, _people, _nature, _food, _activity, _travel, _objects, _symbols;
|
||||
QVector<StickerIcon> _icons;
|
||||
QList<StickerIcon> _icons;
|
||||
QVector<float64> _iconHovers;
|
||||
int32 _iconOver, _iconSel, _iconDown;
|
||||
bool _iconsDragging;
|
||||
|
@ -591,6 +631,8 @@ private:
|
|||
|
||||
uint64 _removingSetId;
|
||||
|
||||
QTimer _saveConfigTimer;
|
||||
|
||||
};
|
||||
|
||||
typedef QList<UserData*> MentionRows;
|
||||
|
@ -679,6 +721,10 @@ public:
|
|||
return rect().contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
||||
}
|
||||
|
||||
void ui_repaintSavedGif(const LayoutSavedGif *layout);
|
||||
bool ui_isSavedGifVisible(const LayoutSavedGif *layout);
|
||||
bool ui_isGifBeingChosen();
|
||||
|
||||
~MentionsDropdown();
|
||||
|
||||
signals:
|
||||
|
|
|
@ -102,20 +102,36 @@ namespace Ui {
|
|||
return false;
|
||||
}
|
||||
|
||||
void clipRedraw(ClipReader *reader) {
|
||||
bool isGifBeingChosen() {
|
||||
if (MainWidget *m = App::main()) return m->ui_isGifBeingChosen();
|
||||
return false;
|
||||
}
|
||||
|
||||
void clipRepaint(ClipReader *reader) {
|
||||
const GifItems &items(App::gifItems());
|
||||
GifItems::const_iterator it = items.constFind(reader);
|
||||
if (it != items.cend()) {
|
||||
if (reader->currentDisplayed()) {
|
||||
return;
|
||||
}
|
||||
Ui::redrawHistoryItem(it.value());
|
||||
Ui::repaintHistoryItem(it.value());
|
||||
}
|
||||
if (Window *w = App::wnd()) w->ui_clipRedraw(reader);
|
||||
if (Window *w = App::wnd()) w->ui_clipRepaint(reader);
|
||||
}
|
||||
|
||||
void redrawHistoryItem(const HistoryItem *item) {
|
||||
if (MainWidget *m = App::main()) m->ui_redrawHistoryItem(item);
|
||||
void repaintHistoryItem(const HistoryItem *item) {
|
||||
if (!item) return;
|
||||
if (MainWidget *m = App::main()) m->ui_repaintHistoryItem(item);
|
||||
}
|
||||
|
||||
void repaintSavedGif(const LayoutSavedGif *layout) {
|
||||
if (!layout) return;
|
||||
if (MainWidget *m = App::main()) m->ui_repaintSavedGif(layout);
|
||||
}
|
||||
|
||||
bool isSavedGifVisible(const LayoutSavedGif *layout) {
|
||||
if (MainWidget *m = App::main()) return m->ui_isSavedGifVisible(layout);
|
||||
return false;
|
||||
}
|
||||
|
||||
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back) {
|
||||
|
@ -148,8 +164,8 @@ namespace Notify {
|
|||
if (MainWidget *m = App::main()) m->notify_migrateUpdated(peer);
|
||||
}
|
||||
|
||||
void mediaViewHidden() {
|
||||
if (MainWidget *m = App::main()) m->notify_mediaViewHidden();
|
||||
void clipStopperHidden(ClipStopperType type) {
|
||||
if (MainWidget *m = App::main()) m->notify_clipStopperHidden(type);
|
||||
}
|
||||
|
||||
void clipReinit(ClipReader *reader) {
|
||||
|
|
|
@ -46,10 +46,13 @@ namespace Ui { // openssl doesn't allow me to use UI :(
|
|||
void hideLayer(bool fast = false);
|
||||
bool isLayerShown();
|
||||
bool isMediaViewShown();
|
||||
bool isGifBeingChosen();
|
||||
|
||||
void clipRedraw(ClipReader *reader);
|
||||
void clipRepaint(ClipReader *reader);
|
||||
|
||||
void redrawHistoryItem(const HistoryItem *item);
|
||||
void repaintHistoryItem(const HistoryItem *item);
|
||||
void repaintSavedGif(const LayoutSavedGif *layout);
|
||||
bool isSavedGifVisible(const LayoutSavedGif *reader);
|
||||
|
||||
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back = false);
|
||||
inline void showPeerHistory(const PeerData *peer, MsgId msgId, bool back = false) {
|
||||
|
@ -68,6 +71,11 @@ namespace Ui { // openssl doesn't allow me to use UI :(
|
|||
|
||||
};
|
||||
|
||||
enum ClipStopperType {
|
||||
ClipStopperMediaview,
|
||||
ClipStopperSavedGifsPanel,
|
||||
};
|
||||
|
||||
namespace Notify {
|
||||
|
||||
void userIsBotChanged(UserData *user);
|
||||
|
@ -76,7 +84,7 @@ namespace Notify {
|
|||
|
||||
void migrateUpdated(PeerData *peer);
|
||||
|
||||
void mediaViewHidden();
|
||||
void clipStopperHidden(ClipStopperType type);
|
||||
|
||||
void clipReinit(ClipReader *reader);
|
||||
|
||||
|
|
|
@ -118,34 +118,104 @@ void Animation::stop() {
|
|||
_manager->stop(this);
|
||||
}
|
||||
|
||||
void AnimationManager::clipReinit(ClipReader *reader) {
|
||||
AnimationManager::AnimationManager() : _timer(this), _iterating(false) {
|
||||
_timer.setSingleShot(false);
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(timeout()));
|
||||
}
|
||||
|
||||
void AnimationManager::start(Animation *obj) {
|
||||
if (_iterating) {
|
||||
_starting.insert(obj, NullType());
|
||||
if (!_stopping.isEmpty()) {
|
||||
_stopping.remove(obj);
|
||||
}
|
||||
} else {
|
||||
if (_objects.isEmpty()) {
|
||||
_timer.start(AnimationTimerDelta);
|
||||
}
|
||||
_objects.insert(obj, NullType());
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationManager::stop(Animation *obj) {
|
||||
if (_iterating) {
|
||||
_stopping.insert(obj, NullType());
|
||||
if (!_starting.isEmpty()) {
|
||||
_starting.insert(obj, NullType());
|
||||
}
|
||||
} else {
|
||||
AnimatingObjects::iterator i = _objects.find(obj);
|
||||
if (i != _objects.cend()) {
|
||||
_objects.erase(i);
|
||||
if (_objects.isEmpty()) {
|
||||
_timer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationManager::timeout() {
|
||||
_iterating = true;
|
||||
uint64 ms = getms();
|
||||
for (AnimatingObjects::const_iterator i = _objects.begin(), e = _objects.end(); i != e; ++i) {
|
||||
i.key()->step(ms, true);
|
||||
}
|
||||
_iterating = false;
|
||||
|
||||
if (!_starting.isEmpty()) {
|
||||
for (AnimatingObjects::iterator i = _starting.begin(), e = _starting.end(); i != e; ++i) {
|
||||
_objects.insert(i.key(), NullType());
|
||||
}
|
||||
_starting.clear();
|
||||
}
|
||||
if (!_stopping.isEmpty()) {
|
||||
for (AnimatingObjects::iterator i = _stopping.begin(), e = _stopping.end(); i != e; ++i) {
|
||||
_objects.remove(i.key());
|
||||
}
|
||||
_stopping.clear();
|
||||
}
|
||||
if (!_objects.size()) {
|
||||
_timer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationManager::clipReinit(ClipReader *reader, qint32 threadIndex) {
|
||||
ClipReader::callback(reader, threadIndex, ClipReaderReinit);
|
||||
Notify::clipReinit(reader);
|
||||
}
|
||||
|
||||
void AnimationManager::clipRedraw(ClipReader *reader) {
|
||||
Ui::clipRedraw(reader);
|
||||
void AnimationManager::clipRepaint(ClipReader *reader, qint32 threadIndex) {
|
||||
ClipReader::callback(reader, threadIndex, ClipReaderRepaint);
|
||||
Ui::clipRepaint(reader);
|
||||
}
|
||||
|
||||
QPixmap _prepareFrame(const ClipFrameRequest &request, const QImage &original, QImage &cache, bool smooth) {
|
||||
QPixmap _prepareFrame(const ClipFrameRequest &request, const QImage &original, QImage &cache, bool hasAlpha) {
|
||||
bool badSize = (original.width() != request.framew) || (original.height() != request.frameh);
|
||||
bool needOuter = (request.outerw != request.framew) || (request.outerh != request.frameh);
|
||||
if (badSize || needOuter || request.rounded) {
|
||||
if (badSize || needOuter || hasAlpha || request.rounded) {
|
||||
int32 factor(request.factor);
|
||||
bool fill = false;
|
||||
if (cache.width() != request.outerw || cache.height() != request.outerh) {
|
||||
cache = QImage(request.outerw, request.outerh, QImage::Format_ARGB32_Premultiplied);
|
||||
if (request.framew < request.outerw || request.frameh < request.outerh || original.hasAlphaChannel()) {
|
||||
if (request.framew < request.outerw || request.frameh < request.outerh || hasAlpha) {
|
||||
fill = true;
|
||||
}
|
||||
cache.setDevicePixelRatio(factor);
|
||||
}
|
||||
{
|
||||
Painter p(&cache);
|
||||
if (fill) p.fillRect(0, 0, cache.width() / factor, cache.height() / factor, st::black);
|
||||
if (smooth && badSize) p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
QRect to((request.outerw - request.framew) / (2 * factor), (request.outerh - request.frameh) / (2 * factor), request.framew / factor, request.frameh / factor);
|
||||
QRect from(0, 0, original.width(), original.height());
|
||||
p.drawImage(to, original, from, Qt::ColorOnly);
|
||||
if (fill) {
|
||||
p.fillRect(0, 0, cache.width() / factor, cache.height() / factor, st::black);
|
||||
}
|
||||
QPoint position((request.outerw - request.framew) / (2 * factor), (request.outerh - request.frameh) / (2 * factor));
|
||||
if (badSize) {
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
QRect to(position, QSize(request.framew / factor, request.frameh / factor));
|
||||
QRect from(0, 0, original.width(), original.height());
|
||||
p.drawImage(to, original, from, Qt::ColorOnly);
|
||||
} else {
|
||||
p.drawImage(position, original);
|
||||
}
|
||||
}
|
||||
if (request.rounded) {
|
||||
imageRound(cache);
|
||||
|
@ -155,7 +225,9 @@ QPixmap _prepareFrame(const ClipFrameRequest &request, const QImage &original, Q
|
|||
return QPixmap::fromImage(original, Qt::ColorOnly);
|
||||
}
|
||||
|
||||
ClipReader::ClipReader(const FileLocation &location, const QByteArray &data) : _state(ClipReading)
|
||||
ClipReader::ClipReader(const FileLocation &location, const QByteArray &data, Callback *cb)
|
||||
: _cb(cb)
|
||||
, _state(ClipReading)
|
||||
, _width(0)
|
||||
, _height(0)
|
||||
, _currentDisplayed(1)
|
||||
|
@ -182,6 +254,13 @@ ClipReader::ClipReader(const FileLocation &location, const QByteArray &data) : _
|
|||
_clipManagers.at(_threadIndex)->append(this, location, data);
|
||||
}
|
||||
|
||||
void ClipReader::callback(ClipReader *reader, int32 threadIndex, ClipReaderNotification notification) {
|
||||
// check if reader is not deleted already
|
||||
if (_clipManagers.size() > threadIndex && _clipManagers.at(threadIndex)->carries(reader)) {
|
||||
if (reader->_cb) reader->_cb->call(notification);
|
||||
}
|
||||
}
|
||||
|
||||
void ClipReader::start(int32 framew, int32 frameh, int32 outerw, int32 outerh, bool rounded) {
|
||||
if (_clipManagers.size() <= _threadIndex) error();
|
||||
if (_state == ClipError) return;
|
||||
|
@ -270,6 +349,8 @@ void ClipReader::error() {
|
|||
|
||||
ClipReader::~ClipReader() {
|
||||
stop();
|
||||
delete _cb;
|
||||
setBadPointer(_cb);
|
||||
}
|
||||
|
||||
class ClipReaderImplementation {
|
||||
|
@ -277,7 +358,7 @@ public:
|
|||
|
||||
ClipReaderImplementation(FileLocation *location, QByteArray *data) : _location(location), _data(data), _device(0) {
|
||||
}
|
||||
virtual bool readNextFrame(QImage &to) = 0;
|
||||
virtual bool readNextFrame(QImage &to, bool &hasAlpha, const QSize &size) = 0;
|
||||
virtual int32 nextFrameDelay() = 0;
|
||||
virtual bool start() = 0;
|
||||
virtual ~ClipReaderImplementation() {
|
||||
|
@ -312,7 +393,7 @@ public:
|
|||
, _frameDelay(0) {
|
||||
}
|
||||
|
||||
bool readNextFrame(QImage &to) {
|
||||
bool readNextFrame(QImage &to, bool &hasAlpha, const QSize &size) {
|
||||
if (_reader) _frameDelay = _reader->nextImageDelay();
|
||||
if (_framesLeft < 1 && !jumpToStart()) {
|
||||
return false;
|
||||
|
@ -324,19 +405,24 @@ public:
|
|||
}
|
||||
--_framesLeft;
|
||||
|
||||
int32 w = frame.width(), h = frame.height();
|
||||
if (to.width() == w && to.height() == h && to.format() == frame.format()) {
|
||||
if (to.byteCount() != frame.byteCount()) {
|
||||
int bpl = qMin(to.bytesPerLine(), frame.bytesPerLine());
|
||||
for (int i = 0; i < h; ++i) {
|
||||
memcpy(to.scanLine(i), frame.constScanLine(i), bpl);
|
||||
if (size.isEmpty() || size == frame.size()) {
|
||||
int32 w = frame.width(), h = frame.height();
|
||||
if (to.width() == w && to.height() == h && to.format() == frame.format()) {
|
||||
if (to.byteCount() != frame.byteCount()) {
|
||||
int bpl = qMin(to.bytesPerLine(), frame.bytesPerLine());
|
||||
for (int i = 0; i < h; ++i) {
|
||||
memcpy(to.scanLine(i), frame.constScanLine(i), bpl);
|
||||
}
|
||||
} else {
|
||||
memcpy(to.bits(), frame.constBits(), frame.byteCount());
|
||||
}
|
||||
} else {
|
||||
memcpy(to.bits(), frame.constBits(), frame.byteCount());
|
||||
to = frame.copy();
|
||||
}
|
||||
} else {
|
||||
to = frame.copy();
|
||||
to = frame.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
hasAlpha = frame.hasAlphaChannel();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -409,7 +495,7 @@ public:
|
|||
_avpkt.size = 0;
|
||||
}
|
||||
|
||||
bool readNextFrame(QImage &to) {
|
||||
bool readNextFrame(QImage &to, bool &hasAlpha, const QSize &size) {
|
||||
int res;
|
||||
while (true) {
|
||||
if (_avpkt.size > 0) { // previous packet not finished
|
||||
|
@ -472,25 +558,31 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
if (to.isNull() || to.width() != _width || to.height() != _height) {
|
||||
to = QImage(_width, _height, QImage::Format_ARGB32);
|
||||
QSize toSize(size.isEmpty() ? QSize(_width, _height) : size);
|
||||
if (to.isNull() || to.size() != toSize) {
|
||||
to = QImage(toSize, QImage::Format_ARGB32);
|
||||
}
|
||||
if (_frame->width == _width && _frame->height == _height && (_frame->format == AV_PIX_FMT_BGRA || (_frame->format == -1 && _codecContext->pix_fmt == AV_PIX_FMT_BGRA))) {
|
||||
if (_frame->width == toSize.width() && _frame->height == toSize.height() && (_frame->format == AV_PIX_FMT_BGRA || (_frame->format == -1 && _codecContext->pix_fmt == AV_PIX_FMT_BGRA))) {
|
||||
int32 sbpl = _frame->linesize[0], dbpl = to.bytesPerLine(), bpl = qMin(sbpl, dbpl);
|
||||
uchar *s = _frame->data[0], *d = to.bits();
|
||||
for (int32 i = 0, l = _frame->height; i < l; ++i) {
|
||||
memcpy(d + i * dbpl, s + i * sbpl, bpl);
|
||||
}
|
||||
|
||||
hasAlpha = true;
|
||||
} else {
|
||||
if (_frame->width != _width || _frame->height != _height || (_frame->format != -1 && _frame->format != _codecContext->pix_fmt) || !_swsContext) {
|
||||
_swsContext = sws_getCachedContext(_swsContext, _frame->width, _frame->height, AVPixelFormat(_frame->format), _width, _height, AV_PIX_FMT_BGRA, 0, 0, 0, 0);
|
||||
if ((_swsSize != toSize) || (_frame->format != -1 && _frame->format != _codecContext->pix_fmt) || !_swsContext) {
|
||||
_swsSize = toSize;
|
||||
_swsContext = sws_getCachedContext(_swsContext, _frame->width, _frame->height, AVPixelFormat(_frame->format), toSize.width(), toSize.height(), AV_PIX_FMT_BGRA, 0, 0, 0, 0);
|
||||
}
|
||||
uint8_t * toData[1] = { to.bits() };
|
||||
int toLinesize[1] = { to.bytesPerLine() };
|
||||
if ((res = sws_scale(_swsContext, _frame->data, _frame->linesize, 0, _frame->height, toData, toLinesize)) != _height) {
|
||||
LOG(("Gif Error: Unable to sws_scale to good size %1, hieght %2, should be %3").arg(logData()).arg(res).arg(_height));
|
||||
if ((res = sws_scale(_swsContext, _frame->data, _frame->linesize, 0, _frame->height, toData, toLinesize)) != _swsSize.height()) {
|
||||
LOG(("Gif Error: Unable to sws_scale to good size %1, height %2, should be %3").arg(logData()).arg(res).arg(_swsSize.height()));
|
||||
return false;
|
||||
}
|
||||
|
||||
hasAlpha = false;
|
||||
}
|
||||
|
||||
int64 duration = av_frame_get_pkt_duration(_frame);
|
||||
|
@ -634,6 +726,7 @@ private:
|
|||
|
||||
int32 _width, _height;
|
||||
SwsContext *_swsContext;
|
||||
QSize _swsSize;
|
||||
|
||||
int64 _frameMs;
|
||||
int32 _nextFrameDelay, _currentFrameDelay;
|
||||
|
@ -665,6 +758,10 @@ public:
|
|||
, _location(_data.isEmpty() ? new FileLocation(location) : 0)
|
||||
, _accessed(false)
|
||||
, _implementation(0)
|
||||
, _currentHasAlpha(true)
|
||||
, _nextHasAlpha(true)
|
||||
, _width(0)
|
||||
, _height(0)
|
||||
, _previousMs(0)
|
||||
, _currentMs(0)
|
||||
, _nextUpdateMs(0)
|
||||
|
@ -682,9 +779,11 @@ public:
|
|||
return error();
|
||||
}
|
||||
if (_currentOriginal.isNull()) {
|
||||
if (!_implementation->readNextFrame(_currentOriginal)) {
|
||||
if (!_implementation->readNextFrame(_currentOriginal, _currentHasAlpha, QSize())) {
|
||||
return error();
|
||||
}
|
||||
_width = _currentOriginal.width();
|
||||
_height = _currentOriginal.height();
|
||||
return ClipProcessReinit;
|
||||
}
|
||||
return ClipProcessWait;
|
||||
|
@ -702,7 +801,7 @@ public:
|
|||
|
||||
_previousMs = _currentMs;
|
||||
_currentMs = ms;
|
||||
_current = _prepareFrame(_request, _currentOriginal, _currentCache, true);
|
||||
_current = _prepareFrame(_request, _currentOriginal, _currentCache, _currentHasAlpha);
|
||||
|
||||
if (!prepareNextFrame()) {
|
||||
return error();
|
||||
|
@ -710,7 +809,7 @@ public:
|
|||
return ClipProcessStarted;
|
||||
} else if (!_paused && ms >= _nextUpdateMs) {
|
||||
swapBuffers();
|
||||
return ClipProcessRedraw;
|
||||
return ClipProcessRepaint;
|
||||
}
|
||||
return ClipProcessWait;
|
||||
}
|
||||
|
@ -722,7 +821,7 @@ public:
|
|||
|
||||
if (ms >= _nextUpdateMs) { // we are late
|
||||
swapBuffers(ms); // keep up
|
||||
return ClipProcessRedraw;
|
||||
return ClipProcessRepaint;
|
||||
}
|
||||
return ClipProcessWait;
|
||||
}
|
||||
|
@ -738,16 +837,17 @@ public:
|
|||
qSwap(_currentOriginal, _nextOriginal);
|
||||
qSwap(_current, _next);
|
||||
qSwap(_currentCache, _nextCache);
|
||||
qSwap(_currentHasAlpha, _nextHasAlpha);
|
||||
}
|
||||
|
||||
bool prepareNextFrame() {
|
||||
if (!_implementation->readNextFrame(_nextOriginal)) {
|
||||
if (!_implementation->readNextFrame(_nextOriginal, _nextHasAlpha, QSize(_request.framew, _request.frameh))) {
|
||||
return false;
|
||||
}
|
||||
_nextUpdateMs = _currentMs + nextFrameDelay();
|
||||
_nextOriginal.setDevicePixelRatio(_request.factor);
|
||||
_next = QPixmap();
|
||||
_next = _prepareFrame(_request, _nextOriginal, _nextCache, true);
|
||||
_next = _prepareFrame(_request, _nextOriginal, _nextCache, _nextHasAlpha);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -809,6 +909,8 @@ private:
|
|||
ClipFrameRequest _request;
|
||||
QPixmap _current, _next;
|
||||
QImage _currentOriginal, _nextOriginal, _currentCache, _nextCache;
|
||||
bool _currentHasAlpha, _nextHasAlpha;
|
||||
int32 _width, _height;
|
||||
|
||||
uint64 _previousMs, _currentMs, _nextUpdateMs;
|
||||
|
||||
|
@ -828,8 +930,8 @@ ClipReadManager::ClipReadManager(QThread *thread) : _processingInThread(0), _nee
|
|||
_timer.moveToThread(thread);
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(process()));
|
||||
|
||||
connect(this, SIGNAL(reinit(ClipReader*)), _manager, SLOT(clipReinit(ClipReader*)));
|
||||
connect(this, SIGNAL(redraw(ClipReader*)), _manager, SLOT(clipRedraw(ClipReader*)));
|
||||
connect(this, SIGNAL(reinit(ClipReader*,qint32)), _manager, SLOT(clipReinit(ClipReader*,qint32)));
|
||||
connect(this, SIGNAL(repaint(ClipReader*,qint32)), _manager, SLOT(clipRepaint(ClipReader*,qint32)));
|
||||
}
|
||||
|
||||
void ClipReadManager::append(ClipReader *reader, const FileLocation &location, const QByteArray &data) {
|
||||
|
@ -854,13 +956,18 @@ void ClipReadManager::stop(ClipReader *reader) {
|
|||
emit processDelayed();
|
||||
}
|
||||
|
||||
bool ClipReadManager::carries(ClipReader *reader) const {
|
||||
QMutexLocker lock(&_readerPointersMutex);
|
||||
return _readerPointers.contains(reader);
|
||||
}
|
||||
|
||||
bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcessResult result, uint64 ms) {
|
||||
QMutexLocker lock(&_readerPointersMutex);
|
||||
ReaderPointers::iterator it = _readerPointers.find(reader->_interface);
|
||||
if (result == ClipProcessError) {
|
||||
if (it != _readerPointers.cend()) {
|
||||
it.key()->error();
|
||||
emit reinit(it.key());
|
||||
emit reinit(it.key(), it.key()->threadIndex());
|
||||
|
||||
_readerPointers.erase(it);
|
||||
it = _readerPointers.end();
|
||||
|
@ -871,9 +978,9 @@ bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcess
|
|||
}
|
||||
|
||||
if (result == ClipProcessStarted) {
|
||||
_loadLevel.fetchAndAddRelease(reader->_currentOriginal.width() * reader->_currentOriginal.height() - AverageGifSize);
|
||||
_loadLevel.fetchAndAddRelease(reader->_width * reader->_height - AverageGifSize);
|
||||
}
|
||||
if (!reader->_paused && (result == ClipProcessRedraw || result == ClipProcessWait)) {
|
||||
if (!reader->_paused && (result == ClipProcessRepaint || result == ClipProcessWait)) {
|
||||
if (it.key()->_lastDisplayMs.get() + WaitBeforeGifPause < qMax(reader->_previousMs, ms)) {
|
||||
reader->_paused = true;
|
||||
it.key()->_paused.set(true);
|
||||
|
@ -885,14 +992,14 @@ bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcess
|
|||
}
|
||||
}
|
||||
}
|
||||
if (result == ClipProcessReinit || result == ClipProcessRedraw || result == ClipProcessStarted) {
|
||||
if (result == ClipProcessReinit || result == ClipProcessRepaint || result == ClipProcessStarted) {
|
||||
it.key()->_current = reader->_current;
|
||||
it.key()->_currentOriginal = reader->_currentOriginal;
|
||||
it.key()->_currentDisplayed.set(false);
|
||||
if (result == ClipProcessReinit) {
|
||||
emit reinit(it.key());
|
||||
} else if (result == ClipProcessRedraw) {
|
||||
emit redraw(it.key());
|
||||
emit reinit(it.key(), it.key()->threadIndex());
|
||||
} else if (result == ClipProcessRepaint) {
|
||||
emit repaint(it.key(), it.key()->threadIndex());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -900,7 +1007,7 @@ bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcess
|
|||
|
||||
ClipReadManager::ResultHandleState ClipReadManager::handleResult(ClipReaderPrivate *reader, ClipProcessResult result, uint64 ms) {
|
||||
if (!handleProcessResult(reader, result, ms)) {
|
||||
_loadLevel.fetchAndAddRelease(-1 * (reader->_currentOriginal.isNull() ? AverageGifSize : reader->_currentOriginal.width() * reader->_currentOriginal.height()));
|
||||
_loadLevel.fetchAndAddRelease(-1 * (reader->_currentOriginal.isNull() ? AverageGifSize : reader->_width * reader->_height));
|
||||
delete reader;
|
||||
return ResultHandleRemove;
|
||||
}
|
||||
|
@ -910,7 +1017,7 @@ ClipReadManager::ResultHandleState ClipReadManager::handleResult(ClipReaderPriva
|
|||
return ResultHandleStop;
|
||||
}
|
||||
|
||||
if (result == ClipProcessRedraw) {
|
||||
if (result == ClipProcessRepaint) {
|
||||
return handleResult(reader, reader->finishProcess(ms), ms);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,8 @@ namespace anim {
|
|||
_delta = 0;
|
||||
}
|
||||
|
||||
typedef float64 Type;
|
||||
|
||||
private:
|
||||
|
||||
float64 _cur, _from, _delta;
|
||||
|
@ -110,6 +112,8 @@ namespace anim {
|
|||
_delta = 0;
|
||||
}
|
||||
|
||||
typedef int32 Type;
|
||||
|
||||
private:
|
||||
|
||||
int32 _cur;
|
||||
|
@ -179,6 +183,8 @@ namespace anim {
|
|||
_delta_r = _delta_g = _delta_b = _delta_a = 0;
|
||||
}
|
||||
|
||||
typedef QColor Type;
|
||||
|
||||
private:
|
||||
|
||||
QColor _cur;
|
||||
|
@ -338,87 +344,129 @@ AnimationCallbacks *animation(Param param, Type *obj, typename AnimationCallback
|
|||
return new AnimationCallbacksAbsoluteWithParam<Type, Param>(param, obj, method);
|
||||
}
|
||||
|
||||
template <typename AnimType>
|
||||
class SimpleAnimation {
|
||||
public:
|
||||
|
||||
typedef Function<void> Callbacks;
|
||||
|
||||
SimpleAnimation() : _data(0) {
|
||||
}
|
||||
|
||||
bool animating(uint64 ms) {
|
||||
if (_data && _data->_a.animating()) {
|
||||
_data->_a.step(ms);
|
||||
return _data && _data->_a.animating();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isNull() {
|
||||
return !_data;
|
||||
}
|
||||
|
||||
typename AnimType::Type current() {
|
||||
return _data ? _data->a.current() : AnimType::Type();
|
||||
}
|
||||
|
||||
typename AnimType::Type current(uint64 ms, const typename AnimType::Type &def) {
|
||||
return animating(ms) ? current() : def;
|
||||
}
|
||||
|
||||
void setup(const typename AnimType::Type &from, Callbacks *update) {
|
||||
if (!_data) {
|
||||
_data = new Data(from, update, animation(this, &SimpleAnimation<AnimType>::step));
|
||||
} else {
|
||||
delete update;
|
||||
_data->a = AnimType(from, from);
|
||||
}
|
||||
}
|
||||
|
||||
void start(const typename AnimType::Type &to, float64 duration, anim::transition transition = anim::linear) {
|
||||
if (_data) {
|
||||
_data->a.start(to);
|
||||
_data->_a.start();
|
||||
_data->duration = duration;
|
||||
_data->transition = transition;
|
||||
}
|
||||
}
|
||||
|
||||
~SimpleAnimation() {
|
||||
delete _data;
|
||||
setBadPointer(_data);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef struct _Data {
|
||||
_Data(const typename AnimType::Type &from, Callbacks *update, AnimationCallbacks *acb)
|
||||
: a(from, from)
|
||||
, _a(acb)
|
||||
, update(update)
|
||||
, duration(0)
|
||||
, transition(anim::linear) {
|
||||
}
|
||||
~_Data() {
|
||||
delete update;
|
||||
setBadPointer(update);
|
||||
}
|
||||
AnimType a;
|
||||
Animation _a;
|
||||
Callbacks *update;
|
||||
float64 duration;
|
||||
anim::transition transition;
|
||||
} Data;
|
||||
Data *_data;
|
||||
|
||||
void step(float64 ms, bool timer) {
|
||||
float64 dt = (ms >= _data->duration) ? 1 : (ms / _data->duration);
|
||||
if (dt >= 1) {
|
||||
_data->a.finish();
|
||||
_data->_a.stop();
|
||||
} else {
|
||||
_data->a.update(dt, _data->transition);
|
||||
}
|
||||
if (timer) {
|
||||
_data->update->call();
|
||||
}
|
||||
if (!_data->_a.animating()) {
|
||||
delete _data;
|
||||
_data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef SimpleAnimation<anim::fvalue> FloatAnimation;
|
||||
typedef SimpleAnimation<anim::ivalue> IntAnimation;
|
||||
typedef SimpleAnimation<anim::cvalue> ColorAnimation;
|
||||
|
||||
#define EnsureAnimation(animation, from, callback) if ((animation).isNull()) { (animation).setup((from), (callback)); }
|
||||
|
||||
class ClipReader;
|
||||
|
||||
class AnimationManager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AnimationManager();
|
||||
|
||||
AnimationManager() : _timer(this), _iterating(false) {
|
||||
_timer.setSingleShot(false);
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(timeout()));
|
||||
}
|
||||
|
||||
void start(Animation *obj) {
|
||||
if (_iterating) {
|
||||
_starting.insert(obj, NullType());
|
||||
if (!_stopping.isEmpty()) {
|
||||
_stopping.remove(obj);
|
||||
}
|
||||
} else {
|
||||
if (_objects.isEmpty()) {
|
||||
_timer.start(AnimationTimerDelta);
|
||||
}
|
||||
_objects.insert(obj, NullType());
|
||||
}
|
||||
}
|
||||
|
||||
void stop(Animation *obj) {
|
||||
if (_iterating) {
|
||||
_stopping.insert(obj, NullType());
|
||||
if (!_starting.isEmpty()) {
|
||||
_starting.insert(obj, NullType());
|
||||
}
|
||||
} else {
|
||||
AnimatingObjects::iterator i = _objects.find(obj);
|
||||
if (i != _objects.cend()) {
|
||||
_objects.erase(i);
|
||||
if (_objects.isEmpty()) {
|
||||
_timer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void start(Animation *obj);
|
||||
void stop(Animation *obj);
|
||||
|
||||
public slots:
|
||||
void timeout();
|
||||
|
||||
void timeout() {
|
||||
_iterating = true;
|
||||
uint64 ms = getms();
|
||||
for (AnimatingObjects::const_iterator i = _objects.begin(), e = _objects.end(); i != e; ++i) {
|
||||
i.key()->step(ms, true);
|
||||
}
|
||||
_iterating = false;
|
||||
|
||||
if (!_starting.isEmpty()) {
|
||||
for (AnimatingObjects::iterator i = _starting.begin(), e = _starting.end(); i != e; ++i) {
|
||||
_objects.insert(i.key(), NullType());
|
||||
}
|
||||
_starting.clear();
|
||||
}
|
||||
if (!_stopping.isEmpty()) {
|
||||
for (AnimatingObjects::iterator i = _stopping.begin(), e = _stopping.end(); i != e; ++i) {
|
||||
_objects.remove(i.key());
|
||||
}
|
||||
_stopping.clear();
|
||||
}
|
||||
if (!_objects.size()) {
|
||||
_timer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void clipReinit(ClipReader *reader);
|
||||
void clipRedraw(ClipReader *reader);
|
||||
void clipReinit(ClipReader *reader, qint32 threadIndex);
|
||||
void clipRepaint(ClipReader *reader, qint32 threadIndex);
|
||||
|
||||
private:
|
||||
|
||||
typedef QMap<Animation*, NullType> AnimatingObjects;
|
||||
AnimatingObjects _objects, _starting, _stopping;
|
||||
QTimer _timer;
|
||||
bool _iterating;
|
||||
|
||||
};
|
||||
|
||||
class FileLocation;
|
||||
|
||||
enum ClipState {
|
||||
|
@ -460,11 +508,19 @@ private:
|
|||
|
||||
};
|
||||
|
||||
enum ClipReaderNotification {
|
||||
ClipReaderReinit,
|
||||
ClipReaderRepaint,
|
||||
};
|
||||
|
||||
class ClipReaderPrivate;
|
||||
class ClipReader {
|
||||
public:
|
||||
|
||||
ClipReader(const FileLocation &location, const QByteArray &data);
|
||||
typedef Function1<void, ClipReaderNotification> Callback;
|
||||
|
||||
ClipReader(const FileLocation &location, const QByteArray &data, Callback *cb = 0);
|
||||
static void callback(ClipReader *reader, int32 threadIndex, ClipReaderNotification notification); // reader can be deleted
|
||||
|
||||
void setAutoplay() {
|
||||
_autoplay = true;
|
||||
|
@ -484,6 +540,9 @@ public:
|
|||
bool paused() const {
|
||||
return _paused.get();
|
||||
}
|
||||
int32 threadIndex() const {
|
||||
return _threadIndex;
|
||||
}
|
||||
|
||||
int32 width() const;
|
||||
int32 height() const;
|
||||
|
@ -501,6 +560,8 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
Callback *_cb;
|
||||
|
||||
ClipState _state;
|
||||
|
||||
ClipFrameRequest _request;
|
||||
|
@ -527,7 +588,7 @@ enum ClipProcessResult {
|
|||
ClipProcessError,
|
||||
ClipProcessStarted,
|
||||
ClipProcessReinit,
|
||||
ClipProcessRedraw,
|
||||
ClipProcessRepaint,
|
||||
ClipProcessWait,
|
||||
};
|
||||
|
||||
|
@ -544,14 +605,15 @@ public:
|
|||
void start(ClipReader *reader);
|
||||
void update(ClipReader *reader);
|
||||
void stop(ClipReader *reader);
|
||||
bool carries(ClipReader *reader) const;
|
||||
~ClipReadManager();
|
||||
|
||||
signals:
|
||||
|
||||
void processDelayed();
|
||||
|
||||
void reinit(ClipReader *reader);
|
||||
void redraw(ClipReader *reader);
|
||||
void reinit(ClipReader *reader, qint32 threadIndex);
|
||||
void repaint(ClipReader *reader, qint32 threadIndex);
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -565,7 +627,7 @@ private:
|
|||
QAtomicInt _loadLevel;
|
||||
typedef QMap<ClipReader*, ClipReaderPrivate*> ReaderPointers;
|
||||
ReaderPointers _readerPointers;
|
||||
QMutex _readerPointersMutex;
|
||||
mutable QMutex _readerPointersMutex;
|
||||
|
||||
bool handleProcessResult(ClipReaderPrivate *reader, ClipProcessResult result, uint64 ms);
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ namespace {
|
|||
static const uint64 RoundedCacheSkip = 0x4000000000000000LLU;
|
||||
}
|
||||
|
||||
StorageImageLocation StorageImageLocation::Null;
|
||||
|
||||
bool Image::isNull() const {
|
||||
return (this == blank());
|
||||
}
|
||||
|
@ -688,6 +690,11 @@ void StorageImage::automaticLoad(const HistoryItem *item) {
|
|||
}
|
||||
}
|
||||
|
||||
void StorageImage::automaticLoadSettingsChanged() {
|
||||
if (loaded() || _loader != CancelledFileLoader) return;
|
||||
_loader = 0;
|
||||
}
|
||||
|
||||
void StorageImage::load(bool loadFirst, bool prior) {
|
||||
if (loaded()) return;
|
||||
|
||||
|
|
|
@ -89,6 +89,8 @@ public:
|
|||
return _secret;
|
||||
}
|
||||
|
||||
static StorageImageLocation Null;
|
||||
|
||||
private:
|
||||
uint64 _widthheight;
|
||||
uint64 _dclocal;
|
||||
|
@ -118,6 +120,8 @@ public:
|
|||
|
||||
virtual void automaticLoad(const HistoryItem *item) { // auto load photo
|
||||
}
|
||||
virtual void automaticLoadSettingsChanged() {
|
||||
}
|
||||
|
||||
virtual bool loaded() const {
|
||||
return true;
|
||||
|
@ -164,6 +168,10 @@ public:
|
|||
virtual void loadEvenCancelled(bool loadFirst = false, bool prior = true) {
|
||||
}
|
||||
|
||||
virtual const StorageImageLocation &location() const {
|
||||
return StorageImageLocation::Null;
|
||||
}
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
void forget() const;
|
||||
|
@ -226,6 +234,7 @@ public:
|
|||
int32 height() const;
|
||||
|
||||
void automaticLoad(const HistoryItem *item); // auto load photo
|
||||
void automaticLoadSettingsChanged();
|
||||
|
||||
bool loaded() const;
|
||||
bool loading() const {
|
||||
|
@ -241,6 +250,10 @@ public:
|
|||
void load(bool loadFirst = false, bool prior = true);
|
||||
void loadEvenCancelled(bool loadFirst = false, bool prior = true);
|
||||
|
||||
virtual const StorageImageLocation &location() const {
|
||||
return _location;
|
||||
}
|
||||
|
||||
~StorageImage();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -148,6 +148,9 @@ QRect myrtlrect(const QRect &r) { \
|
|||
void rtlupdate(const QRect &r) { \
|
||||
update(myrtlrect(r)); \
|
||||
} \
|
||||
void rtlupdate(int x, int y, int w, int h) { \
|
||||
update(myrtlrect(x, y, w, h)); \
|
||||
} \
|
||||
protected: \
|
||||
void enterEvent(QEvent *e) { \
|
||||
TWidget *p(tparent()); \
|
||||
|
|
|
@ -884,7 +884,14 @@ HistoryItem *ChannelHistory::addNewToBlocks(const MTPMessage &msg, NewMessageTyp
|
|||
} else {
|
||||
to = blocks.back();
|
||||
}
|
||||
return addNewItem(to, newBlock, createItem(to, msg, (type == NewMessageUnread)), (type == NewMessageUnread));
|
||||
HistoryItem *item = createItem((type == NewMessageLast) ? 0 : to, msg, (type == NewMessageUnread));
|
||||
if (type == NewMessageLast) {
|
||||
if (!item->detached()) {
|
||||
return item;
|
||||
}
|
||||
item->attach(to);
|
||||
}
|
||||
return addNewItem(to, newBlock, item, (type == NewMessageUnread));
|
||||
}
|
||||
|
||||
void ChannelHistory::addNewToOther(HistoryItem *item, NewMessageType type) {
|
||||
|
@ -1331,14 +1338,17 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
|
|||
}
|
||||
result->attach(block);
|
||||
}
|
||||
if (result) {
|
||||
if (msg.type() == mtpc_message) {
|
||||
result->updateMedia(msg.c_message().has_media() ? (&msg.c_message().vmedia) : 0, (block ? false : true));
|
||||
if (msg.type() == mtpc_message) {
|
||||
result->updateMedia(msg.c_message().has_media() ? (&msg.c_message().vmedia) : 0, (block ? false : true));
|
||||
if (applyServiceAction) {
|
||||
App::checkSavedGif(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool hasNotForwardedDocument = false;
|
||||
|
||||
switch (msg.type()) {
|
||||
case mtpc_messageEmpty:
|
||||
result = new HistoryServiceMsg(this, block, msg.c_messageEmpty().vid.v, date(), lang(lng_message_empty));
|
||||
|
@ -1387,7 +1397,7 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
|
|||
break;
|
||||
case mtpc_messageMediaDocument:
|
||||
switch (m.vmedia.c_messageMediaDocument().vdocument.type()) {
|
||||
case mtpc_document: break;
|
||||
case mtpc_document: hasNotForwardedDocument = true; break;
|
||||
case mtpc_documentEmpty: badMedia = 2; break;
|
||||
default: badMedia = 1; break;
|
||||
}
|
||||
|
@ -1406,9 +1416,11 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
|
|||
}
|
||||
if (badMedia) {
|
||||
result = new HistoryServiceMsg(this, block, m.vid.v, date(m.vdate), lang((badMedia == 2) ? lng_message_empty : lng_media_unsupported), m.vflags.v, 0, m.has_from_id() ? m.vfrom_id.v : 0);
|
||||
hasNotForwardedDocument = false;
|
||||
} else {
|
||||
if ((m.has_fwd_date() && m.vfwd_date.v > 0) || (m.has_fwd_from_id() && peerFromMTP(m.vfwd_from_id) != 0)) {
|
||||
result = new HistoryForwarded(this, block, m);
|
||||
hasNotForwardedDocument = false;
|
||||
} else if (m.has_reply_to_msg_id() && m.vreply_to_msg_id.v > 0) {
|
||||
result = new HistoryReply(this, block, m);
|
||||
} else {
|
||||
|
@ -1543,6 +1555,10 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
|
|||
} break;
|
||||
}
|
||||
|
||||
if (applyServiceAction) {
|
||||
App::checkSavedGif(result);
|
||||
}
|
||||
|
||||
return regItem(result);
|
||||
}
|
||||
|
||||
|
@ -3122,21 +3138,22 @@ void HistoryFileMedia::step_thumbOver(const HistoryItem *parent, float64 ms, boo
|
|||
_animation->a_thumbOver.finish();
|
||||
_animation->_a_thumbOver.stop();
|
||||
checkAnimationFinished();
|
||||
} else {
|
||||
} else if (!timer) {
|
||||
_animation->a_thumbOver.update(dt, anim::linear);
|
||||
}
|
||||
if (timer) {
|
||||
Ui::redrawHistoryItem(parent);
|
||||
Ui::repaintHistoryItem(parent);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryFileMedia::step_radial(const HistoryItem *parent, uint64 ms, bool timer) {
|
||||
_animation->radial.update(dataProgress(), dataFinished(), ms);
|
||||
if (!_animation->radial.animating()) {
|
||||
checkAnimationFinished();
|
||||
}
|
||||
if (timer) {
|
||||
Ui::redrawHistoryItem(parent);
|
||||
Ui::repaintHistoryItem(parent);
|
||||
} else {
|
||||
_animation->radial.update(dataProgress(), dataFinished(), ms);
|
||||
if (!_animation->radial.animating()) {
|
||||
checkAnimationFinished();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3344,8 +3361,7 @@ void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
|
|||
p.setPen(Qt::NoPen);
|
||||
if (selected) {
|
||||
p.setBrush(st::msgDateImgBgSelected);
|
||||
} else if (_animation && _animation->_a_thumbOver.animating()) {
|
||||
_animation->_a_thumbOver.step(ms);
|
||||
} else if (isThumbAnimation(ms)) {
|
||||
float64 over = _animation->a_thumbOver.current();
|
||||
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
|
||||
p.setBrush(st::black);
|
||||
|
@ -3636,8 +3652,7 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
|
|||
p.setPen(Qt::NoPen);
|
||||
if (selected) {
|
||||
p.setBrush(st::msgDateImgBgSelected);
|
||||
} else if (_animation && _animation->_a_thumbOver.animating()) {
|
||||
_animation->_a_thumbOver.step(ms);
|
||||
} else if (isThumbAnimation(ms)) {
|
||||
float64 over = _animation->a_thumbOver.current();
|
||||
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
|
||||
p.setBrush(st::black);
|
||||
|
@ -3835,8 +3850,7 @@ void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
|
|||
p.setPen(Qt::NoPen);
|
||||
if (selected) {
|
||||
p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected);
|
||||
} else if (_animation && _animation->_a_thumbOver.animating()) {
|
||||
_animation->_a_thumbOver.step(ms);
|
||||
} else if (isThumbAnimation(ms)) {
|
||||
float64 over = _animation->a_thumbOver.current();
|
||||
p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over));
|
||||
} else {
|
||||
|
@ -4079,8 +4093,7 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
|||
p.setPen(Qt::NoPen);
|
||||
if (selected) {
|
||||
p.setBrush(st::msgDateImgBgSelected);
|
||||
} else if (_animation && _animation->_a_thumbOver.animating()) {
|
||||
_animation->_a_thumbOver.step(ms);
|
||||
} else if (isThumbAnimation(ms)) {
|
||||
float64 over = _animation->a_thumbOver.current();
|
||||
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
|
||||
p.setBrush(st::black);
|
||||
|
@ -4128,7 +4141,7 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
|||
p.setPen(Qt::NoPen);
|
||||
if (selected) {
|
||||
p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected);
|
||||
} else if (_animation && _animation->_a_thumbOver.animating()) {
|
||||
} else if (isThumbAnimation(ms)) {
|
||||
float64 over = _animation->a_thumbOver.current();
|
||||
p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over));
|
||||
} else {
|
||||
|
@ -4432,7 +4445,7 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
|
|||
|
||||
_data->automaticLoad(parent);
|
||||
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
|
||||
if (loaded && !gif() && _gif != BadClipReader) {
|
||||
if (loaded && !gif() && _gif != BadClipReader && cAutoPlayGif()) {
|
||||
const_cast<HistoryGif*>(this)->playInline(const_cast<HistoryItem*>(parent));
|
||||
if (gif()) _gif->setAutoplay();
|
||||
}
|
||||
|
@ -4467,7 +4480,7 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
|
|||
QRect rthumb(rtlrect(skipx, skipy, width, height, _width));
|
||||
|
||||
if (animating) {
|
||||
p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, Ui::isMediaViewShown() ? 0 : ms));
|
||||
p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, (Ui::isLayerShown() || Ui::isMediaViewShown() || Ui::isGifBeingChosen()) ? 0 : ms));
|
||||
} else {
|
||||
p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(_thumbw, _thumbh, width, height));
|
||||
}
|
||||
|
@ -4475,14 +4488,13 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
|
|||
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
|
||||
}
|
||||
|
||||
if (radial || (!_gif && !loaded && !_data->loading()) || (_gif == BadClipReader)) {
|
||||
if (radial || (!_gif && ((!loaded && !_data->loading()) || !cAutoPlayGif())) || (_gif == BadClipReader)) {
|
||||
float64 radialOpacity = (radial && loaded && !_data->uploading()) ? _animation->radial.opacity() : 1;
|
||||
QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||
p.setPen(Qt::NoPen);
|
||||
if (selected) {
|
||||
p.setBrush(st::msgDateImgBgSelected);
|
||||
} else if (_animation && _animation->_a_thumbOver.animating()) {
|
||||
_animation->_a_thumbOver.step(ms);
|
||||
} else if (isThumbAnimation(ms)) {
|
||||
float64 over = _animation->a_thumbOver.current();
|
||||
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
|
||||
p.setBrush(st::black);
|
||||
|
@ -4544,7 +4556,7 @@ void HistoryGif::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x,
|
|||
if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) {
|
||||
if (_data->uploading()) {
|
||||
lnk = _cancell;
|
||||
} else if (!gif()) {
|
||||
} else if (!gif() || !cAutoPlayGif()) {
|
||||
lnk = _data->loaded() ? _openl : (_data->loading() ? _cancell : _savel);
|
||||
}
|
||||
if (parent->getMedia() == this) {
|
||||
|
@ -4611,6 +4623,9 @@ bool HistoryGif::playInline(HistoryItem *parent) {
|
|||
if (gif()) {
|
||||
stopInline(parent);
|
||||
} else {
|
||||
if (!cAutoPlayGif()) {
|
||||
App::stopGifItems();
|
||||
}
|
||||
_gif = new ClipReader(_data->location(), _data->data());
|
||||
App::regGifItem(_gif, parent);
|
||||
}
|
||||
|
@ -5135,7 +5150,8 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) {
|
|||
_maxw += st::msgPadding.left() + st::webPageLeft + st::msgPadding.right();
|
||||
_minh += st::msgPadding.bottom();
|
||||
if (_asArticle) {
|
||||
_minh += st::msgDateFont->height;
|
||||
_minh = resize(_maxw, parent); // hack
|
||||
// _minh += st::msgDateFont->height;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5411,7 +5427,12 @@ const QString HistoryWebPage::inHistoryText() const {
|
|||
}
|
||||
|
||||
ImagePtr HistoryWebPage::replyPreview() {
|
||||
return _data->photo ? _data->photo->makeReplyPreview() : (_data->doc ? _data->doc->makeReplyPreview() : ImagePtr());
|
||||
return _attach ? _attach->replyPreview() : (_data->photo ? _data->photo->makeReplyPreview() : ImagePtr());
|
||||
}
|
||||
|
||||
HistoryWebPage::~HistoryWebPage() {
|
||||
delete _attach;
|
||||
setBadPointer(_attach);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -5999,12 +6020,6 @@ int32 HistoryMessage::plainMaxWidth() const {
|
|||
|
||||
void HistoryMessage::initDimensions() {
|
||||
if (drawBubble()) {
|
||||
_maxw = plainMaxWidth();
|
||||
if (_text.isEmpty()) {
|
||||
_minh = 0;
|
||||
} else {
|
||||
_minh = st::msgPadding.top() + _text.minHeight() + st::msgPadding.bottom();
|
||||
}
|
||||
if (_media) {
|
||||
_media->initDimensions(this);
|
||||
if (_media->isDisplayed()) {
|
||||
|
@ -6013,15 +6028,24 @@ void HistoryMessage::initDimensions() {
|
|||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
}
|
||||
int32 maxw = _media->maxWidth();
|
||||
if (maxw > _maxw) _maxw = maxw;
|
||||
_minh += _media->minHeight();
|
||||
} else if (!_text.hasSkipBlock()) {
|
||||
_text.setSkipBlock(skipBlockWidth(), skipBlockHeight());
|
||||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_maxw = plainMaxWidth();
|
||||
if (_text.isEmpty()) {
|
||||
_minh = 0;
|
||||
} else {
|
||||
_minh = st::msgPadding.top() + _text.minHeight() + st::msgPadding.bottom();
|
||||
}
|
||||
if (_media && _media->isDisplayed()) {
|
||||
int32 maxw = _media->maxWidth();
|
||||
if (maxw > _maxw) _maxw = maxw;
|
||||
_minh += _media->minHeight();
|
||||
}
|
||||
} else {
|
||||
_media->initDimensions(this);
|
||||
_maxw = _media->maxWidth();
|
||||
|
@ -6211,7 +6235,7 @@ void HistoryMessage::setViewsCount(int32 count) {
|
|||
_viewsText = (_views >= 0) ? formatViewsCount(_views) : QString();
|
||||
_viewsWidth = _viewsText.isEmpty() ? 0 : st::msgDateFont->width(_viewsText);
|
||||
if (was == _viewsWidth) {
|
||||
Ui::redrawHistoryItem(this);
|
||||
Ui::repaintHistoryItem(this);
|
||||
} else {
|
||||
if (_text.hasSkipBlock()) {
|
||||
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
|
||||
|
@ -6227,7 +6251,7 @@ void HistoryMessage::setId(MsgId newId) {
|
|||
bool wasPositive = (id > 0), positive = (newId > 0);
|
||||
HistoryItem::setId(newId);
|
||||
if (wasPositive == positive) {
|
||||
Ui::redrawHistoryItem(this);
|
||||
Ui::repaintHistoryItem(this);
|
||||
} else {
|
||||
if (_text.hasSkipBlock()) {
|
||||
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
|
||||
|
|
|
@ -1235,6 +1235,12 @@ protected:
|
|||
_animation->radial.step(ms);
|
||||
return _animation && _animation->radial.animating();
|
||||
}
|
||||
bool isThumbAnimation(uint64 ms) const {
|
||||
if (!_animation || !_animation->_a_thumbOver.animating()) return false;
|
||||
|
||||
_animation->_a_thumbOver.step(ms);
|
||||
return _animation && _animation->_a_thumbOver.animating();
|
||||
}
|
||||
|
||||
virtual float64 dataProgress() const = 0;
|
||||
virtual bool dataFinished() const = 0;
|
||||
|
@ -1812,6 +1818,12 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
HistoryMedia *attach() const {
|
||||
return _attach;
|
||||
}
|
||||
|
||||
~HistoryWebPage();
|
||||
|
||||
private:
|
||||
WebPageData *_data;
|
||||
TextLinkPtr _openl;
|
||||
|
@ -2175,6 +2187,13 @@ public:
|
|||
return _text.adjustSelection(from, to, type);
|
||||
}
|
||||
|
||||
void linkOver(const TextLinkPtr &lnk) {
|
||||
if (_media) _media->linkOver(this, lnk);
|
||||
}
|
||||
void linkOut(const TextLinkPtr &lnk) {
|
||||
if (_media) _media->linkOut(this, lnk);
|
||||
}
|
||||
|
||||
void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const;
|
||||
QString notificationText() const;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
// flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html
|
||||
|
||||
HistoryInner::HistoryInner(HistoryWidget *historyWidget, ScrollArea *scroll, History *history) : QWidget(0)
|
||||
HistoryInner::HistoryInner(HistoryWidget *historyWidget, ScrollArea *scroll, History *history) : TWidget(0)
|
||||
, _peer(history->peer)
|
||||
, _migrated(history->peer->migrateFrom() ? App::history(history->peer->migrateFrom()->id) : 0)
|
||||
, _history(history)
|
||||
|
@ -116,7 +116,7 @@ void HistoryInner::messagesReceivedDown(PeerData *peer, const QVector<MTPMessage
|
|||
}
|
||||
}
|
||||
|
||||
void HistoryInner::redrawItem(const HistoryItem *item) {
|
||||
void HistoryInner::repaintItem(const HistoryItem *item) {
|
||||
if (!item || item->detached() || !_history) return;
|
||||
int32 msgy = itemTop(item);
|
||||
if (msgy >= 0) {
|
||||
|
@ -475,16 +475,16 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
|||
if (button != Qt::LeftButton) return;
|
||||
|
||||
if (App::pressedItem() != App::hoveredItem()) {
|
||||
redrawItem(App::pressedItem());
|
||||
repaintItem(App::pressedItem());
|
||||
App::pressedItem(App::hoveredItem());
|
||||
redrawItem(App::pressedItem());
|
||||
repaintItem(App::pressedItem());
|
||||
}
|
||||
if (textlnkDown() != textlnkOver()) {
|
||||
redrawItem(App::pressedLinkItem());
|
||||
repaintItem(App::pressedLinkItem());
|
||||
textlnkDown(textlnkOver());
|
||||
App::pressedLinkItem(App::hoveredLinkItem());
|
||||
redrawItem(App::pressedLinkItem());
|
||||
redrawItem(App::pressedItem());
|
||||
repaintItem(App::pressedLinkItem());
|
||||
repaintItem(App::pressedItem());
|
||||
}
|
||||
|
||||
_dragAction = NoDrag;
|
||||
|
@ -512,7 +512,7 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
|||
uint32 selStatus = (symbol << 16) | symbol;
|
||||
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
if (!_selected.isEmpty()) {
|
||||
redrawItem(_selected.cbegin().key());
|
||||
repaintItem(_selected.cbegin().key());
|
||||
_selected.clear();
|
||||
}
|
||||
_selected.insert(_dragItem, selStatus);
|
||||
|
@ -553,12 +553,12 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
|||
uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
|
||||
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
if (!_selected.isEmpty()) {
|
||||
redrawItem(_selected.cbegin().key());
|
||||
repaintItem(_selected.cbegin().key());
|
||||
_selected.clear();
|
||||
}
|
||||
_selected.insert(_dragItem, selStatus);
|
||||
_dragAction = Selecting;
|
||||
redrawItem(_dragItem);
|
||||
repaintItem(_dragItem);
|
||||
} else {
|
||||
_dragAction = PrepareSelect;
|
||||
}
|
||||
|
@ -717,7 +717,7 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
|
|||
}
|
||||
}
|
||||
if (textlnkDown()) {
|
||||
redrawItem(App::pressedLinkItem());
|
||||
repaintItem(App::pressedLinkItem());
|
||||
textlnkDown(TextLinkPtr());
|
||||
App::pressedLinkItem(0);
|
||||
if (!textlnkOver() && _cursor != style::cur_default) {
|
||||
|
@ -726,7 +726,7 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
|
|||
}
|
||||
}
|
||||
if (App::pressedItem()) {
|
||||
redrawItem(App::pressedItem());
|
||||
repaintItem(App::pressedItem());
|
||||
App::pressedItem(0);
|
||||
}
|
||||
|
||||
|
@ -750,16 +750,16 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
|
|||
} else {
|
||||
_selected.erase(i);
|
||||
}
|
||||
redrawItem(_dragItem);
|
||||
repaintItem(_dragItem);
|
||||
} else if (_dragAction == PrepareDrag && !_dragWasInactive && button != Qt::RightButton) {
|
||||
SelectedItems::iterator i = _selected.find(_dragItem);
|
||||
if (i != _selected.cend() && i.value() == FullSelection) {
|
||||
_selected.erase(i);
|
||||
redrawItem(_dragItem);
|
||||
repaintItem(_dragItem);
|
||||
} else if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
|
||||
if (_selected.size() < MaxSelectedItems) {
|
||||
_selected.insert(_dragItem, FullSelection);
|
||||
redrawItem(_dragItem);
|
||||
repaintItem(_dragItem);
|
||||
}
|
||||
} else {
|
||||
_selected.clear();
|
||||
|
@ -804,7 +804,7 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) {
|
|||
_dragAction = Selecting;
|
||||
uint32 selStatus = (symbol << 16) | symbol;
|
||||
if (!_selected.isEmpty()) {
|
||||
redrawItem(_selected.cbegin().key());
|
||||
repaintItem(_selected.cbegin().key());
|
||||
_selected.clear();
|
||||
}
|
||||
_selected.insert(_dragItem, selStatus);
|
||||
|
@ -928,15 +928,35 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
}
|
||||
if (item && !isUponSelected && !_contextMenuLnk) {
|
||||
if (HistoryMedia *media = (msg ? msg->getMedia() : 0)) {
|
||||
if (media->type() == MediaTypeWebPage && static_cast<HistoryWebPage*>(media)->attach()) {
|
||||
media = static_cast<HistoryWebPage*>(media)->attach();
|
||||
}
|
||||
if (media->type() == MediaTypeSticker) {
|
||||
DocumentData *doc = media->getDocument();
|
||||
if (doc && doc->sticker() && doc->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
||||
_menu->addAction(lang(doc->sticker()->setInstalled() ? lng_context_pack_info : lng_context_pack_add), _widget, SLOT(onStickerPackInfo()));
|
||||
}
|
||||
|
||||
_menu->addAction(lang(lng_context_save_image), this, SLOT(saveContextFile()))->setEnabled(true);
|
||||
} else if (media->type() == MediaTypeGif) {
|
||||
DocumentData *doc = media->getDocument();
|
||||
if (doc) {
|
||||
if (doc->loading()) {
|
||||
_menu->addAction(lang(lng_context_cancel_download), this, SLOT(cancelContextDownload()))->setEnabled(true);
|
||||
} else {
|
||||
if (doc->mime.toLower() == qstr("video/mp4") && doc->type == AnimatedDocument) {
|
||||
_menu->addAction(lang(lng_context_save_gif), this, SLOT(saveContextGif()))->setEnabled(true);
|
||||
}
|
||||
if (!doc->already(true).isEmpty()) {
|
||||
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), this, SLOT(showContextInFolder()))->setEnabled(true);
|
||||
}
|
||||
_menu->addAction(lang(lng_context_save_file), this, SLOT(saveContextFile()))->setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
QString contextMenuText = item->selectedText(FullSelection);
|
||||
if (!contextMenuText.isEmpty() && (!msg || !msg->getMedia() || msg->getMedia()->type() != MediaTypeSticker)) {
|
||||
if (!contextMenuText.isEmpty() && (!msg || !msg->getMedia() || _dragCursorState == HistoryInTextCursorState)) {
|
||||
_menu->addAction(lang(lng_context_copy_text), this, SLOT(copyContextText()))->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
@ -1047,23 +1067,36 @@ void HistoryInner::copyContextImage() {
|
|||
}
|
||||
|
||||
void HistoryInner::cancelContextDownload() {
|
||||
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
if (lnkVideo) {
|
||||
if (VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data())) {
|
||||
lnkVideo->video()->cancel();
|
||||
} else if (lnkAudio) {
|
||||
} else if (AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data())) {
|
||||
lnkAudio->audio()->cancel();
|
||||
} else if (lnkDocument) {
|
||||
} else if (DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data())) {
|
||||
lnkDocument->document()->cancel();
|
||||
} else if (HistoryItem *item = App::contextItem()) {
|
||||
if (HistoryMedia *media = item->getMedia()) {
|
||||
if (DocumentData *doc = media->getDocument()) {
|
||||
doc->cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryInner::showContextInFolder() {
|
||||
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
QString already = lnkVideo ? lnkVideo->video()->already(true) : (lnkAudio ? lnkAudio->audio()->already(true) : (lnkDocument ? lnkDocument->document()->already(true) : QString()));
|
||||
QString already;
|
||||
if (VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data())) {
|
||||
already = lnkVideo->video()->already(true);
|
||||
} else if (AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data())) {
|
||||
already = lnkAudio->audio()->already(true);
|
||||
} else if (DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data())) {
|
||||
already = lnkDocument->document()->already(true);
|
||||
} else if (HistoryItem *item = App::contextItem()) {
|
||||
if (HistoryMedia *media = item->getMedia()) {
|
||||
if (DocumentData *doc = media->getDocument()) {
|
||||
already = doc->already(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!already.isEmpty()) psShowInFolder(already);
|
||||
}
|
||||
|
||||
|
@ -1080,12 +1113,29 @@ void HistoryInner::openContextFile() {
|
|||
}
|
||||
|
||||
void HistoryInner::saveContextFile() {
|
||||
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
if (lnkVideo) VideoSaveLink::doSave(lnkVideo->video(), true);
|
||||
if (lnkAudio) AudioSaveLink::doSave(lnkAudio->audio(), true);
|
||||
if (lnkDocument) DocumentSaveLink::doSave(lnkDocument->document(), true);
|
||||
if (VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data())) {
|
||||
VideoSaveLink::doSave(lnkVideo->video(), true);
|
||||
} else if (AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data())) {
|
||||
AudioSaveLink::doSave(lnkAudio->audio(), true);
|
||||
} else if (DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data())) {
|
||||
DocumentSaveLink::doSave(lnkDocument->document(), true);
|
||||
} else if (HistoryItem *item = App::contextItem()) {
|
||||
if (HistoryMedia *media = item->getMedia()) {
|
||||
if (DocumentData *doc = media->getDocument()) {
|
||||
DocumentSaveLink::doSave(doc, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryInner::saveContextGif() {
|
||||
if (HistoryItem *item = App::contextItem()) {
|
||||
if (HistoryMedia *media = item->getMedia()) {
|
||||
if (DocumentData *doc = media->getDocument()) {
|
||||
_widget->saveGif(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryInner::copyContextText() {
|
||||
|
@ -1345,13 +1395,13 @@ void HistoryInner::enterEvent(QEvent *e) {
|
|||
|
||||
void HistoryInner::leaveEvent(QEvent *e) {
|
||||
if (HistoryItem *item = App::hoveredItem()) {
|
||||
redrawItem(item);
|
||||
repaintItem(item);
|
||||
App::hoveredItem(0);
|
||||
}
|
||||
if (textlnkOver()) {
|
||||
if (HistoryItem *item = App::hoveredLinkItem()) {
|
||||
item->linkOut(textlnkOver());
|
||||
redrawItem(item);
|
||||
repaintItem(item);
|
||||
App::hoveredLinkItem(0);
|
||||
}
|
||||
textlnkOver(TextLinkPtr());
|
||||
|
@ -1524,12 +1574,12 @@ void HistoryInner::onUpdateSelected() {
|
|||
m = mapMouseToItem(point, item);
|
||||
if (item->hasPoint(m.x(), m.y())) {
|
||||
if (App::hoveredItem() != item) {
|
||||
redrawItem(App::hoveredItem());
|
||||
repaintItem(App::hoveredItem());
|
||||
App::hoveredItem(item);
|
||||
redrawItem(App::hoveredItem());
|
||||
repaintItem(App::hoveredItem());
|
||||
}
|
||||
} else if (App::hoveredItem()) {
|
||||
redrawItem(App::hoveredItem());
|
||||
repaintItem(App::hoveredItem());
|
||||
App::hoveredItem(0);
|
||||
}
|
||||
}
|
||||
|
@ -1557,7 +1607,7 @@ void HistoryInner::onUpdateSelected() {
|
|||
if (textlnkOver()) {
|
||||
if (HistoryItem *item = App::hoveredLinkItem()) {
|
||||
item->linkOut(textlnkOver());
|
||||
redrawItem(item);
|
||||
repaintItem(item);
|
||||
} else {
|
||||
update(_botDescRect);
|
||||
}
|
||||
|
@ -1568,7 +1618,7 @@ void HistoryInner::onUpdateSelected() {
|
|||
if (textlnkOver()) {
|
||||
if (HistoryItem *item = App::hoveredLinkItem()) {
|
||||
item->linkOver(textlnkOver());
|
||||
redrawItem(item);
|
||||
repaintItem(item);
|
||||
} else {
|
||||
update(_botDescRect);
|
||||
}
|
||||
|
@ -1610,7 +1660,7 @@ void HistoryInner::onUpdateSelected() {
|
|||
uint32 selState = _dragItem->adjustSelection(qMin(second, _dragSymbol), qMax(second, _dragSymbol), _dragSelType);
|
||||
if (_selected[_dragItem] != selState) {
|
||||
_selected[_dragItem] = selState;
|
||||
Ui::redrawHistoryItem(_dragItem);
|
||||
repaintItem(_dragItem);
|
||||
}
|
||||
if (!_wasSelectedText && (selState == FullSelection || (selState & 0xFFFF) != ((selState >> 16) & 0xFFFF))) {
|
||||
_wasSelectedText = true;
|
||||
|
@ -2561,6 +2611,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
, _replyForwardPressed(false)
|
||||
, _replyReturn(0)
|
||||
, _stickersUpdateRequest(0)
|
||||
, _savedGifsUpdateRequest(0)
|
||||
, _peer(0)
|
||||
, _clearPeer(0)
|
||||
, _channel(NoChannel)
|
||||
|
@ -2744,7 +2795,11 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
|
||||
void HistoryWidget::start() {
|
||||
connect(App::main(), SIGNAL(stickersUpdated()), &_emojiPan, SLOT(refreshStickers()));
|
||||
connect(App::main(), SIGNAL(savedGifsUpdated()), &_emojiPan, SLOT(refreshSavedGifs()));
|
||||
|
||||
updateRecentStickers();
|
||||
if (App::main()) emit App::main()->savedGifsUpdated();
|
||||
|
||||
connect(App::api(), SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*)));
|
||||
}
|
||||
|
||||
|
@ -2948,11 +3003,16 @@ void HistoryWidget::onRecordUpdate(qint16 level, qint32 samples) {
|
|||
}
|
||||
|
||||
void HistoryWidget::updateStickers() {
|
||||
if (cLastStickersUpdate() && getms(true) < cLastStickersUpdate() + StickersUpdateTimeout) return;
|
||||
if (_stickersUpdateRequest) return;
|
||||
|
||||
cSetStickersHash(stickersCountHash(true));
|
||||
_stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_int(cStickersHash())), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed));
|
||||
if (!cLastStickersUpdate() || getms(true) >= cLastStickersUpdate() + StickersUpdateTimeout) {
|
||||
if (!_stickersUpdateRequest) {
|
||||
_stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_int(Local::countStickersHash(true))), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed));
|
||||
}
|
||||
}
|
||||
if (!cLastSavedGifsUpdate() || getms(true) >= cLastSavedGifsUpdate() + StickersUpdateTimeout) {
|
||||
if (!_savedGifsUpdateRequest) {
|
||||
_savedGifsUpdateRequest = MTP::send(MTPmessages_GetSavedGifs(MTP_int(Local::countSavedGifsHash())), rpcDone(&HistoryWidget::savedGifsGot), rpcFail(&HistoryWidget::savedGifsFailed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::notify_botCommandsChanged(UserData *user) {
|
||||
|
@ -2993,7 +3053,7 @@ void HistoryWidget::notify_migrateUpdated(PeerData *peer) {
|
|||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::notify_mediaViewHidden() {
|
||||
void HistoryWidget::notify_clipStopperHidden(ClipStopperType type) {
|
||||
if (_list) _list->update();
|
||||
}
|
||||
|
||||
|
@ -3062,10 +3122,8 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
|
|||
}
|
||||
}
|
||||
|
||||
int32 countedHash = stickersCountHash();
|
||||
cSetStickersHash(countedHash);
|
||||
if (countedHash != d.vhash.v) {
|
||||
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(countedHash));
|
||||
if (Local::countStickersHash() != d.vhash.v) {
|
||||
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countStickersHash()));
|
||||
}
|
||||
|
||||
if (!setsToRequest.isEmpty() && App::api()) {
|
||||
|
@ -3091,6 +3149,61 @@ bool HistoryWidget::stickersFailed(const RPCError &error) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void HistoryWidget::savedGifsGot(const MTPmessages_SavedGifs &gifs) {
|
||||
cSetLastSavedGifsUpdate(getms(true));
|
||||
_savedGifsUpdateRequest = 0;
|
||||
|
||||
if (gifs.type() != mtpc_messages_savedGifs) return;
|
||||
const MTPDmessages_savedGifs &d(gifs.c_messages_savedGifs());
|
||||
|
||||
const QVector<MTPDocument> &d_gifs(d.vgifs.c_vector().v);
|
||||
|
||||
SavedGifs &saved(cRefSavedGifs());
|
||||
saved.clear();
|
||||
|
||||
saved.reserve(d_gifs.size());
|
||||
for (int32 i = 0, l = d_gifs.size(); i != l; ++i) {
|
||||
DocumentData *doc = App::feedDocument(d_gifs.at(i));
|
||||
if (!doc || !doc->isAnimation()) {
|
||||
LOG(("API Error: bad document returned in HistoryWidget::savedGifsGot!"));
|
||||
continue;
|
||||
}
|
||||
|
||||
saved.push_back(doc);
|
||||
}
|
||||
if (Local::countSavedGifsHash() != d.vhash.v) {
|
||||
LOG(("API Error: received saved gifs hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countSavedGifsHash()));
|
||||
}
|
||||
|
||||
Local::writeSavedGifs();
|
||||
|
||||
if (App::main()) emit App::main()->savedGifsUpdated();
|
||||
}
|
||||
|
||||
void HistoryWidget::saveGif(DocumentData *doc) {
|
||||
if (doc->mime.toLower() == qstr("video/mp4") && doc->type == AnimatedDocument) {
|
||||
if (cSavedGifs().indexOf(doc) != 0) {
|
||||
MTP::send(MTPmessages_SaveGif(MTP_inputDocument(MTP_long(doc->id), MTP_long(doc->access)), MTP_bool(false)), rpcDone(&HistoryWidget::saveGifDone, doc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::saveGifDone(DocumentData *doc, const MTPBool &result) {
|
||||
if (mtpIsTrue(result)) {
|
||||
App::addSavedGif(doc);
|
||||
}
|
||||
}
|
||||
|
||||
bool HistoryWidget::savedGifsFailed(const RPCError &error) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
|
||||
LOG(("App Fail: Failed to get saved gifs!"));
|
||||
|
||||
cSetLastSavedGifsUpdate(getms(true));
|
||||
_savedGifsUpdateRequest = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HistoryWidget::clearReplyReturns() {
|
||||
_replyReturns.clear();
|
||||
_replyReturn = 0;
|
||||
|
@ -3232,7 +3345,9 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
|||
}
|
||||
}
|
||||
|
||||
// App::stopGifItems();
|
||||
if (!cAutoPlayGif()) {
|
||||
App::stopGifItems();
|
||||
}
|
||||
clearReplyReturns();
|
||||
|
||||
clearAllLoadRequests();
|
||||
|
@ -5448,7 +5563,7 @@ void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
|
|||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadPhoto, 0);
|
||||
}
|
||||
Ui::redrawHistoryItem(item);
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5460,7 +5575,7 @@ void HistoryWidget::onDocumentProgress(const FullMsgId &newId) {
|
|||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadFile, doc ? doc->uploadOffset : 0);
|
||||
}
|
||||
Ui::redrawHistoryItem(item);
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5471,7 +5586,7 @@ void HistoryWidget::onAudioProgress(const FullMsgId &newId) {
|
|||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadAudio, audio ? audio->uploadOffset : 0);
|
||||
}
|
||||
Ui::redrawHistoryItem(item);
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5482,7 +5597,7 @@ void HistoryWidget::onPhotoFailed(const FullMsgId &newId) {
|
|||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadPhoto, -1);
|
||||
}
|
||||
// Ui::redrawHistoryItem(item);
|
||||
// Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5493,7 +5608,7 @@ void HistoryWidget::onDocumentFailed(const FullMsgId &newId) {
|
|||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadFile, -1);
|
||||
}
|
||||
Ui::redrawHistoryItem(item);
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5504,7 +5619,7 @@ void HistoryWidget::onAudioFailed(const FullMsgId &newId) {
|
|||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadAudio, -1);
|
||||
}
|
||||
Ui::redrawHistoryItem(item);
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5602,12 +5717,24 @@ bool HistoryWidget::isItemVisible(HistoryItem *item) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void HistoryWidget::ui_redrawHistoryItem(const HistoryItem *item) {
|
||||
void HistoryWidget::ui_repaintHistoryItem(const HistoryItem *item) {
|
||||
if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) {
|
||||
_list->redrawItem(item);
|
||||
_list->repaintItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::ui_repaintSavedGif(const LayoutSavedGif *layout) {
|
||||
_emojiPan.ui_repaintSavedGif(layout);
|
||||
}
|
||||
|
||||
bool HistoryWidget::ui_isSavedGifVisible(const LayoutSavedGif *layout) {
|
||||
return _emojiPan.ui_isSavedGifVisible(layout) || _attachMention.ui_isSavedGifVisible(layout);
|
||||
}
|
||||
|
||||
bool HistoryWidget::ui_isGifBeingChosen() {
|
||||
return _emojiPan.ui_isGifBeingChosen() || _attachMention.ui_isGifBeingChosen();
|
||||
}
|
||||
|
||||
void HistoryWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
|
||||
if (_peer && _list && (item == App::mousedItem() || item == App::hoveredItem() || item == App::hoveredLinkItem())) {
|
||||
_list->onUpdateSelected();
|
||||
|
@ -6527,7 +6654,7 @@ void HistoryWidget::onAnimActiveStep() {
|
|||
if (getms() - _animActiveStart > st::activeFadeInDuration + st::activeFadeOutDuration) {
|
||||
stopAnimActive();
|
||||
} else {
|
||||
Ui::redrawHistoryItem(item);
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ enum DragState {
|
|||
};
|
||||
|
||||
class HistoryWidget;
|
||||
class HistoryInner : public QWidget {
|
||||
class HistoryInner : public TWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -69,7 +69,7 @@ public:
|
|||
int32 recountHeight(const HistoryItem *resizedItem);
|
||||
void updateSize();
|
||||
|
||||
void redrawItem(const HistoryItem *item);
|
||||
void repaintItem(const HistoryItem *item);
|
||||
|
||||
bool canCopySelected() const;
|
||||
bool canDeleteSelected() const;
|
||||
|
@ -114,6 +114,7 @@ public slots:
|
|||
void showContextInFolder();
|
||||
void openContextFile();
|
||||
void saveContextFile();
|
||||
void saveContextGif();
|
||||
void copyContextText();
|
||||
void copySelectedText();
|
||||
|
||||
|
@ -541,6 +542,8 @@ public:
|
|||
|
||||
void updateNotifySettings();
|
||||
|
||||
void saveGif(DocumentData *doc);
|
||||
|
||||
bool contentOverlapped(const QRect &globalRect);
|
||||
|
||||
void grabStart() {
|
||||
|
@ -556,13 +559,16 @@ public:
|
|||
|
||||
bool isItemVisible(HistoryItem *item);
|
||||
|
||||
void ui_redrawHistoryItem(const HistoryItem *item);
|
||||
void ui_repaintHistoryItem(const HistoryItem *item);
|
||||
void ui_repaintSavedGif(const LayoutSavedGif *gif);
|
||||
bool ui_isSavedGifVisible(const LayoutSavedGif *layout);
|
||||
bool ui_isGifBeingChosen();
|
||||
|
||||
void notify_historyItemLayoutChanged(const HistoryItem *item);
|
||||
void notify_botCommandsChanged(UserData *user);
|
||||
void notify_userIsBotChanged(UserData *user);
|
||||
void notify_migrateUpdated(PeerData *peer);
|
||||
void notify_mediaViewHidden();
|
||||
void notify_clipStopperHidden(ClipStopperType type);
|
||||
void notify_historyItemResized(const HistoryItem *item, bool scrollToIt);
|
||||
|
||||
~HistoryWidget();
|
||||
|
@ -701,6 +707,8 @@ private:
|
|||
void addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed);
|
||||
void addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed);
|
||||
|
||||
void saveGifDone(DocumentData *doc, const MTPBool &result);
|
||||
|
||||
void reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId request);
|
||||
bool reportSpamFail(const RPCError &error, mtpRequestId request);
|
||||
|
||||
|
@ -713,10 +721,13 @@ private:
|
|||
|
||||
void countHistoryShowFrom();
|
||||
|
||||
mtpRequestId _stickersUpdateRequest;
|
||||
void stickersGot(const MTPmessages_AllStickers &stickers);
|
||||
bool stickersFailed(const RPCError &error);
|
||||
|
||||
mtpRequestId _stickersUpdateRequest;
|
||||
mtpRequestId _savedGifsUpdateRequest;
|
||||
void savedGifsGot(const MTPmessages_SavedGifs &gifs);
|
||||
bool savedGifsFailed(const RPCError &error);
|
||||
|
||||
void writeDraft(MsgId *replyTo = 0, const QString *text = 0, const MessageCursor *cursor = 0, bool *previewCancelled = 0);
|
||||
void setFieldText(const QString &text);
|
||||
|
|
|
@ -195,6 +195,7 @@ StickerPreviewWidget::StickerPreviewWidget(QWidget *parent) : TWidget(parent)
|
|||
, a_shown(0, 0)
|
||||
, _a_shown(animation(this, &StickerPreviewWidget::step_shown))
|
||||
, _doc(0)
|
||||
, _gif(0)
|
||||
, _cacheStatus(CacheNotLoaded) {
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
}
|
||||
|
@ -232,7 +233,7 @@ void StickerPreviewWidget::step_shown(float64 ms, bool timer) {
|
|||
}
|
||||
|
||||
void StickerPreviewWidget::showPreview(DocumentData *sticker) {
|
||||
if (sticker && !sticker->sticker()) sticker = 0;
|
||||
if (sticker && !sticker->isAnimation() && !sticker->sticker()) sticker = 0;
|
||||
if (sticker) {
|
||||
_cache = QPixmap();
|
||||
if (isHidden() || _a_shown.animating()) {
|
||||
|
@ -245,10 +246,17 @@ void StickerPreviewWidget::showPreview(DocumentData *sticker) {
|
|||
} else if (isHidden()) {
|
||||
return;
|
||||
} else {
|
||||
if (_gif) _cache = currentImage();
|
||||
a_shown.start(0);
|
||||
_a_shown.start();
|
||||
}
|
||||
_doc = sticker;
|
||||
if (_gif) {
|
||||
if (gif()) {
|
||||
delete _gif;
|
||||
}
|
||||
_gif = 0;
|
||||
}
|
||||
_cacheStatus = CacheNotLoaded;
|
||||
}
|
||||
|
||||
|
@ -259,7 +267,10 @@ void StickerPreviewWidget::hidePreview() {
|
|||
QSize StickerPreviewWidget::currentDimensions() const {
|
||||
if (!_doc) return QSize(_cache.width() / cIntRetinaFactor(), _cache.height() / cIntRetinaFactor());
|
||||
|
||||
QSize result(qMax(_doc->dimensions.width(), 1), qMax(_doc->dimensions.height(), 1));
|
||||
QSize result(qMax(convertScale(_doc->dimensions.width()), 1), qMax(convertScale(_doc->dimensions.height()), 1));
|
||||
if (gif() && _gif->ready()) {
|
||||
result = QSize(qMax(convertScale(_gif->width()), 1), qMax(convertScale(_gif->height()), 1));
|
||||
}
|
||||
if (result.width() > st::maxStickerSize) {
|
||||
result.setHeight(qMax(qRound((st::maxStickerSize * result.height()) / result.width()), 1));
|
||||
result.setWidth(st::maxStickerSize);
|
||||
|
@ -272,22 +283,64 @@ QSize StickerPreviewWidget::currentDimensions() const {
|
|||
}
|
||||
|
||||
QPixmap StickerPreviewWidget::currentImage() const {
|
||||
if (_doc && _cacheStatus != CacheLoaded) {
|
||||
_doc->checkSticker();
|
||||
if (_doc->sticker()->img->isNull()) {
|
||||
if (_cacheStatus != CacheThumbLoaded) {
|
||||
if (_doc) {
|
||||
if (_doc->sticker()) {
|
||||
if (_cacheStatus != CacheLoaded) {
|
||||
_doc->checkSticker();
|
||||
if (_doc->sticker()->img->isNull()) {
|
||||
if (_cacheStatus != CacheThumbLoaded && _doc->thumb->loaded()) {
|
||||
QSize s = currentDimensions();
|
||||
_cache = _doc->thumb->pixBlurred(s.width(), s.height());
|
||||
_cacheStatus = CacheThumbLoaded;
|
||||
}
|
||||
} else {
|
||||
QSize s = currentDimensions();
|
||||
_cache = _doc->sticker()->img->pix(s.width(), s.height());
|
||||
_cacheStatus = CacheLoaded;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_doc->automaticLoad(0);
|
||||
if (_doc->loaded()) {
|
||||
if (!_gif && _gif != BadClipReader) {
|
||||
StickerPreviewWidget *that = const_cast<StickerPreviewWidget*>(this);
|
||||
that->_gif = new ClipReader(_doc->location(), _doc->data(), func(that, &StickerPreviewWidget::clipCallback));
|
||||
if (gif()) _gif->setAutoplay();
|
||||
}
|
||||
}
|
||||
if (gif() && _gif->started()) {
|
||||
QSize s = currentDimensions();
|
||||
return _gif->current(s.width(), s.height(), s.width(), s.height(), getms());
|
||||
}
|
||||
if (_cacheStatus != CacheThumbLoaded && _doc->thumb->loaded()) {
|
||||
QSize s = currentDimensions();
|
||||
_cache = _doc->thumb->pixBlurred(s.width(), s.height());
|
||||
_cacheStatus = CacheThumbLoaded;
|
||||
}
|
||||
} else {
|
||||
QSize s = currentDimensions();
|
||||
_cache = _doc->sticker()->img->pix(s.width(), s.height());
|
||||
_cacheStatus = CacheLoaded;
|
||||
}
|
||||
}
|
||||
return _cache;
|
||||
}
|
||||
|
||||
void StickerPreviewWidget::clipCallback(ClipReaderNotification notification) {
|
||||
switch (notification) {
|
||||
case ClipReaderReinit: {
|
||||
if (gif() && _gif->state() == ClipError) {
|
||||
delete _gif;
|
||||
_gif = BadClipReader;
|
||||
}
|
||||
|
||||
if (gif() && _gif->ready() && !_gif->started()) {
|
||||
QSize s = currentDimensions();
|
||||
_gif->start(s.width(), s.height(), s.width(), s.height(), false);
|
||||
}
|
||||
|
||||
update();
|
||||
} break;
|
||||
|
||||
case ClipReaderRepaint: update(); break;
|
||||
}
|
||||
}
|
||||
|
||||
StickerPreviewWidget::~StickerPreviewWidget() {
|
||||
}
|
||||
|
|
|
@ -131,6 +131,12 @@ private:
|
|||
anim::fvalue a_shown;
|
||||
Animation _a_shown;
|
||||
DocumentData *_doc;
|
||||
ClipReader *_gif;
|
||||
bool gif() const {
|
||||
return (!_gif || _gif == BadClipReader) ? false : true;
|
||||
}
|
||||
|
||||
void clipCallback(ClipReaderNotification notification);
|
||||
|
||||
enum CacheStatus {
|
||||
CacheNotLoaded,
|
||||
|
|
|
@ -227,21 +227,22 @@ void LayoutRadialProgressItem::step_iconOver(float64 ms, bool timer) {
|
|||
if (dt >= 1) {
|
||||
a_iconOver.finish();
|
||||
_a_iconOver.stop();
|
||||
} else {
|
||||
} else if (!timer) {
|
||||
a_iconOver.update(dt, anim::linear);
|
||||
}
|
||||
if (timer && iconAnimated()) {
|
||||
Ui::redrawHistoryItem(_parent);
|
||||
Ui::repaintHistoryItem(_parent);
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutRadialProgressItem::step_radial(uint64 ms, bool timer) {
|
||||
_radial->update(dataProgress(), dataFinished(), ms);
|
||||
if (!_radial->animating()) {
|
||||
checkRadialFinished();
|
||||
}
|
||||
if (timer) {
|
||||
Ui::redrawHistoryItem(_parent);
|
||||
Ui::repaintHistoryItem(_parent);
|
||||
} else {
|
||||
_radial->update(dataProgress(), dataFinished(), ms);
|
||||
if (!_radial->animating()) {
|
||||
checkRadialFinished();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -590,6 +591,7 @@ void LayoutOverviewAudio::paint(Painter &p, const QRect &clip, uint32 selection,
|
|||
if (selected) {
|
||||
p.setBrush(st::msgFileInBgSelected);
|
||||
} else if (_a_iconOver.animating()) {
|
||||
_a_iconOver.step(context->ms);
|
||||
float64 over = a_iconOver.current();
|
||||
p.setBrush(style::interpolate(st::msgFileInBg, st::msgFileInBgOver, over));
|
||||
} else {
|
||||
|
@ -787,6 +789,7 @@ void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selecti
|
|||
if (selected) {
|
||||
p.setBrush(st::msgFileInBgSelected);
|
||||
} else if (_a_iconOver.animating()) {
|
||||
_a_iconOver.step(context->ms);
|
||||
float64 over = a_iconOver.current();
|
||||
p.setBrush(style::interpolate(st::msgFileInBg, st::msgFileInBgOver, over));
|
||||
} else {
|
||||
|
@ -1280,3 +1283,230 @@ LayoutOverviewLink::Link::Link(const QString &url, const QString &text)
|
|||
, width(st::normalFont->width(text))
|
||||
, lnk(linkFromUrl(url)) {
|
||||
}
|
||||
|
||||
LayoutSavedGif::LayoutSavedGif(DocumentData *data)
|
||||
: _data(data)
|
||||
, _position(0)
|
||||
, _width(st::savedGifMinWidth)
|
||||
, _state(0)
|
||||
, _gif(0)
|
||||
, _animation(0) {
|
||||
}
|
||||
|
||||
void LayoutSavedGif::setPosition(int32 position, int32 width) {
|
||||
_position = position;
|
||||
_width = width;
|
||||
if (_position < 0) {
|
||||
if (gif()) delete _gif;
|
||||
_gif = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutSavedGif::setWidth(int32 width) {
|
||||
_width = width;
|
||||
}
|
||||
|
||||
int32 LayoutSavedGif::position() const {
|
||||
return _position;
|
||||
}
|
||||
|
||||
int32 LayoutSavedGif::width() const {
|
||||
return _width;
|
||||
}
|
||||
|
||||
void LayoutSavedGif::notify_over(bool over) {
|
||||
if (!_data->loaded()) {
|
||||
ensureAnimation();
|
||||
if (over == !(_state & StateOver)) {
|
||||
EnsureAnimation(_animation->_a_over, (_state & StateOver) ? 1 : 0, (func(this, &LayoutSavedGif::update)));
|
||||
_animation->_a_over.start(over ? 1 : 0, st::stickersRowDuration);
|
||||
}
|
||||
}
|
||||
if (over) {
|
||||
_state |= StateOver;
|
||||
} else {
|
||||
_state &= ~StateOver;
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutSavedGif::notify_deleteOver(bool over) {
|
||||
if (over == !(_state & StateDeleteOver)) {
|
||||
EnsureAnimation(_a_deleteOver, (_state & StateDeleteOver) ? 1 : 0, func(this, &LayoutSavedGif::update));
|
||||
if (over) {
|
||||
_state |= StateDeleteOver;
|
||||
} else {
|
||||
_state &= ~StateDeleteOver;
|
||||
}
|
||||
_a_deleteOver.start((_state & StateDeleteOver) ? 1 : 0, st::stickersRowDuration);
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutSavedGif::paint(Painter &p, bool paused, uint64 ms) const {
|
||||
_data->automaticLoad(0);
|
||||
|
||||
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
|
||||
if (loaded && !gif() && _gif != BadClipReader) {
|
||||
LayoutSavedGif *that = const_cast<LayoutSavedGif*>(this);
|
||||
that->_gif = new ClipReader(_data->location(), _data->data(), func(that, &LayoutSavedGif::clipCallback));
|
||||
if (gif()) _gif->setAutoplay();
|
||||
}
|
||||
|
||||
bool animating = (gif() && _gif->started());
|
||||
if (displayLoading) {
|
||||
ensureAnimation();
|
||||
if (!_animation->radial.animating()) {
|
||||
_animation->radial.start(_data->progress());
|
||||
}
|
||||
}
|
||||
bool radial = isRadialAnimation(ms);
|
||||
|
||||
int32 height = st::savedGifHeight;
|
||||
QSize frame = countFrameSize();
|
||||
|
||||
QRect r(0, 0, _width, height);
|
||||
if (animating) {
|
||||
if (!_thumb.isNull()) const_cast<LayoutSavedGif*>(this)->_thumb = QPixmap();
|
||||
p.drawPixmap(r.topLeft(), _gif->current(frame.width(), frame.height(), _width, height, paused ? 0 : ms));
|
||||
} else {
|
||||
if (!_data->thumb->isNull()) {
|
||||
if (_data->thumb->loaded()) {
|
||||
if (_thumb.width() != _width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) {
|
||||
const_cast<LayoutSavedGif*>(this)->_thumb = _data->thumb->pixNoCache(frame.width(), frame.height(), true, false, false, _width, height);
|
||||
}
|
||||
} else {
|
||||
_data->thumb->load();
|
||||
}
|
||||
}
|
||||
p.drawPixmap(r.topLeft(), _thumb);
|
||||
}
|
||||
|
||||
if (radial || (!_gif && !loaded && !_data->loading()) || (_gif == BadClipReader)) {
|
||||
float64 radialOpacity = (radial && loaded && !_data->uploading()) ? _animation->radial.opacity() : 1;
|
||||
if (_animation && _animation->_a_over.animating(ms)) {
|
||||
float64 over = _animation->_a_over.current();
|
||||
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
|
||||
p.fillRect(r, st::black);
|
||||
} else {
|
||||
p.fillRect(r, (_state & StateOver) ? st::msgDateImgBgOver : st::msgDateImgBg);
|
||||
}
|
||||
p.setOpacity(radialOpacity * p.opacity());
|
||||
|
||||
p.setOpacity(radialOpacity);
|
||||
style::sprite icon;
|
||||
if (_data->loaded() && !radial) {
|
||||
icon = st::msgFileInPlay;
|
||||
} else if (radial || _data->loading()) {
|
||||
icon = st::msgFileInCancel;
|
||||
} else {
|
||||
icon = st::msgFileInDownload;
|
||||
}
|
||||
QRect inner((_width - st::msgFileSize) / 2, (height - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||
p.drawSpriteCenter(inner, icon);
|
||||
if (radial) {
|
||||
p.setOpacity(1);
|
||||
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
||||
_animation->radial.draw(p, rinner, st::msgFileRadialLine, st::msgInBg);
|
||||
}
|
||||
}
|
||||
|
||||
if (_state & StateOver) {
|
||||
float64 deleteOver = _a_deleteOver.current(ms, (_state & StateDeleteOver) ? 1 : 0);
|
||||
QPoint deletePos = QPoint(_width - st::stickerPanDelete.pxWidth(), 0);
|
||||
p.setOpacity(deleteOver + (1 - deleteOver) * st::stickerPanDeleteOpacity);
|
||||
p.drawSpriteLeft(deletePos, _width, st::stickerPanDelete);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
}
|
||||
|
||||
QSize LayoutSavedGif::countFrameSize() const {
|
||||
bool animating = (gif() && _gif->ready());
|
||||
int32 framew = animating ? _gif->width() : _data->thumb->width(), frameh = animating ? _gif->height() : _data->thumb->height(), height = st::savedGifHeight;
|
||||
if (framew * height > frameh * _width) {
|
||||
if (framew < st::maxStickerSize || frameh > height) {
|
||||
if (frameh > height || (framew * height / frameh) <= st::maxStickerSize) {
|
||||
framew = framew * height / frameh;
|
||||
frameh = height;
|
||||
} else {
|
||||
frameh = int32(frameh * st::maxStickerSize) / framew;
|
||||
framew = st::maxStickerSize;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (frameh < st::maxStickerSize || framew > _width) {
|
||||
if (framew > _width || (frameh * _width / framew) <= st::maxStickerSize) {
|
||||
frameh = frameh * _width / framew;
|
||||
framew = _width;
|
||||
} else {
|
||||
framew = int32(framew * st::maxStickerSize) / frameh;
|
||||
frameh = st::maxStickerSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QSize(framew, frameh);
|
||||
}
|
||||
|
||||
void LayoutSavedGif::preload() {
|
||||
_data->thumb->load();
|
||||
}
|
||||
|
||||
LayoutSavedGif::~LayoutSavedGif() {
|
||||
delete _animation;
|
||||
setBadPointer(_animation);
|
||||
}
|
||||
|
||||
void LayoutSavedGif::ensureAnimation() const {
|
||||
if (!_animation) {
|
||||
_animation = new AnimationData(animation(const_cast<LayoutSavedGif*>(this), &LayoutSavedGif::step_radial));
|
||||
}
|
||||
}
|
||||
|
||||
bool LayoutSavedGif::isRadialAnimation(uint64 ms) const {
|
||||
if (!_animation || !_animation->radial.animating()) return false;
|
||||
|
||||
_animation->radial.step(ms);
|
||||
return _animation && _animation->radial.animating();
|
||||
}
|
||||
|
||||
void LayoutSavedGif::step_radial(uint64 ms, bool timer) {
|
||||
if (timer) {
|
||||
update();
|
||||
} else {
|
||||
_animation->radial.update(_data->progress(), !_data->loading() || _data->loaded(), ms);
|
||||
if (!_animation->radial.animating() && _data->loaded()) {
|
||||
delete _animation;
|
||||
_animation = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutSavedGif::clipCallback(ClipReaderNotification notification) {
|
||||
switch (notification) {
|
||||
case ClipReaderReinit: {
|
||||
if (gif()) {
|
||||
if (_gif->state() == ClipError) {
|
||||
delete _gif;
|
||||
_gif = BadClipReader;
|
||||
_data->forget();
|
||||
} else if (_gif->ready() && !_gif->started()) {
|
||||
int32 height = st::savedGifHeight;
|
||||
QSize frame = countFrameSize();
|
||||
_gif->start(frame.width(), frame.height(), _width, height, false);
|
||||
} else if (_gif->paused() && !Ui::isSavedGifVisible(this)) {
|
||||
delete _gif;
|
||||
_gif = 0;
|
||||
_data->forget();
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
} break;
|
||||
|
||||
case ClipReaderRepaint: update(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutSavedGif::update() {
|
||||
if (_position >= 0) {
|
||||
Ui::repaintSavedGif(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -470,3 +470,62 @@ private:
|
|||
QVector<Link> _links;
|
||||
|
||||
};
|
||||
|
||||
class LayoutSavedGif {
|
||||
public:
|
||||
LayoutSavedGif(DocumentData *data);
|
||||
|
||||
void paint(Painter &p, bool paused, uint64 ms) const;
|
||||
void preload();
|
||||
DocumentData *document() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
void setPosition(int32 position, int32 width);
|
||||
void setWidth(int32 width);
|
||||
int32 position() const;
|
||||
int32 width() const;
|
||||
|
||||
void notify_over(bool over);
|
||||
void notify_deleteOver(bool over);
|
||||
|
||||
~LayoutSavedGif();
|
||||
|
||||
private:
|
||||
DocumentData *_data;
|
||||
int32 _position; // < 0 means removed from layout
|
||||
int32 _width;
|
||||
QSize countFrameSize() const;
|
||||
|
||||
enum StateFlags {
|
||||
StateOver = 0x01,
|
||||
StateDeleteOver = 0x02,
|
||||
};
|
||||
int32 _state;
|
||||
|
||||
ClipReader *_gif;
|
||||
bool gif() const {
|
||||
return (!_gif || _gif == BadClipReader) ? false : true;
|
||||
}
|
||||
QPixmap _thumb;
|
||||
|
||||
void ensureAnimation() const;
|
||||
bool isRadialAnimation(uint64 ms) const;
|
||||
void step_radial(uint64 ms, bool timer);
|
||||
|
||||
void clipCallback(ClipReaderNotification notification);
|
||||
void update();
|
||||
|
||||
struct AnimationData {
|
||||
AnimationData(AnimationCallbacks *radialCallbacks)
|
||||
: over(false)
|
||||
, radial(radialCallbacks) {
|
||||
}
|
||||
bool over;
|
||||
FloatAnimation _a_over;
|
||||
RadialAnimation radial;
|
||||
};
|
||||
mutable AnimationData *_animation;
|
||||
mutable FloatAnimation _a_deleteOver;
|
||||
|
||||
};
|
||||
|
|
|
@ -552,6 +552,7 @@ namespace {
|
|||
lskStickers = 0x0b, // no data
|
||||
lskSavedPeers = 0x0c, // no data
|
||||
lskReportSpamStatuses = 0x0d, // no data
|
||||
lskSavedGifs = 0x0e,
|
||||
};
|
||||
|
||||
typedef QMap<PeerId, FileKey> DraftsMap;
|
||||
|
@ -568,7 +569,7 @@ namespace {
|
|||
FileLocationAliases _fileLocationAliases;
|
||||
FileKey _locationsKey = 0, _reportSpamStatusesKey = 0;
|
||||
|
||||
FileKey _recentStickersKeyOld = 0, _stickersKey = 0;
|
||||
FileKey _recentStickersKeyOld = 0, _stickersKey = 0, _savedGifsKey;
|
||||
|
||||
FileKey _backgroundKey = 0;
|
||||
bool _backgroundWasRead = false;
|
||||
|
@ -797,6 +798,14 @@ namespace {
|
|||
cSetMaxGroupCount(maxSize);
|
||||
} break;
|
||||
|
||||
case dbiSavedGifsLimit: {
|
||||
qint32 limit;
|
||||
stream >> limit;
|
||||
if (!_checkStreamStatus(stream)) return false;
|
||||
|
||||
cSetSavedGifsLimit(limit);
|
||||
} break;
|
||||
|
||||
case dbiMaxMegaGroupCount: {
|
||||
qint32 maxSize;
|
||||
stream >> maxSize;
|
||||
|
@ -873,6 +882,14 @@ namespace {
|
|||
cSetAutoDownloadGif(gif);
|
||||
} break;
|
||||
|
||||
case dbiAutoPlay: {
|
||||
qint32 gif;
|
||||
stream >> gif;
|
||||
if (!_checkStreamStatus(stream)) return false;
|
||||
|
||||
cSetAutoPlayGif(gif == 1);
|
||||
} break;
|
||||
|
||||
case dbiIncludeMuted: {
|
||||
qint32 v;
|
||||
stream >> v;
|
||||
|
@ -881,6 +898,14 @@ namespace {
|
|||
cSetIncludeMuted(v == 1);
|
||||
} break;
|
||||
|
||||
case dbiShowingSavedGifs: {
|
||||
qint32 v;
|
||||
stream >> v;
|
||||
if (!_checkStreamStatus(stream)) return false;
|
||||
|
||||
cSetShowingSavedGifs(v == 1);
|
||||
} break;
|
||||
|
||||
case dbiDesktopNotify: {
|
||||
qint32 v;
|
||||
stream >> v;
|
||||
|
@ -1438,7 +1463,7 @@ namespace {
|
|||
_writeMap(WriteMapFast);
|
||||
}
|
||||
|
||||
uint32 size = 14 * (sizeof(quint32) + sizeof(qint32));
|
||||
uint32 size = 16 * (sizeof(quint32) + sizeof(qint32));
|
||||
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath()) + _bytearraySize(cAskDownloadPath() ? QByteArray() : cDownloadPathBookmark());
|
||||
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));
|
||||
|
@ -1454,6 +1479,7 @@ namespace {
|
|||
data.stream << quint32(dbiDefaultAttach) << qint32(cDefaultAttach());
|
||||
data.stream << quint32(dbiSoundNotify) << qint32(cSoundNotify());
|
||||
data.stream << quint32(dbiIncludeMuted) << qint32(cIncludeMuted());
|
||||
data.stream << quint32(dbiShowingSavedGifs) << qint32(cShowingSavedGifs());
|
||||
data.stream << quint32(dbiDesktopNotify) << qint32(cDesktopNotify());
|
||||
data.stream << quint32(dbiNotifyView) << qint32(cNotifyView());
|
||||
data.stream << quint32(dbiWindowsNotifications) << qint32(cWindowsNotifications());
|
||||
|
@ -1463,6 +1489,7 @@ namespace {
|
|||
data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
|
||||
data.stream << quint32(dbiSongVolume) << qint32(qRound(cSongVolume() * 1e6));
|
||||
data.stream << quint32(dbiAutoDownload) << qint32(cAutoDownloadPhoto()) << qint32(cAutoDownloadAudio()) << qint32(cAutoDownloadGif());
|
||||
data.stream << quint32(dbiAutoPlay) << qint32(cAutoPlayGif() ? 1 : 0);
|
||||
|
||||
{
|
||||
RecentEmojisPreload v(cRecentEmojisPreload());
|
||||
|
@ -1608,7 +1635,9 @@ namespace {
|
|||
DraftsNotReadMap draftsNotReadMap;
|
||||
StorageMap imagesMap, stickerImagesMap, audiosMap;
|
||||
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
|
||||
quint64 locationsKey = 0, reportSpamStatusesKey = 0, recentStickersKeyOld = 0, stickersKey = 0, backgroundKey = 0, userSettingsKey = 0, recentHashtagsKey = 0, savedPeersKey = 0;
|
||||
quint64 locationsKey = 0, reportSpamStatusesKey = 0;
|
||||
quint64 recentStickersKeyOld = 0, stickersKey = 0, savedGifsKey = 0;
|
||||
quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsKey = 0, savedPeersKey = 0;
|
||||
while (!map.stream.atEnd()) {
|
||||
quint32 keyType;
|
||||
map.stream >> keyType;
|
||||
|
@ -1691,6 +1720,9 @@ namespace {
|
|||
case lskStickers: {
|
||||
map.stream >> stickersKey;
|
||||
} break;
|
||||
case lskSavedGifs: {
|
||||
map.stream >> savedGifsKey;
|
||||
} break;
|
||||
case lskSavedPeers: {
|
||||
map.stream >> savedPeersKey;
|
||||
} break;
|
||||
|
@ -1718,6 +1750,7 @@ namespace {
|
|||
_reportSpamStatusesKey = reportSpamStatusesKey;
|
||||
_recentStickersKeyOld = recentStickersKeyOld;
|
||||
_stickersKey = stickersKey;
|
||||
_savedGifsKey = savedGifsKey;
|
||||
_savedPeersKey = savedPeersKey;
|
||||
_backgroundKey = backgroundKey;
|
||||
_userSettingsKey = userSettingsKey;
|
||||
|
@ -1790,6 +1823,7 @@ namespace {
|
|||
if (_reportSpamStatusesKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_recentStickersKeyOld) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_stickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_savedGifsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_userSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
|
@ -1837,6 +1871,9 @@ namespace {
|
|||
if (_stickersKey) {
|
||||
mapData.stream << quint32(lskStickers) << quint64(_stickersKey);
|
||||
}
|
||||
if (_savedGifsKey) {
|
||||
mapData.stream << quint32(lskSavedGifs) << quint64(_savedGifsKey);
|
||||
}
|
||||
if (_savedPeersKey) {
|
||||
mapData.stream << quint32(lskSavedPeers) << quint64(_savedPeersKey);
|
||||
}
|
||||
|
@ -2040,7 +2077,7 @@ namespace Local {
|
|||
cSetDcOptions(dcOpts);
|
||||
}
|
||||
|
||||
quint32 size = 11 * (sizeof(quint32) + sizeof(qint32));
|
||||
quint32 size = 12 * (sizeof(quint32) + sizeof(qint32));
|
||||
for (mtpDcOptions::const_iterator i = dcOpts.cbegin(), e = dcOpts.cend(); i != e; ++i) {
|
||||
size += sizeof(quint32) + sizeof(quint32) + sizeof(quint32);
|
||||
size += sizeof(quint32) + _stringSize(QString::fromUtf8(i->ip.data(), i->ip.size()));
|
||||
|
@ -2058,6 +2095,7 @@ namespace Local {
|
|||
EncryptedDescriptor data(size);
|
||||
data.stream << quint32(dbiMaxGroupCount) << qint32(cMaxGroupCount());
|
||||
data.stream << quint32(dbiMaxMegaGroupCount) << qint32(cMaxMegaGroupCount());
|
||||
data.stream << quint32(dbiSavedGifsLimit) << qint32(cSavedGifsLimit());
|
||||
data.stream << quint32(dbiAutoStart) << qint32(cAutoStart());
|
||||
data.stream << quint32(dbiStartMinimized) << qint32(cStartMinimized());
|
||||
data.stream << quint32(dbiSendToMenu) << qint32(cSendToMenu());
|
||||
|
@ -2111,7 +2149,9 @@ namespace Local {
|
|||
_stickerImagesMap.clear();
|
||||
_audiosMap.clear();
|
||||
_storageImagesSize = _storageStickersSize = _storageAudiosSize = 0;
|
||||
_locationsKey = _reportSpamStatusesKey = _recentStickersKeyOld = _stickersKey = _backgroundKey = _userSettingsKey = _recentHashtagsKey = _savedPeersKey = 0;
|
||||
_locationsKey = _reportSpamStatusesKey = 0;
|
||||
_recentStickersKeyOld = _stickersKey = _savedGifsKey = 0;
|
||||
_backgroundKey = _userSettingsKey = _recentHashtagsKey = _savedPeersKey = 0;
|
||||
_oldMapVersion = _oldSettingsVersion = 0;
|
||||
_mapChanged = true;
|
||||
_writeMap(WriteMapNow);
|
||||
|
@ -2667,7 +2707,7 @@ namespace Local {
|
|||
_writeMap();
|
||||
} else {
|
||||
int32 setsCount = 0;
|
||||
QByteArray hashToWrite = (qsl("%d:") + QString::number(cStickersHash())).toUtf8();
|
||||
QByteArray hashToWrite;
|
||||
quint32 size = sizeof(quint32) + _bytearraySize(hashToWrite);
|
||||
for (StickerSets::const_iterator i = sets.cbegin(); i != sets.cend(); ++i) {
|
||||
bool notLoaded = (i->flags & MTPDstickerSet_flag_NOT_LOADED);
|
||||
|
@ -2729,8 +2769,6 @@ namespace Local {
|
|||
RecentStickerPack &recent(cRefRecentStickers());
|
||||
recent.clear();
|
||||
|
||||
cSetStickersHash(0);
|
||||
|
||||
StickerSet &def(sets.insert(DefaultStickerSetId, StickerSet(DefaultStickerSetId, 0, lang(lng_stickers_default_set), QString(), 0, 0, MTPDstickerSet::flag_official)).value());
|
||||
StickerSet &custom(sets.insert(CustomStickerSetId, StickerSet(CustomStickerSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, 0)).value());
|
||||
|
||||
|
@ -2806,9 +2844,8 @@ namespace Local {
|
|||
|
||||
quint32 cnt;
|
||||
QByteArray hash;
|
||||
stickers.stream >> cnt >> hash;
|
||||
if (stickers.version < 8019) {
|
||||
hash.clear(); // bad data in old caches
|
||||
stickers.stream >> cnt >> hash; // ignore hash, it is counted
|
||||
if (stickers.version < 8019) { // bad data in old caches
|
||||
cnt += 2; // try to read at least something
|
||||
}
|
||||
for (uint32 i = 0; i < cnt; ++i) {
|
||||
|
@ -2886,11 +2923,124 @@ namespace Local {
|
|||
++set.count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hash.startsWith(qsl("%d:").toUtf8())) {
|
||||
cSetStickersHash(QString::fromUtf8(hash.mid(3)).toInt());
|
||||
int32 countStickersHash(bool checkOfficial) {
|
||||
uint32 acc = 0;
|
||||
bool foundOfficial = false, foundBad = false;;
|
||||
const StickerSets &sets(cStickerSets());
|
||||
const StickerSetsOrder &order(cStickerSetsOrder());
|
||||
for (StickerSetsOrder::const_iterator i = order.cbegin(), e = order.cend(); i != e; ++i) {
|
||||
StickerSets::const_iterator j = sets.constFind(*i);
|
||||
if (j != sets.cend()) {
|
||||
if (j->id == 0) {
|
||||
foundBad = true;
|
||||
} else if (j->flags & MTPDstickerSet::flag_official) {
|
||||
foundOfficial = true;
|
||||
}
|
||||
if (!(j->flags & MTPDstickerSet::flag_disabled)) {
|
||||
acc = (acc * 20261) + j->hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (!checkOfficial || (!foundBad && foundOfficial)) ? int32(acc & 0x7FFFFFFF) : 0;
|
||||
}
|
||||
|
||||
int32 countSavedGifsHash() {
|
||||
uint32 acc = 0;
|
||||
const SavedGifs &saved(cSavedGifs());
|
||||
for (SavedGifs::const_iterator i = saved.cbegin(), e = saved.cend(); i != e; ++i) {
|
||||
uint64 docId = (*i)->id;
|
||||
|
||||
acc = (acc * 20261) + uint32(docId >> 32);
|
||||
acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF);
|
||||
}
|
||||
return int32(acc & 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
void writeSavedGifs() {
|
||||
if (!_working()) return;
|
||||
|
||||
const SavedGifs &saved(cSavedGifs());
|
||||
if (saved.isEmpty()) {
|
||||
if (_savedGifsKey) {
|
||||
clearKey(_savedGifsKey);
|
||||
_savedGifsKey = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
_writeMap();
|
||||
} else {
|
||||
cSetStickersHash(0);
|
||||
quint32 size = sizeof(quint32); // count
|
||||
for (SavedGifs::const_iterator i = saved.cbegin(), e = saved.cend(); i != e; ++i) {
|
||||
DocumentData *doc = *i;
|
||||
|
||||
// id + access + date + namelen + name + mimelen + mime + dc + size + width + height + type
|
||||
size += sizeof(quint64) + sizeof(quint64) + sizeof(qint32) + _stringSize(doc->name) + _stringSize(doc->mime) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32);
|
||||
|
||||
// thumb
|
||||
size += _storageImageLocationSize();
|
||||
}
|
||||
|
||||
if (!_savedGifsKey) {
|
||||
_savedGifsKey = genKey();
|
||||
_mapChanged = true;
|
||||
_writeMap(WriteMapFast);
|
||||
}
|
||||
EncryptedDescriptor data(size);
|
||||
data.stream << quint32(saved.size());
|
||||
for (SavedGifs::const_iterator i = saved.cbegin(), e = saved.cend(); i != e; ++i) {
|
||||
DocumentData *doc = *i;
|
||||
|
||||
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);
|
||||
_writeStorageImageLocation(data.stream, doc->thumb->location());
|
||||
}
|
||||
FileWriteDescriptor file(_savedGifsKey);
|
||||
file.writeEncrypted(data);
|
||||
}
|
||||
}
|
||||
|
||||
void readSavedGifs() {
|
||||
if (!_savedGifsKey) return;
|
||||
|
||||
FileReadDescriptor gifs;
|
||||
if (!readEncryptedFile(gifs, _savedGifsKey)) {
|
||||
clearKey(_savedGifsKey);
|
||||
_savedGifsKey = 0;
|
||||
_writeMap();
|
||||
return;
|
||||
}
|
||||
|
||||
SavedGifs &saved(cRefSavedGifs());
|
||||
saved.clear();
|
||||
|
||||
quint32 cnt;
|
||||
gifs.stream >> cnt;
|
||||
saved.reserve(cnt);
|
||||
QMap<uint64, NullType> read;
|
||||
for (uint32 i = 0; i < cnt; ++i) {
|
||||
quint64 id, access;
|
||||
QString name, mime;
|
||||
qint32 date, dc, size, width, height, type;
|
||||
gifs.stream >> id >> access >> date >> name >> mime >> dc >> size >> width >> height >> type;
|
||||
|
||||
StorageImageLocation thumb(_readStorageImageLocation(gifs));
|
||||
|
||||
if (read.contains(id)) continue;
|
||||
read.insert(id, NullType());
|
||||
|
||||
QVector<MTPDocumentAttribute> attributes;
|
||||
if (!name.isEmpty()) attributes.push_back(MTP_documentAttributeFilename(MTP_string(name)));
|
||||
if (type == AnimatedDocument) {
|
||||
attributes.push_back(MTP_documentAttributeAnimated());
|
||||
}
|
||||
if (width > 0 && height > 0) {
|
||||
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));
|
||||
}
|
||||
|
||||
DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, thumb.isNull() ? ImagePtr() : ImagePtr(thumb), dc, size, thumb);
|
||||
if (!doc->isAnimation()) continue;
|
||||
|
||||
saved.push_back(doc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,6 +142,11 @@ namespace Local {
|
|||
|
||||
void writeStickers();
|
||||
void readStickers();
|
||||
int32 countStickersHash(bool checkOfficial = false);
|
||||
|
||||
void writeSavedGifs();
|
||||
void readSavedGifs();
|
||||
int32 countSavedGifsHash();
|
||||
|
||||
void writeBackground(int32 id, const QImage &img);
|
||||
bool readBackground();
|
||||
|
|
|
@ -742,7 +742,7 @@ QPixmap MainWidget::grabTopBar() {
|
|||
}
|
||||
|
||||
void MainWidget::ui_showStickerPreview(DocumentData *sticker) {
|
||||
if (!sticker || !sticker->sticker()) return;
|
||||
if (!sticker || ((!sticker->isAnimation() || !sticker->loaded()) && !sticker->sticker())) return;
|
||||
if (!_stickerPreview) {
|
||||
_stickerPreview = new StickerPreviewWidget(this);
|
||||
resizeEvent(0);
|
||||
|
@ -773,7 +773,7 @@ void MainWidget::notify_userIsContactChanged(UserData *user, bool fromThisApp) {
|
|||
if (i != items.cend()) {
|
||||
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
|
||||
j.key()->initDimensions();
|
||||
Ui::redrawHistoryItem(j.key());
|
||||
Ui::repaintHistoryItem(j.key());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -786,18 +786,28 @@ void MainWidget::notify_migrateUpdated(PeerData *peer) {
|
|||
history.notify_migrateUpdated(peer);
|
||||
}
|
||||
|
||||
void MainWidget::notify_mediaViewHidden() {
|
||||
history.notify_mediaViewHidden();
|
||||
void MainWidget::notify_clipStopperHidden(ClipStopperType type) {
|
||||
history.notify_clipStopperHidden(type);
|
||||
}
|
||||
|
||||
void MainWidget::ui_redrawHistoryItem(const HistoryItem *item) {
|
||||
if (!item) return;
|
||||
|
||||
history.ui_redrawHistoryItem(item);
|
||||
void MainWidget::ui_repaintHistoryItem(const HistoryItem *item) {
|
||||
history.ui_repaintHistoryItem(item);
|
||||
if (!item->history()->dialogs.isEmpty() && item->history()->lastMsg == item) {
|
||||
dialogs.dlgUpdated(item->history()->dialogs[0]);
|
||||
}
|
||||
if (overview) overview->ui_redrawHistoryItem(item);
|
||||
if (overview) overview->ui_repaintHistoryItem(item);
|
||||
}
|
||||
|
||||
void MainWidget::ui_repaintSavedGif(const LayoutSavedGif *layout) {
|
||||
history.ui_repaintSavedGif(layout);
|
||||
}
|
||||
|
||||
bool MainWidget::ui_isSavedGifVisible(const LayoutSavedGif *layout) {
|
||||
return history.ui_isSavedGifVisible(layout);
|
||||
}
|
||||
|
||||
bool MainWidget::ui_isGifBeingChosen() {
|
||||
return history.ui_isGifBeingChosen();
|
||||
}
|
||||
|
||||
void MainWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
|
||||
|
@ -814,7 +824,7 @@ void MainWidget::notify_historyItemResized(const HistoryItem *item, bool scrollT
|
|||
history.resizeEvent(0);
|
||||
}
|
||||
}
|
||||
if (item) Ui::redrawHistoryItem(item);
|
||||
if (item) Ui::repaintHistoryItem(item);
|
||||
}
|
||||
|
||||
void MainWidget::noHider(HistoryHider *destroyed) {
|
||||
|
@ -1638,7 +1648,7 @@ void MainWidget::videoLoadProgress(mtpFileLoader *loader) {
|
|||
VideoItems::const_iterator i = items.constFind(video);
|
||||
if (i != items.cend()) {
|
||||
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
|
||||
Ui::redrawHistoryItem(j.key());
|
||||
Ui::repaintHistoryItem(j.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1694,7 +1704,7 @@ void MainWidget::audioLoadProgress(mtpFileLoader *loader) {
|
|||
AudioItems::const_iterator i = items.constFind(audio);
|
||||
if (i != items.cend()) {
|
||||
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
|
||||
Ui::redrawHistoryItem(j.key());
|
||||
Ui::repaintHistoryItem(j.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1729,7 +1739,7 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
|
|||
}
|
||||
|
||||
if (HistoryItem *item = App::histItemById(audioId.msgId)) {
|
||||
Ui::redrawHistoryItem(item);
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1790,7 +1800,7 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
|
|||
}
|
||||
|
||||
if (HistoryItem *item = App::histItemById(songId.msgId)) {
|
||||
Ui::redrawHistoryItem(item);
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1828,7 +1838,7 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
|
|||
DocumentItems::const_iterator i = items.constFind(document);
|
||||
if (i != items.cend()) {
|
||||
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
|
||||
Ui::redrawHistoryItem(j.key());
|
||||
Ui::repaintHistoryItem(j.key());
|
||||
}
|
||||
}
|
||||
App::wnd()->documentUpdated(document);
|
||||
|
@ -3415,6 +3425,7 @@ void MainWidget::start(const MTPUser &user) {
|
|||
_started = true;
|
||||
App::wnd()->sendServiceHistoryRequest();
|
||||
Local::readStickers();
|
||||
Local::readSavedGifs();
|
||||
history.start();
|
||||
}
|
||||
|
||||
|
@ -4155,7 +4166,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
msgRow->history()->unregTyping(App::self());
|
||||
}
|
||||
App::historyRegItem(msgRow);
|
||||
Ui::redrawHistoryItem(msgRow);
|
||||
Ui::repaintHistoryItem(msgRow);
|
||||
}
|
||||
}
|
||||
App::historyUnregRandom(d.vrandom_id.v);
|
||||
|
@ -4176,7 +4187,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
if (HistoryItem *item = App::histItemById(NoChannel, v.at(i).v)) {
|
||||
if (item->isMediaUnread()) {
|
||||
item->markMediaRead();
|
||||
Ui::redrawHistoryItem(item);
|
||||
Ui::repaintHistoryItem(item);
|
||||
if (item->out() && item->history()->peer->isUser()) {
|
||||
item->history()->peer->asUser()->madeAction();
|
||||
}
|
||||
|
@ -4580,7 +4591,6 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
sets.erase(custom);
|
||||
}
|
||||
}
|
||||
cSetStickersHash(stickersCountHash());
|
||||
Local::writeStickers();
|
||||
emit stickersUpdated();
|
||||
}
|
||||
|
@ -4600,11 +4610,9 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
}
|
||||
if (result.size() != cStickerSetsOrder().size() || result.size() != order.size()) {
|
||||
cSetLastStickersUpdate(0);
|
||||
cSetStickersHash(0);
|
||||
App::main()->updateStickers();
|
||||
} else {
|
||||
cSetStickerSetsOrder(result);
|
||||
cSetStickersHash(stickersCountHash());
|
||||
Local::writeStickers();
|
||||
emit stickersUpdated();
|
||||
}
|
||||
|
@ -4612,7 +4620,11 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
|
||||
case mtpc_updateStickerSets: {
|
||||
cSetLastStickersUpdate(0);
|
||||
cSetStickersHash(0);
|
||||
App::main()->updateStickers();
|
||||
} break;
|
||||
|
||||
case mtpc_updateSavedGifs: {
|
||||
cSetLastSavedGifsUpdate(0);
|
||||
App::main()->updateStickers();
|
||||
} break;
|
||||
|
||||
|
|
|
@ -409,14 +409,17 @@ public:
|
|||
|
||||
void ui_showStickerPreview(DocumentData *sticker);
|
||||
void ui_hideStickerPreview();
|
||||
void ui_redrawHistoryItem(const HistoryItem *item);
|
||||
void ui_repaintHistoryItem(const HistoryItem *item);
|
||||
void ui_repaintSavedGif(const LayoutSavedGif *layout);
|
||||
bool ui_isSavedGifVisible(const LayoutSavedGif *layout);
|
||||
bool ui_isGifBeingChosen();
|
||||
void ui_showPeerHistory(quint64 peer, qint32 msgId, bool back);
|
||||
|
||||
void notify_botCommandsChanged(UserData *bot);
|
||||
void notify_userIsBotChanged(UserData *bot);
|
||||
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
|
||||
void notify_migrateUpdated(PeerData *peer);
|
||||
void notify_mediaViewHidden();
|
||||
void notify_clipStopperHidden(ClipStopperType type);
|
||||
void notify_historyItemResized(const HistoryItem *row, bool scrollToIt);
|
||||
void notify_historyItemLayoutChanged(const HistoryItem *item);
|
||||
|
||||
|
@ -430,6 +433,7 @@ signals:
|
|||
void dialogRowReplaced(DialogRow *oldRow, DialogRow *newRow);
|
||||
void dialogsUpdated();
|
||||
void stickersUpdated();
|
||||
void savedGifsUpdated();
|
||||
|
||||
public slots:
|
||||
|
||||
|
|
|
@ -603,7 +603,7 @@ void MediaView::onDocClick() {
|
|||
}
|
||||
}
|
||||
|
||||
void MediaView::ui_clipRedraw(ClipReader *reader) {
|
||||
void MediaView::ui_clipRepaint(ClipReader *reader) {
|
||||
if (reader == _gif) {
|
||||
update(_x, _y, _w, _h);
|
||||
}
|
||||
|
@ -1960,7 +1960,7 @@ void MediaView::hide() {
|
|||
QWidget::hide();
|
||||
stopGif();
|
||||
|
||||
Notify::mediaViewHidden();
|
||||
Notify::clipStopperHidden(ClipStopperMediaview);
|
||||
}
|
||||
|
||||
void MediaView::onMenuDestroy(QObject *obj) {
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
void activateControls();
|
||||
void onDocClick();
|
||||
|
||||
void ui_clipRedraw(ClipReader *reader);
|
||||
void ui_clipRepaint(ClipReader *reader);
|
||||
|
||||
void notify_clipReinit(ClipReader *reader);
|
||||
|
||||
|
|
|
@ -154,6 +154,9 @@ namespace {
|
|||
bool onErrorDefault(mtpRequestId requestId, const RPCError &error) {
|
||||
const QString &err(error.type());
|
||||
int32 code = error.code();
|
||||
if (!mtpIsFlood(error)) {
|
||||
int breakpoint = 0;
|
||||
}
|
||||
bool badGuestDC = (code == 400) && (err == qsl("FILE_ID_INVALID"));
|
||||
QRegularExpressionMatch m;
|
||||
if ((m = QRegularExpression("^(FILE|PHONE|NETWORK|USER)_MIGRATE_(\\d+)$").match(err)).hasMatch()) {
|
||||
|
|
|
@ -154,6 +154,7 @@ namespace {
|
|||
mtpUpdateDcOptions(data.vdc_options.c_vector().v);
|
||||
cSetMaxGroupCount(data.vchat_size_max.v);
|
||||
cSetMaxMegaGroupCount(data.vmegagroup_size_max.v);
|
||||
cSetSavedGifsLimit(data.vsaved_gifs_limit.v);
|
||||
|
||||
configLoadedOnce = true;
|
||||
Local::writeSettings();
|
||||
|
|
|
@ -2466,6 +2466,10 @@ void _serialize_inputMessagesFilterUrl(MTPStringLogger &to, int32 stage, int32 l
|
|||
to.add("{ inputMessagesFilterUrl }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputMessagesFilterGif(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputMessagesFilterGif }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_updateNewMessage(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -3039,6 +3043,10 @@ void _serialize_updateStickerSets(MTPStringLogger &to, int32 stage, int32 lev, T
|
|||
to.add("{ updateStickerSets }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_updateSavedGifs(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ updateSavedGifs }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_updates_state(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -3336,7 +3344,8 @@ void _serialize_config(MTPStringLogger &to, int32 stage, int32 lev, Types &types
|
|||
case 14: to.add(" chat_big_size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 15: to.add(" push_chat_period_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 16: to.add(" push_chat_limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 17: to.add(" disabled_features: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 17: to.add(" saved_gifs_limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 18: to.add(" disabled_features: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
@ -5107,6 +5116,24 @@ void _serialize_messages_foundGifs(MTPStringLogger &to, int32 stage, int32 lev,
|
|||
}
|
||||
}
|
||||
|
||||
void _serialize_messages_savedGifsNotModified(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ messages_savedGifsNotModified }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_messages_savedGifs(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ messages_savedGifs");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" gifs: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_req_pq(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -5621,6 +5648,20 @@ void _serialize_messages_reorderStickerSets(MTPStringLogger &to, int32 stage, in
|
|||
}
|
||||
}
|
||||
|
||||
void _serialize_messages_saveGif(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ messages_saveGif");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" unsave: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_upload_saveFilePart(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -7098,6 +7139,19 @@ void _serialize_messages_searchGifs(MTPStringLogger &to, int32 stage, int32 lev,
|
|||
}
|
||||
}
|
||||
|
||||
void _serialize_messages_getSavedGifs(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ messages_getSavedGifs");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_updates_getState(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ updates_getState }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
@ -7546,6 +7600,7 @@ namespace {
|
|||
_serializers.insert(mtpc_inputMessagesFilterAudio, _serialize_inputMessagesFilterAudio);
|
||||
_serializers.insert(mtpc_inputMessagesFilterAudioDocuments, _serialize_inputMessagesFilterAudioDocuments);
|
||||
_serializers.insert(mtpc_inputMessagesFilterUrl, _serialize_inputMessagesFilterUrl);
|
||||
_serializers.insert(mtpc_inputMessagesFilterGif, _serialize_inputMessagesFilterGif);
|
||||
_serializers.insert(mtpc_updateNewMessage, _serialize_updateNewMessage);
|
||||
_serializers.insert(mtpc_updateMessageID, _serialize_updateMessageID);
|
||||
_serializers.insert(mtpc_updateDeleteMessages, _serialize_updateDeleteMessages);
|
||||
|
@ -7586,6 +7641,7 @@ namespace {
|
|||
_serializers.insert(mtpc_updateNewStickerSet, _serialize_updateNewStickerSet);
|
||||
_serializers.insert(mtpc_updateStickerSetsOrder, _serialize_updateStickerSetsOrder);
|
||||
_serializers.insert(mtpc_updateStickerSets, _serialize_updateStickerSets);
|
||||
_serializers.insert(mtpc_updateSavedGifs, _serialize_updateSavedGifs);
|
||||
_serializers.insert(mtpc_updates_state, _serialize_updates_state);
|
||||
_serializers.insert(mtpc_updates_differenceEmpty, _serialize_updates_differenceEmpty);
|
||||
_serializers.insert(mtpc_updates_difference, _serialize_updates_difference);
|
||||
|
@ -7754,6 +7810,8 @@ namespace {
|
|||
_serializers.insert(mtpc_help_termsOfService, _serialize_help_termsOfService);
|
||||
_serializers.insert(mtpc_foundGif, _serialize_foundGif);
|
||||
_serializers.insert(mtpc_messages_foundGifs, _serialize_messages_foundGifs);
|
||||
_serializers.insert(mtpc_messages_savedGifsNotModified, _serialize_messages_savedGifsNotModified);
|
||||
_serializers.insert(mtpc_messages_savedGifs, _serialize_messages_savedGifs);
|
||||
|
||||
_serializers.insert(mtpc_req_pq, _serialize_req_pq);
|
||||
_serializers.insert(mtpc_req_DH_params, _serialize_req_DH_params);
|
||||
|
@ -7794,6 +7852,7 @@ namespace {
|
|||
_serializers.insert(mtpc_messages_uninstallStickerSet, _serialize_messages_uninstallStickerSet);
|
||||
_serializers.insert(mtpc_messages_editChatAdmin, _serialize_messages_editChatAdmin);
|
||||
_serializers.insert(mtpc_messages_reorderStickerSets, _serialize_messages_reorderStickerSets);
|
||||
_serializers.insert(mtpc_messages_saveGif, _serialize_messages_saveGif);
|
||||
_serializers.insert(mtpc_upload_saveFilePart, _serialize_upload_saveFilePart);
|
||||
_serializers.insert(mtpc_upload_saveBigFilePart, _serialize_upload_saveBigFilePart);
|
||||
_serializers.insert(mtpc_help_saveAppLog, _serialize_help_saveAppLog);
|
||||
|
@ -7902,6 +7961,7 @@ namespace {
|
|||
_serializers.insert(mtpc_messages_getStickerSet, _serialize_messages_getStickerSet);
|
||||
_serializers.insert(mtpc_messages_getDocumentByHash, _serialize_messages_getDocumentByHash);
|
||||
_serializers.insert(mtpc_messages_searchGifs, _serialize_messages_searchGifs);
|
||||
_serializers.insert(mtpc_messages_getSavedGifs, _serialize_messages_getSavedGifs);
|
||||
_serializers.insert(mtpc_updates_getState, _serialize_updates_getState);
|
||||
_serializers.insert(mtpc_updates_getDifference, _serialize_updates_getDifference);
|
||||
_serializers.insert(mtpc_updates_getChannelDifference, _serialize_updates_getChannelDifference);
|
||||
|
|
|
@ -240,6 +240,7 @@ enum {
|
|||
mtpc_inputMessagesFilterAudio = 0xcfc87522,
|
||||
mtpc_inputMessagesFilterAudioDocuments = 0x5afbf764,
|
||||
mtpc_inputMessagesFilterUrl = 0x7ef0dd87,
|
||||
mtpc_inputMessagesFilterGif = 0xffc86587,
|
||||
mtpc_updateNewMessage = 0x1f2b0afd,
|
||||
mtpc_updateMessageID = 0x4e90bfd6,
|
||||
mtpc_updateDeleteMessages = 0xa20db0e5,
|
||||
|
@ -280,6 +281,7 @@ enum {
|
|||
mtpc_updateNewStickerSet = 0x688a30aa,
|
||||
mtpc_updateStickerSetsOrder = 0xf0dfb451,
|
||||
mtpc_updateStickerSets = 0x43ae3dec,
|
||||
mtpc_updateSavedGifs = 0x9375341e,
|
||||
mtpc_updates_state = 0xa56c2a3e,
|
||||
mtpc_updates_differenceEmpty = 0x5d75a138,
|
||||
mtpc_updates_difference = 0xf49ca0,
|
||||
|
@ -296,7 +298,7 @@ enum {
|
|||
mtpc_photos_photo = 0x20212ca8,
|
||||
mtpc_upload_file = 0x96a18d5,
|
||||
mtpc_dcOption = 0x5d8c6cc,
|
||||
mtpc_config = 0x6cb6e65e,
|
||||
mtpc_config = 0x6bbc5f8,
|
||||
mtpc_nearestDc = 0x8e1a1775,
|
||||
mtpc_help_appUpdate = 0x8987f311,
|
||||
mtpc_help_noAppUpdate = 0xc45a6536,
|
||||
|
@ -448,6 +450,8 @@ enum {
|
|||
mtpc_help_termsOfService = 0xf1ee3e90,
|
||||
mtpc_foundGif = 0xd579cccb,
|
||||
mtpc_messages_foundGifs = 0x450a1c0a,
|
||||
mtpc_messages_savedGifsNotModified = 0xe8025ca2,
|
||||
mtpc_messages_savedGifs = 0x2e0709a5,
|
||||
mtpc_invokeAfterMsg = 0xcb9f372d,
|
||||
mtpc_invokeAfterMsgs = 0x3dc4b4f0,
|
||||
mtpc_initConnection = 0x69796de9,
|
||||
|
@ -559,6 +563,8 @@ enum {
|
|||
mtpc_messages_reorderStickerSets = 0x9fcfbc30,
|
||||
mtpc_messages_getDocumentByHash = 0x338e2464,
|
||||
mtpc_messages_searchGifs = 0xbf9a776b,
|
||||
mtpc_messages_getSavedGifs = 0x83bf3d52,
|
||||
mtpc_messages_saveGif = 0x327a30cb,
|
||||
mtpc_updates_getState = 0xedd4882a,
|
||||
mtpc_updates_getDifference = 0xa041495,
|
||||
mtpc_updates_getChannelDifference = 0xbb32d7c0,
|
||||
|
@ -1229,6 +1235,9 @@ class MTPDfoundGif;
|
|||
class MTPmessages_foundGifs;
|
||||
class MTPDmessages_foundGifs;
|
||||
|
||||
class MTPmessages_savedGifs;
|
||||
class MTPDmessages_savedGifs;
|
||||
|
||||
|
||||
// Boxed types definitions
|
||||
typedef MTPBoxed<MTPresPQ> MTPResPQ;
|
||||
|
@ -1390,6 +1399,7 @@ typedef MTPBoxed<MTPchannels_channelParticipant> MTPchannels_ChannelParticipant;
|
|||
typedef MTPBoxed<MTPhelp_termsOfService> MTPhelp_TermsOfService;
|
||||
typedef MTPBoxed<MTPfoundGif> MTPFoundGif;
|
||||
typedef MTPBoxed<MTPmessages_foundGifs> MTPmessages_FoundGifs;
|
||||
typedef MTPBoxed<MTPmessages_savedGifs> MTPmessages_SavedGifs;
|
||||
|
||||
// Type classes definitions
|
||||
|
||||
|
@ -5198,6 +5208,7 @@ private:
|
|||
friend MTPmessagesFilter MTP_inputMessagesFilterAudio();
|
||||
friend MTPmessagesFilter MTP_inputMessagesFilterAudioDocuments();
|
||||
friend MTPmessagesFilter MTP_inputMessagesFilterUrl();
|
||||
friend MTPmessagesFilter MTP_inputMessagesFilterGif();
|
||||
|
||||
mtpTypeId _type;
|
||||
};
|
||||
|
@ -5768,6 +5779,7 @@ private:
|
|||
friend MTPupdate MTP_updateNewStickerSet(const MTPmessages_StickerSet &_stickerset);
|
||||
friend MTPupdate MTP_updateStickerSetsOrder(const MTPVector<MTPlong> &_order);
|
||||
friend MTPupdate MTP_updateStickerSets();
|
||||
friend MTPupdate MTP_updateSavedGifs();
|
||||
|
||||
mtpTypeId _type;
|
||||
};
|
||||
|
@ -6148,7 +6160,7 @@ public:
|
|||
private:
|
||||
explicit MTPconfig(MTPDconfig *_data);
|
||||
|
||||
friend MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, const MTPVector<MTPDisabledFeature> &_disabled_features);
|
||||
friend MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, const MTPVector<MTPDisabledFeature> &_disabled_features);
|
||||
};
|
||||
typedef MTPBoxed<MTPconfig> MTPConfig;
|
||||
|
||||
|
@ -9013,6 +9025,44 @@ private:
|
|||
};
|
||||
typedef MTPBoxed<MTPmessages_foundGifs> MTPmessages_FoundGifs;
|
||||
|
||||
class MTPmessages_savedGifs : private mtpDataOwner {
|
||||
public:
|
||||
MTPmessages_savedGifs() : mtpDataOwner(0), _type(0) {
|
||||
}
|
||||
MTPmessages_savedGifs(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
|
||||
MTPDmessages_savedGifs &_messages_savedGifs() {
|
||||
if (!data) throw mtpErrorUninitialized();
|
||||
if (_type != mtpc_messages_savedGifs) throw mtpErrorWrongTypeId(_type, mtpc_messages_savedGifs);
|
||||
split();
|
||||
return *(MTPDmessages_savedGifs*)data;
|
||||
}
|
||||
const MTPDmessages_savedGifs &c_messages_savedGifs() const {
|
||||
if (!data) throw mtpErrorUninitialized();
|
||||
if (_type != mtpc_messages_savedGifs) throw mtpErrorWrongTypeId(_type, mtpc_messages_savedGifs);
|
||||
return *(const MTPDmessages_savedGifs*)data;
|
||||
}
|
||||
|
||||
uint32 innerLength() const;
|
||||
mtpTypeId type() const;
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons);
|
||||
void write(mtpBuffer &to) const;
|
||||
|
||||
typedef void ResponseType;
|
||||
|
||||
private:
|
||||
explicit MTPmessages_savedGifs(mtpTypeId type);
|
||||
explicit MTPmessages_savedGifs(MTPDmessages_savedGifs *_data);
|
||||
|
||||
friend MTPmessages_savedGifs MTP_messages_savedGifsNotModified();
|
||||
friend MTPmessages_savedGifs MTP_messages_savedGifs(MTPint _hash, const MTPVector<MTPDocument> &_gifs);
|
||||
|
||||
mtpTypeId _type;
|
||||
};
|
||||
typedef MTPBoxed<MTPmessages_savedGifs> MTPmessages_SavedGifs;
|
||||
|
||||
// Type constructors with data
|
||||
|
||||
class MTPDresPQ : public mtpDataImpl<MTPDresPQ> {
|
||||
|
@ -11635,7 +11685,7 @@ class MTPDconfig : public mtpDataImpl<MTPDconfig> {
|
|||
public:
|
||||
MTPDconfig() {
|
||||
}
|
||||
MTPDconfig(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, const MTPVector<MTPDisabledFeature> &_disabled_features) : vdate(_date), vexpires(_expires), vtest_mode(_test_mode), vthis_dc(_this_dc), vdc_options(_dc_options), vchat_size_max(_chat_size_max), vmegagroup_size_max(_megagroup_size_max), vforwarded_count_max(_forwarded_count_max), vonline_update_period_ms(_online_update_period_ms), voffline_blur_timeout_ms(_offline_blur_timeout_ms), voffline_idle_timeout_ms(_offline_idle_timeout_ms), vonline_cloud_timeout_ms(_online_cloud_timeout_ms), vnotify_cloud_delay_ms(_notify_cloud_delay_ms), vnotify_default_delay_ms(_notify_default_delay_ms), vchat_big_size(_chat_big_size), vpush_chat_period_ms(_push_chat_period_ms), vpush_chat_limit(_push_chat_limit), vdisabled_features(_disabled_features) {
|
||||
MTPDconfig(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, const MTPVector<MTPDisabledFeature> &_disabled_features) : vdate(_date), vexpires(_expires), vtest_mode(_test_mode), vthis_dc(_this_dc), vdc_options(_dc_options), vchat_size_max(_chat_size_max), vmegagroup_size_max(_megagroup_size_max), vforwarded_count_max(_forwarded_count_max), vonline_update_period_ms(_online_update_period_ms), voffline_blur_timeout_ms(_offline_blur_timeout_ms), voffline_idle_timeout_ms(_offline_idle_timeout_ms), vonline_cloud_timeout_ms(_online_cloud_timeout_ms), vnotify_cloud_delay_ms(_notify_cloud_delay_ms), vnotify_default_delay_ms(_notify_default_delay_ms), vchat_big_size(_chat_big_size), vpush_chat_period_ms(_push_chat_period_ms), vpush_chat_limit(_push_chat_limit), vsaved_gifs_limit(_saved_gifs_limit), vdisabled_features(_disabled_features) {
|
||||
}
|
||||
|
||||
MTPint vdate;
|
||||
|
@ -11655,6 +11705,7 @@ public:
|
|||
MTPint vchat_big_size;
|
||||
MTPint vpush_chat_period_ms;
|
||||
MTPint vpush_chat_limit;
|
||||
MTPint vsaved_gifs_limit;
|
||||
MTPVector<MTPDisabledFeature> vdisabled_features;
|
||||
};
|
||||
|
||||
|
@ -13048,6 +13099,17 @@ public:
|
|||
MTPVector<MTPFoundGif> vresults;
|
||||
};
|
||||
|
||||
class MTPDmessages_savedGifs : public mtpDataImpl<MTPDmessages_savedGifs> {
|
||||
public:
|
||||
MTPDmessages_savedGifs() {
|
||||
}
|
||||
MTPDmessages_savedGifs(MTPint _hash, const MTPVector<MTPDocument> &_gifs) : vhash(_hash), vgifs(_gifs) {
|
||||
}
|
||||
|
||||
MTPint vhash;
|
||||
MTPVector<MTPDocument> vgifs;
|
||||
};
|
||||
|
||||
// RPC methods
|
||||
|
||||
class MTPreq_pq { // RPC method 'req_pq'
|
||||
|
@ -18085,6 +18147,87 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class MTPmessages_getSavedGifs { // RPC method 'messages.getSavedGifs'
|
||||
public:
|
||||
MTPint vhash;
|
||||
|
||||
MTPmessages_getSavedGifs() {
|
||||
}
|
||||
MTPmessages_getSavedGifs(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getSavedGifs) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
MTPmessages_getSavedGifs(MTPint _hash) : vhash(_hash) {
|
||||
}
|
||||
|
||||
uint32 innerLength() const {
|
||||
return vhash.innerLength();
|
||||
}
|
||||
mtpTypeId type() const {
|
||||
return mtpc_messages_getSavedGifs;
|
||||
}
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getSavedGifs) {
|
||||
vhash.read(from, end);
|
||||
}
|
||||
void write(mtpBuffer &to) const {
|
||||
vhash.write(to);
|
||||
}
|
||||
|
||||
typedef MTPmessages_SavedGifs ResponseType;
|
||||
};
|
||||
class MTPmessages_GetSavedGifs : public MTPBoxed<MTPmessages_getSavedGifs> {
|
||||
public:
|
||||
MTPmessages_GetSavedGifs() {
|
||||
}
|
||||
MTPmessages_GetSavedGifs(const MTPmessages_getSavedGifs &v) : MTPBoxed<MTPmessages_getSavedGifs>(v) {
|
||||
}
|
||||
MTPmessages_GetSavedGifs(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_getSavedGifs>(from, end, cons) {
|
||||
}
|
||||
MTPmessages_GetSavedGifs(MTPint _hash) : MTPBoxed<MTPmessages_getSavedGifs>(MTPmessages_getSavedGifs(_hash)) {
|
||||
}
|
||||
};
|
||||
|
||||
class MTPmessages_saveGif { // RPC method 'messages.saveGif'
|
||||
public:
|
||||
MTPInputDocument vid;
|
||||
MTPBool vunsave;
|
||||
|
||||
MTPmessages_saveGif() {
|
||||
}
|
||||
MTPmessages_saveGif(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_saveGif) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
MTPmessages_saveGif(const MTPInputDocument &_id, MTPBool _unsave) : vid(_id), vunsave(_unsave) {
|
||||
}
|
||||
|
||||
uint32 innerLength() const {
|
||||
return vid.innerLength() + vunsave.innerLength();
|
||||
}
|
||||
mtpTypeId type() const {
|
||||
return mtpc_messages_saveGif;
|
||||
}
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_saveGif) {
|
||||
vid.read(from, end);
|
||||
vunsave.read(from, end);
|
||||
}
|
||||
void write(mtpBuffer &to) const {
|
||||
vid.write(to);
|
||||
vunsave.write(to);
|
||||
}
|
||||
|
||||
typedef MTPBool ResponseType;
|
||||
};
|
||||
class MTPmessages_SaveGif : public MTPBoxed<MTPmessages_saveGif> {
|
||||
public:
|
||||
MTPmessages_SaveGif() {
|
||||
}
|
||||
MTPmessages_SaveGif(const MTPmessages_saveGif &v) : MTPBoxed<MTPmessages_saveGif>(v) {
|
||||
}
|
||||
MTPmessages_SaveGif(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_saveGif>(from, end, cons) {
|
||||
}
|
||||
MTPmessages_SaveGif(const MTPInputDocument &_id, MTPBool _unsave) : MTPBoxed<MTPmessages_saveGif>(MTPmessages_saveGif(_id, _unsave)) {
|
||||
}
|
||||
};
|
||||
|
||||
class MTPupdates_getState { // RPC method 'updates.getState'
|
||||
public:
|
||||
MTPupdates_getState() {
|
||||
|
@ -24951,6 +25094,7 @@ inline void MTPmessagesFilter::read(const mtpPrime *&from, const mtpPrime *end,
|
|||
case mtpc_inputMessagesFilterAudio: _type = cons; break;
|
||||
case mtpc_inputMessagesFilterAudioDocuments: _type = cons; break;
|
||||
case mtpc_inputMessagesFilterUrl: _type = cons; break;
|
||||
case mtpc_inputMessagesFilterGif: _type = cons; break;
|
||||
default: throw mtpErrorUnexpected(cons, "MTPmessagesFilter");
|
||||
}
|
||||
}
|
||||
|
@ -24969,6 +25113,7 @@ inline MTPmessagesFilter::MTPmessagesFilter(mtpTypeId type) : _type(type) {
|
|||
case mtpc_inputMessagesFilterAudio: break;
|
||||
case mtpc_inputMessagesFilterAudioDocuments: break;
|
||||
case mtpc_inputMessagesFilterUrl: break;
|
||||
case mtpc_inputMessagesFilterGif: break;
|
||||
default: throw mtpErrorBadTypeId(type, "MTPmessagesFilter");
|
||||
}
|
||||
}
|
||||
|
@ -24999,6 +25144,9 @@ inline MTPmessagesFilter MTP_inputMessagesFilterAudioDocuments() {
|
|||
inline MTPmessagesFilter MTP_inputMessagesFilterUrl() {
|
||||
return MTPmessagesFilter(mtpc_inputMessagesFilterUrl);
|
||||
}
|
||||
inline MTPmessagesFilter MTP_inputMessagesFilterGif() {
|
||||
return MTPmessagesFilter(mtpc_inputMessagesFilterGif);
|
||||
}
|
||||
|
||||
inline uint32 MTPupdate::innerLength() const {
|
||||
switch (_type) {
|
||||
|
@ -25426,6 +25574,7 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI
|
|||
v.vorder.read(from, end);
|
||||
} break;
|
||||
case mtpc_updateStickerSets: _type = cons; break;
|
||||
case mtpc_updateSavedGifs: _type = cons; break;
|
||||
default: throw mtpErrorUnexpected(cons, "MTPupdate");
|
||||
}
|
||||
}
|
||||
|
@ -25693,6 +25842,7 @@ inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) {
|
|||
case mtpc_updateNewStickerSet: setData(new MTPDupdateNewStickerSet()); break;
|
||||
case mtpc_updateStickerSetsOrder: setData(new MTPDupdateStickerSetsOrder()); break;
|
||||
case mtpc_updateStickerSets: break;
|
||||
case mtpc_updateSavedGifs: break;
|
||||
default: throw mtpErrorBadTypeId(type, "MTPupdate");
|
||||
}
|
||||
}
|
||||
|
@ -25894,6 +26044,9 @@ inline MTPupdate MTP_updateStickerSetsOrder(const MTPVector<MTPlong> &_order) {
|
|||
inline MTPupdate MTP_updateStickerSets() {
|
||||
return MTPupdate(mtpc_updateStickerSets);
|
||||
}
|
||||
inline MTPupdate MTP_updateSavedGifs() {
|
||||
return MTPupdate(mtpc_updateSavedGifs);
|
||||
}
|
||||
|
||||
inline MTPupdates_state::MTPupdates_state() : mtpDataOwner(new MTPDupdates_state()) {
|
||||
}
|
||||
|
@ -26419,7 +26572,7 @@ inline MTPconfig::MTPconfig() : mtpDataOwner(new MTPDconfig()) {
|
|||
|
||||
inline uint32 MTPconfig::innerLength() const {
|
||||
const MTPDconfig &v(c_config());
|
||||
return v.vdate.innerLength() + v.vexpires.innerLength() + v.vtest_mode.innerLength() + v.vthis_dc.innerLength() + v.vdc_options.innerLength() + v.vchat_size_max.innerLength() + v.vmegagroup_size_max.innerLength() + v.vforwarded_count_max.innerLength() + v.vonline_update_period_ms.innerLength() + v.voffline_blur_timeout_ms.innerLength() + v.voffline_idle_timeout_ms.innerLength() + v.vonline_cloud_timeout_ms.innerLength() + v.vnotify_cloud_delay_ms.innerLength() + v.vnotify_default_delay_ms.innerLength() + v.vchat_big_size.innerLength() + v.vpush_chat_period_ms.innerLength() + v.vpush_chat_limit.innerLength() + v.vdisabled_features.innerLength();
|
||||
return v.vdate.innerLength() + v.vexpires.innerLength() + v.vtest_mode.innerLength() + v.vthis_dc.innerLength() + v.vdc_options.innerLength() + v.vchat_size_max.innerLength() + v.vmegagroup_size_max.innerLength() + v.vforwarded_count_max.innerLength() + v.vonline_update_period_ms.innerLength() + v.voffline_blur_timeout_ms.innerLength() + v.voffline_idle_timeout_ms.innerLength() + v.vonline_cloud_timeout_ms.innerLength() + v.vnotify_cloud_delay_ms.innerLength() + v.vnotify_default_delay_ms.innerLength() + v.vchat_big_size.innerLength() + v.vpush_chat_period_ms.innerLength() + v.vpush_chat_limit.innerLength() + v.vsaved_gifs_limit.innerLength() + v.vdisabled_features.innerLength();
|
||||
}
|
||||
inline mtpTypeId MTPconfig::type() const {
|
||||
return mtpc_config;
|
||||
|
@ -26446,6 +26599,7 @@ inline void MTPconfig::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI
|
|||
v.vchat_big_size.read(from, end);
|
||||
v.vpush_chat_period_ms.read(from, end);
|
||||
v.vpush_chat_limit.read(from, end);
|
||||
v.vsaved_gifs_limit.read(from, end);
|
||||
v.vdisabled_features.read(from, end);
|
||||
}
|
||||
inline void MTPconfig::write(mtpBuffer &to) const {
|
||||
|
@ -26467,12 +26621,13 @@ inline void MTPconfig::write(mtpBuffer &to) const {
|
|||
v.vchat_big_size.write(to);
|
||||
v.vpush_chat_period_ms.write(to);
|
||||
v.vpush_chat_limit.write(to);
|
||||
v.vsaved_gifs_limit.write(to);
|
||||
v.vdisabled_features.write(to);
|
||||
}
|
||||
inline MTPconfig::MTPconfig(MTPDconfig *_data) : mtpDataOwner(_data) {
|
||||
}
|
||||
inline MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, const MTPVector<MTPDisabledFeature> &_disabled_features) {
|
||||
return MTPconfig(new MTPDconfig(_date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _megagroup_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _push_chat_period_ms, _push_chat_limit, _disabled_features));
|
||||
inline MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, const MTPVector<MTPDisabledFeature> &_disabled_features) {
|
||||
return MTPconfig(new MTPDconfig(_date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _megagroup_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _push_chat_period_ms, _push_chat_limit, _saved_gifs_limit, _disabled_features));
|
||||
}
|
||||
|
||||
inline MTPnearestDc::MTPnearestDc() : mtpDataOwner(new MTPDnearestDc()) {
|
||||
|
@ -30193,6 +30348,57 @@ inline MTPmessages_foundGifs MTP_messages_foundGifs(MTPint _next_offset, const M
|
|||
return MTPmessages_foundGifs(new MTPDmessages_foundGifs(_next_offset, _results));
|
||||
}
|
||||
|
||||
inline uint32 MTPmessages_savedGifs::innerLength() const {
|
||||
switch (_type) {
|
||||
case mtpc_messages_savedGifs: {
|
||||
const MTPDmessages_savedGifs &v(c_messages_savedGifs());
|
||||
return v.vhash.innerLength() + v.vgifs.innerLength();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
inline mtpTypeId MTPmessages_savedGifs::type() const {
|
||||
if (!_type) throw mtpErrorUninitialized();
|
||||
return _type;
|
||||
}
|
||||
inline void MTPmessages_savedGifs::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
|
||||
if (cons != _type) setData(0);
|
||||
switch (cons) {
|
||||
case mtpc_messages_savedGifsNotModified: _type = cons; break;
|
||||
case mtpc_messages_savedGifs: _type = cons; {
|
||||
if (!data) setData(new MTPDmessages_savedGifs());
|
||||
MTPDmessages_savedGifs &v(_messages_savedGifs());
|
||||
v.vhash.read(from, end);
|
||||
v.vgifs.read(from, end);
|
||||
} break;
|
||||
default: throw mtpErrorUnexpected(cons, "MTPmessages_savedGifs");
|
||||
}
|
||||
}
|
||||
inline void MTPmessages_savedGifs::write(mtpBuffer &to) const {
|
||||
switch (_type) {
|
||||
case mtpc_messages_savedGifs: {
|
||||
const MTPDmessages_savedGifs &v(c_messages_savedGifs());
|
||||
v.vhash.write(to);
|
||||
v.vgifs.write(to);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
inline MTPmessages_savedGifs::MTPmessages_savedGifs(mtpTypeId type) : mtpDataOwner(0), _type(type) {
|
||||
switch (type) {
|
||||
case mtpc_messages_savedGifsNotModified: break;
|
||||
case mtpc_messages_savedGifs: setData(new MTPDmessages_savedGifs()); break;
|
||||
default: throw mtpErrorBadTypeId(type, "MTPmessages_savedGifs");
|
||||
}
|
||||
}
|
||||
inline MTPmessages_savedGifs::MTPmessages_savedGifs(MTPDmessages_savedGifs *_data) : mtpDataOwner(_data), _type(mtpc_messages_savedGifs) {
|
||||
}
|
||||
inline MTPmessages_savedGifs MTP_messages_savedGifsNotModified() {
|
||||
return MTPmessages_savedGifs(mtpc_messages_savedGifsNotModified);
|
||||
}
|
||||
inline MTPmessages_savedGifs MTP_messages_savedGifs(MTPint _hash, const MTPVector<MTPDocument> &_gifs) {
|
||||
return MTPmessages_savedGifs(new MTPDmessages_savedGifs(_hash, _gifs));
|
||||
}
|
||||
|
||||
// Human-readable text serialization
|
||||
#if (defined _DEBUG || defined _WITH_DEBUG)
|
||||
|
||||
|
|
|
@ -357,6 +357,7 @@ inputMessagesFilterDocument#9eddf188 = MessagesFilter;
|
|||
inputMessagesFilterAudio#cfc87522 = MessagesFilter;
|
||||
inputMessagesFilterAudioDocuments#5afbf764 = MessagesFilter;
|
||||
inputMessagesFilterUrl#7ef0dd87 = MessagesFilter;
|
||||
inputMessagesFilterGif#ffc86587 = MessagesFilter;
|
||||
|
||||
updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
|
||||
updateMessageID#4e90bfd6 id:int random_id:long = Update;
|
||||
|
@ -398,6 +399,7 @@ updateChatParticipantAdmin#b6901959 chat_id:int user_id:int is_admin:Bool versio
|
|||
updateNewStickerSet#688a30aa stickerset:messages.StickerSet = Update;
|
||||
updateStickerSetsOrder#f0dfb451 order:Vector<long> = Update;
|
||||
updateStickerSets#43ae3dec = Update;
|
||||
updateSavedGifs#9375341e = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
|
@ -422,7 +424,7 @@ upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
|
|||
|
||||
dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true id:int ip_address:string port:int = DcOption;
|
||||
|
||||
config#6cb6e65e date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int disabled_features:Vector<DisabledFeature> = Config;
|
||||
config#6bbc5f8 date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int disabled_features:Vector<DisabledFeature> = Config;
|
||||
|
||||
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
|
||||
|
||||
|
@ -641,6 +643,9 @@ foundGif#d579cccb webpage:WebPage = FoundGif;
|
|||
|
||||
messages.foundGifs#450a1c0a next_offset:int results:Vector<FoundGif> = messages.FoundGifs;
|
||||
|
||||
messages.savedGifsNotModified#e8025ca2 = messages.SavedGifs;
|
||||
messages.savedGifs#2e0709a5 hash:int gifs:Vector<Document> = messages.SavedGifs;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
|
@ -759,6 +764,8 @@ messages.searchGlobal#9e3cacb0 q:string offset_date:int offset_peer:InputPeer of
|
|||
messages.reorderStickerSets#9fcfbc30 order:Vector<long> = Bool;
|
||||
messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
|
||||
messages.searchGifs#bf9a776b q:string offset:int = messages.FoundGifs;
|
||||
messages.getSavedGifs#83bf3d52 hash:int = messages.SavedGifs;
|
||||
messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference;
|
||||
|
|
|
@ -345,7 +345,7 @@ void OverviewInner::moveToNextItem(MsgId &msgId, int32 &index, MsgId upTo, int32
|
|||
}
|
||||
}
|
||||
|
||||
void OverviewInner::redrawItem(MsgId itemId, int32 itemIndex) {
|
||||
void OverviewInner::repaintItem(MsgId itemId, int32 itemIndex) {
|
||||
fixItemIndex(itemIndex, itemId);
|
||||
if (itemIndex >= 0) {
|
||||
if (_type == OverviewPhotos || _type == OverviewVideos) {
|
||||
|
@ -476,10 +476,10 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but
|
|||
if (button != Qt::LeftButton) return;
|
||||
|
||||
if (textlnkDown() != textlnkOver()) {
|
||||
redrawItem(App::pressedLinkItem());
|
||||
repaintItem(App::pressedLinkItem());
|
||||
textlnkDown(textlnkOver());
|
||||
App::pressedLinkItem(App::hoveredLinkItem());
|
||||
redrawItem(App::pressedLinkItem());
|
||||
repaintItem(App::pressedLinkItem());
|
||||
}
|
||||
|
||||
_dragAction = NoDrag;
|
||||
|
@ -508,12 +508,12 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but
|
|||
uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
|
||||
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
if (!_selected.isEmpty()) {
|
||||
redrawItem(_selected.cbegin().key(), -1);
|
||||
repaintItem(_selected.cbegin().key(), -1);
|
||||
_selected.clear();
|
||||
}
|
||||
_selected.insert(_dragItem, selStatus);
|
||||
_dragAction = Selecting;
|
||||
redrawItem(_dragItem, _dragItemIndex);
|
||||
repaintItem(_dragItem, _dragItemIndex);
|
||||
_overview->updateTopBarSelection();
|
||||
} else {
|
||||
_dragAction = PrepareSelect;
|
||||
|
@ -552,7 +552,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
|
|||
}
|
||||
}
|
||||
if (textlnkDown()) {
|
||||
redrawItem(App::pressedLinkItem());
|
||||
repaintItem(App::pressedLinkItem());
|
||||
textlnkDown(TextLinkPtr());
|
||||
App::pressedLinkItem(0);
|
||||
if (!textlnkOver() && _cursor != style::cur_default) {
|
||||
|
@ -577,16 +577,16 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
|
|||
} else {
|
||||
_selected.erase(i);
|
||||
}
|
||||
redrawItem(_dragItem, _dragItemIndex);
|
||||
repaintItem(_dragItem, _dragItemIndex);
|
||||
} else if (_dragAction == PrepareDrag && !needClick && !_dragWasInactive && button != Qt::RightButton) {
|
||||
SelectedItems::iterator i = _selected.find(_dragItem);
|
||||
if (i != _selected.cend() && i.value() == FullSelection) {
|
||||
_selected.erase(i);
|
||||
redrawItem(_dragItem, _dragItemIndex);
|
||||
repaintItem(_dragItem, _dragItemIndex);
|
||||
} else if (i == _selected.cend() && itemMsgId(_dragItem) > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
|
||||
if (_selected.size() < MaxSelectedItems) {
|
||||
_selected.insert(_dragItem, FullSelection);
|
||||
redrawItem(_dragItem, _dragItemIndex);
|
||||
repaintItem(_dragItem, _dragItemIndex);
|
||||
}
|
||||
} else {
|
||||
_selected.clear();
|
||||
|
@ -994,7 +994,7 @@ void OverviewInner::onUpdateSelected() {
|
|||
fixItemIndex(itemIndex, itemId);
|
||||
if (itemIndex >= 0) {
|
||||
_items.at(itemIndex)->linkOut(textlnkOver());
|
||||
redrawItem(itemId, itemIndex);
|
||||
repaintItem(itemId, itemIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1004,7 +1004,7 @@ void OverviewInner::onUpdateSelected() {
|
|||
if (textlnkOver()) {
|
||||
if (item && index >= 0) {
|
||||
_items.at(index)->linkOver(textlnkOver());
|
||||
redrawItem(complexMsgId(item), index);
|
||||
repaintItem(complexMsgId(item), index);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1012,8 +1012,8 @@ void OverviewInner::onUpdateSelected() {
|
|||
}
|
||||
if (_mousedItem != oldMousedItem) {
|
||||
lnkChanged = true;
|
||||
if (oldMousedItem) redrawItem(oldMousedItem, oldMousedItemIndex);
|
||||
if (item) redrawItem(item);
|
||||
if (oldMousedItem) repaintItem(oldMousedItem, oldMousedItemIndex);
|
||||
if (item) repaintItem(item);
|
||||
QToolTip::hideText();
|
||||
}
|
||||
if (_cursorState == HistoryInDateCursorState && cursorState != HistoryInDateCursorState) {
|
||||
|
@ -1199,11 +1199,11 @@ void OverviewInner::enterEvent(QEvent *e) {
|
|||
|
||||
void OverviewInner::leaveEvent(QEvent *e) {
|
||||
if (_selectedMsgId) {
|
||||
redrawItem(_selectedMsgId, -1);
|
||||
repaintItem(_selectedMsgId, -1);
|
||||
_selectedMsgId = 0;
|
||||
}
|
||||
if (textlnkOver()) {
|
||||
redrawItem(App::hoveredLinkItem());
|
||||
repaintItem(App::hoveredLinkItem());
|
||||
textlnkOver(TextLinkPtr());
|
||||
App::hoveredLinkItem(0);
|
||||
if (!textlnkDown() && _cursor != style::cur_default) {
|
||||
|
@ -1223,8 +1223,8 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
if (_menu) {
|
||||
_menu->deleteLater();
|
||||
_menu = 0;
|
||||
redrawItem(App::contextItem());
|
||||
if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
|
||||
repaintItem(App::contextItem());
|
||||
if (_selectedMsgId) repaintItem(_selectedMsgId, -1);
|
||||
}
|
||||
if (e->reason() == QContextMenuEvent::Mouse) {
|
||||
dragActionUpdate(e->globalPos());
|
||||
|
@ -1301,8 +1301,8 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
}
|
||||
}
|
||||
App::contextItem(App::hoveredLinkItem());
|
||||
redrawItem(App::contextItem());
|
||||
if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
|
||||
repaintItem(App::contextItem());
|
||||
if (_selectedMsgId) repaintItem(_selectedMsgId, -1);
|
||||
} else if (!ignoreMousedItem && App::mousedItem() && App::mousedItem()->channelId() == itemChannel(_mousedItem) && App::mousedItem()->id == itemMsgId(_mousedItem)) {
|
||||
_menu = new PopupMenu();
|
||||
if ((_contextMenuLnk && dynamic_cast<TextLink*>(_contextMenuLnk.data()))) {
|
||||
|
@ -1340,8 +1340,8 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
}
|
||||
}
|
||||
App::contextItem(App::mousedItem());
|
||||
redrawItem(App::contextItem());
|
||||
if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
|
||||
repaintItem(App::contextItem());
|
||||
if (_selectedMsgId) repaintItem(_selectedMsgId, -1);
|
||||
}
|
||||
if (_menu) {
|
||||
connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*)));
|
||||
|
@ -1627,8 +1627,8 @@ void OverviewInner::onMenuDestroy(QObject *obj) {
|
|||
if (_menu == obj) {
|
||||
_menu = 0;
|
||||
dragActionUpdate(QCursor::pos());
|
||||
redrawItem(App::contextItem());
|
||||
if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
|
||||
repaintItem(App::contextItem());
|
||||
if (_selectedMsgId) repaintItem(_selectedMsgId, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1719,7 +1719,7 @@ void OverviewInner::mediaOverviewUpdated() {
|
|||
allGood = false;
|
||||
}
|
||||
HistoryItem *item = App::histItemById(itemChannel(msgid), itemMsgId(msgid));
|
||||
LayoutMediaItem *layout = getItemLayout(item);
|
||||
LayoutMediaItem *layout = layoutPrepare(item);
|
||||
if (!layout) continue;
|
||||
|
||||
setLayoutItem(index, layout, 0);
|
||||
|
@ -1765,13 +1765,13 @@ void OverviewInner::mediaOverviewUpdated() {
|
|||
allGood = false;
|
||||
}
|
||||
HistoryItem *item = App::histItemById(itemChannel(msgid), itemMsgId(msgid));
|
||||
LayoutMediaItem *layout = getItemLayout(item);
|
||||
LayoutMediaItem *layout = layoutPrepare(item);
|
||||
if (!layout) continue;
|
||||
|
||||
if (withDates) {
|
||||
QDate date = item->date.date();
|
||||
if (!index || (index > 0 && (dateEveryMonth ? (date.month() != prevDate.month() || date.year() != prevDate.year()) : (date != prevDate)))) {
|
||||
top += setLayoutItem(index, getDateLayout(date, dateEveryMonth), top);
|
||||
top += setLayoutItem(index, layoutPrepare(date, dateEveryMonth), top);
|
||||
++index;
|
||||
prevDate = date;
|
||||
}
|
||||
|
@ -1851,7 +1851,7 @@ void OverviewInner::itemRemoved(HistoryItem *item) {
|
|||
update();
|
||||
}
|
||||
|
||||
void OverviewInner::redrawItem(const HistoryItem *msg) {
|
||||
void OverviewInner::repaintItem(const HistoryItem *msg) {
|
||||
if (!msg) return;
|
||||
|
||||
History *history = (msg->history() == _history) ? _history : (msg->history() == _migrated ? _migrated : 0);
|
||||
|
@ -1921,7 +1921,7 @@ void OverviewInner::recountMargins() {
|
|||
}
|
||||
}
|
||||
|
||||
LayoutMediaItem *OverviewInner::getItemLayout(HistoryItem *item) {
|
||||
LayoutMediaItem *OverviewInner::layoutPrepare(HistoryItem *item) {
|
||||
if (!item) return 0;
|
||||
|
||||
LayoutItems::const_iterator i = _layoutItems.cend();
|
||||
|
@ -1963,7 +1963,7 @@ LayoutMediaItem *OverviewInner::getItemLayout(HistoryItem *item) {
|
|||
return (i == _layoutItems.cend()) ? 0 : i.value();
|
||||
}
|
||||
|
||||
LayoutItem *OverviewInner::getDateLayout(const QDate &date, bool month) {
|
||||
LayoutItem *OverviewInner::layoutPrepare(const QDate &date, bool month) {
|
||||
int32 key = date.year() * 100 + date.month();
|
||||
if (!month) key = key * 100 + date.day();
|
||||
LayoutDates::const_iterator i = _layoutDates.constFind(key);
|
||||
|
@ -2288,9 +2288,9 @@ void OverviewWidget::changingMsgId(HistoryItem *row, MsgId newId) {
|
|||
}
|
||||
}
|
||||
|
||||
void OverviewWidget::ui_redrawHistoryItem(const HistoryItem *item) {
|
||||
void OverviewWidget::ui_repaintHistoryItem(const HistoryItem *item) {
|
||||
if (peer() == item->history()->peer || migratePeer() == item->history()->peer) {
|
||||
_inner.redrawItem(item);
|
||||
_inner.repaintItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
|
||||
void mediaOverviewUpdated();
|
||||
void changingMsgId(HistoryItem *row, MsgId newId);
|
||||
void redrawItem(const HistoryItem *msg);
|
||||
void repaintItem(const HistoryItem *msg);
|
||||
void itemRemoved(HistoryItem *item);
|
||||
|
||||
void getSelectionState(int32 &selectedForForward, int32 &selectedForDelete) const;
|
||||
|
@ -124,7 +124,7 @@ private:
|
|||
|
||||
void updateDragSelection(MsgId dragSelFrom, int32 dragSelFromIndex, MsgId dragSelTo, int32 dragSelToIndex, bool dragSelecting);
|
||||
|
||||
void redrawItem(MsgId itemId, int32 itemIndex);
|
||||
void repaintItem(MsgId itemId, int32 itemIndex);
|
||||
|
||||
void touchResetSpeed();
|
||||
void touchUpdateSpeed();
|
||||
|
@ -157,8 +157,8 @@ private:
|
|||
LayoutItems _layoutItems;
|
||||
typedef QMap<int32, LayoutOverviewDate*> LayoutDates;
|
||||
LayoutDates _layoutDates;
|
||||
LayoutMediaItem *getItemLayout(HistoryItem *item);
|
||||
LayoutItem *getDateLayout(const QDate &date, bool month);
|
||||
LayoutMediaItem *layoutPrepare(HistoryItem *item);
|
||||
LayoutItem *layoutPrepare(const QDate &date, bool month);
|
||||
int32 setLayoutItem(int32 index, LayoutItem *item, int32 top);
|
||||
|
||||
FlatInput _search;
|
||||
|
@ -299,7 +299,7 @@ public:
|
|||
resizeEvent(0);
|
||||
}
|
||||
|
||||
void ui_redrawHistoryItem(const HistoryItem *item);
|
||||
void ui_repaintHistoryItem(const HistoryItem *item);
|
||||
|
||||
void notify_historyItemLayoutChanged(const HistoryItem *item);
|
||||
|
||||
|
|
|
@ -1832,7 +1832,9 @@ int32 ProfileWidget::lastScrollTop() const {
|
|||
void ProfileWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTopBarCache, bool back, int32 lastScrollTop) {
|
||||
if (App::app()) App::app()->mtpPause();
|
||||
|
||||
// App::stopGifItems();
|
||||
if (!cAutoPlayGif()) {
|
||||
App::stopGifItems();
|
||||
}
|
||||
|
||||
(back ? _cacheOver : _cacheUnder) = bgAnimCache;
|
||||
(back ? _cacheTopBarOver : _cacheTopBarUnder) = bgAnimTopBarCache;
|
||||
|
|
|
@ -108,15 +108,17 @@ RecentEmojiPack gRecentEmojis;
|
|||
RecentEmojisPreload gRecentEmojisPreload;
|
||||
EmojiColorVariants gEmojiVariants;
|
||||
|
||||
int32 gStickersHash = 0;
|
||||
|
||||
RecentStickerPreload gRecentStickersPreload;
|
||||
RecentStickerPack gRecentStickers;
|
||||
StickerSets gStickerSets;
|
||||
StickerSetsOrder gStickerSetsOrder;
|
||||
|
||||
uint64 gLastStickersUpdate = 0;
|
||||
|
||||
SavedGifs gSavedGifs;
|
||||
uint64 gLastSavedGifsUpdate = 0;
|
||||
bool gShowingSavedGifs = false;
|
||||
int32 gSavedGifsLimit = 100;
|
||||
|
||||
RecentHashtagPack gRecentWriteHashtags, gRecentSearchHashtags;
|
||||
|
||||
bool gPasswordRecovered = false;
|
||||
|
@ -174,6 +176,7 @@ ReportSpamStatuses gReportSpamStatuses;
|
|||
int32 gAutoDownloadPhoto = 0; // all auto download
|
||||
int32 gAutoDownloadAudio = 0;
|
||||
int32 gAutoDownloadGif = 0;
|
||||
bool gAutoPlayGif = true;
|
||||
|
||||
void settingsParseArgs(int argc, char *argv[]) {
|
||||
#ifdef Q_OS_MAC
|
||||
|
|
|
@ -197,7 +197,6 @@ RecentEmojiPack &cGetRecentEmojis();
|
|||
|
||||
class DocumentData;
|
||||
typedef QVector<DocumentData*> StickerPack;
|
||||
DeclareSetting(int32, StickersHash);
|
||||
|
||||
typedef QList<QPair<DocumentData*, int16> > RecentStickerPackOld;
|
||||
typedef QVector<QPair<uint64, ushort> > RecentStickerPreload;
|
||||
|
@ -207,8 +206,6 @@ DeclareRefSetting(RecentStickerPack, RecentStickers);
|
|||
|
||||
RecentStickerPack &cGetRecentStickers();
|
||||
|
||||
DeclareSetting(uint64, LastStickersUpdate);
|
||||
|
||||
static const uint64 DefaultStickerSetId = 0; // for backward compatibility
|
||||
static const uint64 CustomStickerSetId = 0xFFFFFFFFFFFFFFFFULL, RecentStickerSetId = 0xFFFFFFFFFFFFFFFEULL;
|
||||
static const uint64 NoneStickerSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel
|
||||
|
@ -224,6 +221,13 @@ typedef QMap<uint64, StickerSet> StickerSets;
|
|||
DeclareRefSetting(StickerSets, StickerSets);
|
||||
typedef QList<uint64> StickerSetsOrder;
|
||||
DeclareRefSetting(StickerSetsOrder, StickerSetsOrder);
|
||||
DeclareSetting(uint64, LastStickersUpdate);
|
||||
|
||||
typedef QVector<DocumentData*> SavedGifs;
|
||||
DeclareRefSetting(SavedGifs, SavedGifs);
|
||||
DeclareSetting(uint64, LastSavedGifsUpdate);
|
||||
DeclareSetting(bool, ShowingSavedGifs);
|
||||
DeclareSetting(int32, SavedGifsLimit);
|
||||
|
||||
typedef QList<QPair<QString, ushort> > RecentHashtagPack;
|
||||
DeclareSetting(RecentHashtagPack, RecentWriteHashtags);
|
||||
|
@ -335,5 +339,6 @@ enum DBIAutoDownloadFlags {
|
|||
DeclareSetting(int32, AutoDownloadPhoto);
|
||||
DeclareSetting(int32, AutoDownloadAudio);
|
||||
DeclareSetting(int32, AutoDownloadGif);
|
||||
DeclareSetting(bool, AutoPlayGif);
|
||||
|
||||
void settingsParseArgs(int argc, char *argv[]);
|
||||
|
|
|
@ -578,6 +578,10 @@ void PhotoData::automaticLoad(const HistoryItem *item) {
|
|||
full->automaticLoad(item);
|
||||
}
|
||||
|
||||
void PhotoData::automaticLoadSettingsChanged() {
|
||||
full->automaticLoadSettingsChanged();
|
||||
}
|
||||
|
||||
void PhotoData::download() {
|
||||
full->loadEvenCancelled();
|
||||
notifyLayoutChanged();
|
||||
|
@ -1158,6 +1162,11 @@ void AudioData::automaticLoad(const HistoryItem *item) {
|
|||
}
|
||||
}
|
||||
|
||||
void AudioData::automaticLoadSettingsChanged() {
|
||||
if (loaded() || status != FileReady || !saveToCache() || _loader != CancelledFileLoader) return;
|
||||
_loader = 0;
|
||||
}
|
||||
|
||||
void AudioData::performActionOnLoad() {
|
||||
if (_actionOnLoad == ActionOnLoadNone) return;
|
||||
|
||||
|
@ -1332,6 +1341,8 @@ void DocumentOpenLink::doOpen(DocumentData *data, ActionOnLoad action) {
|
|||
|
||||
HistoryItem *item = App::hoveredLinkItem() ? App::hoveredLinkItem() : (App::contextItem() ? App::contextItem() : 0);
|
||||
|
||||
MTP::send(MTPmessages_SendMedia(MTP_int(0), item->history()->peer->input, MTP_int(0), MTP_inputMediaDocument(MTP_inputDocument(MTP_long(data->id), MTP_long(data->access))), MTP_long(MTP::nonce<uint64>()), MTPnullMarkup));
|
||||
|
||||
bool playMusic = data->song() && audioPlayer() && item;
|
||||
bool playAnimation = data->isAnimation() && item && item->getMedia();
|
||||
const FileLocation &location(data->location(true));
|
||||
|
@ -1556,18 +1567,27 @@ void DocumentData::automaticLoad(const HistoryItem *item) {
|
|||
if (saveToCache() && _loader != CancelledFileLoader) {
|
||||
if (type == StickerDocument) {
|
||||
save(QString(), _actionOnLoad, _actionOnLoadMsgId);
|
||||
} else if (isAnimation() && item) {
|
||||
} else if (isAnimation()) {
|
||||
bool loadFromCloud = false;
|
||||
if (item->history()->peer->isUser()) {
|
||||
loadFromCloud = !(cAutoDownloadGif() & dbiadNoPrivate);
|
||||
} else {
|
||||
loadFromCloud = !(cAutoDownloadGif() & dbiadNoGroups);
|
||||
if (item) {
|
||||
if (item->history()->peer->isUser()) {
|
||||
loadFromCloud = !(cAutoDownloadGif() & dbiadNoPrivate);
|
||||
} else {
|
||||
loadFromCloud = !(cAutoDownloadGif() & dbiadNoGroups);
|
||||
}
|
||||
} else { // if load at least anywhere
|
||||
loadFromCloud = !(cAutoDownloadGif() & dbiadNoPrivate) || !(cAutoDownloadGif() & dbiadNoGroups);
|
||||
}
|
||||
save(QString(), _actionOnLoad, _actionOnLoadMsgId, loadFromCloud ? LoadFromCloudOrLocal : LoadFromLocalOnly, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentData::automaticLoadSettingsChanged() {
|
||||
if (loaded() || status != FileReady || !isAnimation() || !saveToCache() || _loader != CancelledFileLoader) return;
|
||||
_loader = 0;
|
||||
}
|
||||
|
||||
void DocumentData::performActionOnLoad() {
|
||||
if (_actionOnLoad == ActionOnLoadNone) return;
|
||||
|
||||
|
|
|
@ -733,6 +733,7 @@ public:
|
|||
PhotoData(const PhotoId &id, const uint64 &access = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr());
|
||||
|
||||
void automaticLoad(const HistoryItem *item);
|
||||
void automaticLoadSettingsChanged();
|
||||
|
||||
void download();
|
||||
bool loaded() const;
|
||||
|
@ -823,6 +824,8 @@ public:
|
|||
|
||||
void automaticLoad(const HistoryItem *item) {
|
||||
}
|
||||
void automaticLoadSettingsChanged() {
|
||||
}
|
||||
|
||||
bool loaded(bool check = false) const;
|
||||
bool loading() const;
|
||||
|
@ -919,6 +922,7 @@ public:
|
|||
AudioData(const AudioId &id, const uint64 &access = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
|
||||
|
||||
void automaticLoad(const HistoryItem *item); // auto load voice message
|
||||
void automaticLoadSettingsChanged();
|
||||
|
||||
bool loaded(bool check = false) const;
|
||||
bool loading() const;
|
||||
|
@ -1079,6 +1083,7 @@ public:
|
|||
void setattributes(const QVector<MTPDocumentAttribute> &attributes);
|
||||
|
||||
void automaticLoad(const HistoryItem *item); // auto load sticker or video
|
||||
void automaticLoadSettingsChanged();
|
||||
|
||||
bool loaded(bool check = false) const;
|
||||
bool loading() const;
|
||||
|
|
|
@ -294,6 +294,9 @@ enum DataBlockId {
|
|||
dbiMaxMegaGroupCount = 0x32,
|
||||
dbiDownloadPath = 0x33,
|
||||
dbiAutoDownload = 0x34,
|
||||
dbiSavedGifsLimit = 0x35,
|
||||
dbiShowingSavedGifs = 0x36,
|
||||
dbiAutoPlay = 0x37,
|
||||
|
||||
dbiEncryptedWithSalt = 333,
|
||||
dbiEncrypted = 444,
|
||||
|
@ -469,3 +472,69 @@ static int32 FullArcLength = 360 * 16;
|
|||
static int32 QuarterArcLength = (FullArcLength / 4);
|
||||
static int32 MinArcLength = (FullArcLength / 360);
|
||||
static int32 AlmostFullArcLength = (FullArcLength - MinArcLength);
|
||||
|
||||
template <typename ReturnType>
|
||||
class Function {
|
||||
public:
|
||||
|
||||
virtual ReturnType call() = 0;
|
||||
virtual ~Function() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Object, typename ReturnType>
|
||||
class ObjectFunction : public Function<ReturnType> {
|
||||
public:
|
||||
typedef ReturnType (Object::*Method)();
|
||||
|
||||
ObjectFunction(Object *obj, Method method) : _obj(obj), _method(method) {
|
||||
}
|
||||
|
||||
virtual ReturnType call() {
|
||||
return (_obj->*_method)();
|
||||
}
|
||||
|
||||
private:
|
||||
Object *_obj;
|
||||
Method _method;
|
||||
|
||||
};
|
||||
|
||||
template <typename Object, typename ReturnType>
|
||||
Function<ReturnType> *func(Object *obj, typename ReturnType (Object::*method)()) {
|
||||
return new ObjectFunction<Object, ReturnType>(obj, method);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename ArgumentType1>
|
||||
class Function1 {
|
||||
public:
|
||||
|
||||
virtual ReturnType call(ArgumentType1 arg1) = 0;
|
||||
virtual ~Function1() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Object, typename ReturnType, typename ArgumentType1>
|
||||
class ObjectFunction1 : public Function1<ReturnType, ArgumentType1> {
|
||||
public:
|
||||
typedef ReturnType (Object::*Method)(ArgumentType1);
|
||||
|
||||
ObjectFunction1(Object *obj, Method method) : _obj(obj), _method(method) {
|
||||
}
|
||||
|
||||
virtual ReturnType call(ArgumentType1 arg1) {
|
||||
return (_obj->*_method)(arg1);
|
||||
}
|
||||
|
||||
private:
|
||||
Object *_obj;
|
||||
Method _method;
|
||||
|
||||
};
|
||||
|
||||
template <typename Object, typename ReturnType, typename ArgumentType1>
|
||||
Function1<ReturnType, ArgumentType1> *func(Object *obj, ReturnType (Object::*method)(ArgumentType1)) {
|
||||
return new ObjectFunction1<Object, ReturnType, ArgumentType1>(obj, method);
|
||||
}
|
||||
|
|
|
@ -647,8 +647,6 @@ void Window::sendServiceHistoryRequest() {
|
|||
}
|
||||
|
||||
void Window::setupMain(bool anim, const MTPUser *self) {
|
||||
Local::readStickers();
|
||||
|
||||
QPixmap bg = anim ? grabInner() : QPixmap();
|
||||
clearWidgets();
|
||||
main = new MainWidget(this);
|
||||
|
@ -797,9 +795,9 @@ void Window::showDocument(DocumentData *doc, HistoryItem *item) {
|
|||
_mediaView->setFocus();
|
||||
}
|
||||
|
||||
void Window::ui_clipRedraw(ClipReader *reader) {
|
||||
void Window::ui_clipRepaint(ClipReader *reader) {
|
||||
if (_mediaView && !_mediaView->isHidden()) {
|
||||
_mediaView->ui_clipRedraw(reader);
|
||||
_mediaView->ui_clipRepaint(reader);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ public:
|
|||
return contentOverlapped(QRect(w->mapToGlobal(r.boundingRect().topLeft()), r.boundingRect().size()));
|
||||
}
|
||||
|
||||
void ui_clipRedraw(ClipReader *reader);
|
||||
void ui_clipRepaint(ClipReader *reader);
|
||||
void ui_showLayer(LayeredWidget *box, ShowLayerOptions options);
|
||||
bool ui_isLayerShown();
|
||||
bool ui_isMediaViewShown();
|
||||
|
|
Loading…
Add table
Reference in a new issue