Merge branch 'emojis' into dev

This commit is contained in:
John Preston 2015-05-08 16:02:33 +03:00
commit be1eb1c693
42 changed files with 5919 additions and 6431 deletions

View file

@ -515,7 +515,7 @@
6DB9C3763D02B1415CD9D565 /* Project object */ = { 6DB9C3763D02B1415CD9D565 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0610; LastUpgradeCheck = 0630;
}; };
buildConfigurationList = DAC4C1AA5EDEA1C85E9CA5E6 /* Build configuration list for PBXProject "MetaEmoji" */; buildConfigurationList = DAC4C1AA5EDEA1C85E9CA5E6 /* Build configuration list for PBXProject "MetaEmoji" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.2";
@ -589,6 +589,7 @@
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = ""; FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
@ -677,6 +678,7 @@
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = ""; FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = NO;

View file

@ -420,6 +420,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_media_video" = "Video file"; "lng_media_video" = "Video file";
"lng_media_audio" = "Voice message"; "lng_media_audio" = "Voice message";
"lng_emoji_category0" = "Frequently used";
"lng_emoji_category1" = "People";
"lng_emoji_category2" = "Nature";
"lng_emoji_category3" = "Food & Drink";
"lng_emoji_category4" = "Celebration";
"lng_emoji_category5" = "Activity";
"lng_emoji_category6" = "Travel & Places";
"lng_emoji_category7" = "Objects & Symbols";
"lng_emoji_category8" = "Stickers";
"lng_in_dlg_photo" = "Photo"; "lng_in_dlg_photo" = "Photo";
"lng_in_dlg_video" = "Video"; "lng_in_dlg_video" = "Video";
"lng_in_dlg_contact" = "Contact"; "lng_in_dlg_contact" = "Contact";

View file

@ -21,7 +21,6 @@ semibold: 'Open Sans Semibold';
fsize: 13px; fsize: 13px;
spriteFile: ':/gui/art/sprite.png' / 2:':/gui/art/sprite_125x.png' / 3:':/gui/art/sprite_150x.png' / 4:':/gui/art/sprite_200x.png'; spriteFile: ':/gui/art/sprite.png' / 2:':/gui/art/sprite_125x.png' / 3:':/gui/art/sprite_150x.png' / 4:':/gui/art/sprite_200x.png';
emojisFile: ':/gui/art/emoji.png' / 2:':/gui/art/emoji_125x.png' / 3:':/gui/art/emoji_150x.png' / 4:':/gui/art/emoji_200x.png';
emojiImgSize: 18px; // exceptional value for retina emojiImgSize: 18px; // exceptional value for retina
emojiSize: 18px; emojiSize: 18px;
emojiPadding: 0px; emojiPadding: 0px;
@ -123,9 +122,9 @@ sysUnlock: sysButton(sysUpd) {
img: sprite(207px, 22px, 19px, 19px); img: sprite(207px, 22px, 19px, 19px);
} }
titleBackButton: iconedButton(btnDefIconed) { titleBackButton: iconedButton(btnDefIconed) {
icon: sprite(133px, 197px, 13px, 20px); icon: sprite(113px, 108px, 13px, 20px);
iconPos: point(5px, 9px); iconPos: point(5px, 9px);
downIcon: sprite(133px, 197px, 13px, 20px); downIcon: sprite(113px, 108px, 13px, 20px);
downIconPos: point(5px, 10px); downIconPos: point(5px, 10px);
bgColor: #c4d8e9; bgColor: #c4d8e9;
@ -998,7 +997,7 @@ replyHeight: 49px;
replyTop: 8px; replyTop: 8px;
replyBottom: 6px; replyBottom: 6px;
replyIconPos: point(13px, 13px); replyIconPos: point(13px, 13px);
replyIcon: sprite(174px, 195px, 24px, 24px); replyIcon: sprite(343px, 197px, 24px, 24px);
replyCancel: iconedButton(btnDefIconed) { replyCancel: iconedButton(btnDefIconed) {
icon: sprite(165px, 24px, 14px, 14px); icon: sprite(165px, 24px, 14px, 14px);
iconPos: point(17px, 17px); iconPos: point(17px, 17px);
@ -1009,7 +1008,7 @@ replyCancel: iconedButton(btnDefIconed) {
width: 49px; width: 49px;
height: 49px; height: 49px;
} }
forwardIcon: sprite(368px, 173px, 24px, 24px); forwardIcon: sprite(368px, 197px, 24px, 24px);
historyScroll: flatScroll(scrollDef) { historyScroll: flatScroll(scrollDef) {
barColor: #89a0b47a; barColor: #89a0b47a;
@ -1460,33 +1459,39 @@ emojiScroll: flatScroll(scrollDef) {
topsh: 0px; topsh: 0px;
bottomsh: 0px; bottomsh: 0px;
} }
emojiRecentActive: sprite(290px, 287px, 20px, 20px);
emojiRecentOver: sprite(311px, 287px, 20px, 20px);
emojiRecent: sprite(6px, 197px, 20px, 20px); emojiRecent: sprite(6px, 197px, 20px, 20px);
emojiPeopleActive: sprite(290px, 221px, 20px, 20px); emojiRecentOver: sprite(290px, 221px, 20px, 20px);
emojiPeopleOver: sprite(311px, 221px, 20px, 20px); emojiRecentActive: sprite(290px, 242px, 20px, 20px);
emojiPeople: sprite(27px, 197px, 20px, 20px); emojiPeople: sprite(27px, 197px, 20px, 20px);
emojiNatureActive: sprite(245px, 266px, 20px, 20px); emojiPeopleOver: sprite(311px, 221px, 20px, 20px);
emojiNatureOver: sprite(266px, 266px, 20px, 20px); emojiPeopleActive: sprite(311px, 242px, 20px, 20px);
emojiNature: sprite(48px, 197px, 20px, 20px); emojiNature: sprite(48px, 197px, 20px, 20px);
emojiObjectsActive: sprite(290px, 242px, 20px, 20px); emojiNatureOver: sprite(245px, 266px, 20px, 20px);
emojiObjectsOver: sprite(311px, 242px, 20px, 20px); emojiNatureActive: sprite(245px, 287px, 20px, 20px);
emojiObjects: sprite(69px, 197px, 20px, 20px); emojiFood: sprite(69px, 197px, 20px, 20px);
emojiPlacesActive: sprite(245px, 287px, 20px, 20px); emojiFoodOver: sprite(266px, 266px, 20px, 20px);
emojiPlacesOver: sprite(266px, 287px, 20px, 20px); emojiFoodActive: sprite(266px, 287px, 20px, 20px);
emojiPlaces: sprite(90px, 197px, 20px, 20px); emojiCelebration: sprite(90px, 197px, 20px, 20px);
emojiSymbolsActive: sprite(290px, 266px, 20px, 20px); emojiCelebrationOver: sprite(290px, 266px, 20px, 20px);
emojiSymbolsOver: sprite(311px, 266px, 20px, 20px); emojiCelebrationActive: sprite(290px, 287px, 20px, 20px);
emojiSymbols: sprite(111px, 197px, 20px, 20px); emojiActivity: sprite(111px, 197px, 20px, 20px);
emojiStickersActive: sprite(311px, 308px, 20px, 20px); emojiActivityOver: sprite(311px, 266px, 20px, 20px);
emojiStickersOver: sprite(354px, 200px, 20px, 20px); emojiActivityActive: sprite(311px, 287px, 20px, 20px);
emojiStickers: sprite(375px, 200px, 20px, 20px); emojiTravel: sprite(132px, 197px, 20px, 20px);
emojiTravelOver: sprite(321px, 344px, 20px, 20px);
emojiTravelActive: sprite(321px, 365px, 20px, 20px);
emojiObjects: sprite(153px, 197px, 20px, 20px);
emojiObjectsOver: sprite(342px, 344px, 20px, 20px);
emojiObjectsActive: sprite(342px, 365px, 20px, 20px);
emojiStickers: sprite(174px, 197px, 20px, 20px);
emojiStickersOver: sprite(363px, 344px, 20px, 20px);
emojiStickersActive: sprite(363px, 365px, 20px, 20px);
rbEmoji: flatCheckbox { rbEmoji: flatCheckbox {
textColor: transparent; textColor: transparent;
bgColor: transparent; bgColor: transparent;
disColor: transparent; disColor: transparent;
width: 29px; width: 28px;
height: 36px; height: 36px;
textTop: 0px; textTop: 0px;
@ -1523,6 +1528,38 @@ rbEmojiNature: flatCheckbox(rbEmoji) {
disImageRect: emojiNature; disImageRect: emojiNature;
chkDisImageRect: emojiNatureActive; chkDisImageRect: emojiNatureActive;
} }
rbEmojiFood: flatCheckbox(rbEmoji) {
imageRect: emojiFood;
chkImageRect: emojiFoodActive;
overImageRect: emojiFoodOver;
chkOverImageRect: emojiFoodActive;
disImageRect: emojiFood;
chkDisImageRect: emojiFoodActive;
}
rbEmojiCelebration: flatCheckbox(rbEmoji) {
imageRect: emojiCelebration;
chkImageRect: emojiCelebrationActive;
overImageRect: emojiCelebrationOver;
chkOverImageRect: emojiCelebrationActive;
disImageRect: emojiCelebration;
chkDisImageRect: emojiCelebrationActive;
}
rbEmojiActivity: flatCheckbox(rbEmoji) {
imageRect: emojiActivity;
chkImageRect: emojiActivityActive;
overImageRect: emojiActivityOver;
chkOverImageRect: emojiActivityActive;
disImageRect: emojiActivity;
chkDisImageRect: emojiActivityActive;
}
rbEmojiTravel: flatCheckbox(rbEmoji) {
imageRect: emojiTravel;
chkImageRect: emojiTravelActive;
overImageRect: emojiTravelOver;
chkOverImageRect: emojiTravelActive;
disImageRect: emojiTravel;
chkDisImageRect: emojiTravelActive;
}
rbEmojiObjects: flatCheckbox(rbEmoji) { rbEmojiObjects: flatCheckbox(rbEmoji) {
imageRect: emojiObjects; imageRect: emojiObjects;
chkImageRect: emojiObjectsActive; chkImageRect: emojiObjectsActive;
@ -1531,22 +1568,6 @@ rbEmojiObjects: flatCheckbox(rbEmoji) {
disImageRect: emojiObjects; disImageRect: emojiObjects;
chkDisImageRect: emojiObjectsActive; chkDisImageRect: emojiObjectsActive;
} }
rbEmojiPlaces: flatCheckbox(rbEmoji) {
imageRect: emojiPlaces;
chkImageRect: emojiPlacesActive;
overImageRect: emojiPlacesOver;
chkOverImageRect: emojiPlacesActive;
disImageRect: emojiPlaces;
chkDisImageRect: emojiPlacesActive;
}
rbEmojiSymbols: flatCheckbox(rbEmoji) {
imageRect: emojiSymbols;
chkImageRect: emojiSymbolsActive;
overImageRect: emojiSymbolsOver;
chkOverImageRect: emojiSymbolsActive;
disImageRect: emojiSymbols;
chkDisImageRect: emojiSymbolsActive;
}
rbEmojiStickers: flatCheckbox(rbEmojiRecent) { rbEmojiStickers: flatCheckbox(rbEmojiRecent) {
imageRect: emojiStickers; imageRect: emojiStickers;
chkImageRect: emojiStickersActive; chkImageRect: emojiStickersActive;
@ -1556,15 +1577,25 @@ rbEmojiStickers: flatCheckbox(rbEmojiRecent) {
chkDisImageRect: emojiStickersActive; chkDisImageRect: emojiStickersActive;
} }
emojiPanPadding: margins(5px, 0px, 0px, 5px); emojiPanPadding: margins(5px, 0px, 0px, 5px);
emojiPanSize: size(28px, 28px); emojiPanSize: size(35px, 35px);
emojiPanSub: 0px;
emojiPanDuration: 200; emojiPanDuration: 200;
emojiPanHover: #f0f0f0; emojiPanHover: #f0f0f0;
emojiPanRound: 2px; emojiPanRound: 2px;
emojiPanHeader: 25px;
emojiPanHeaderFont: font(fsize semibold);
emojiPanHeaderColor: #999;
emojiPanHeaderLeft: 5px;
emojiPanHeaderTop: 5px;
emojiPanHeaderBg: #fffd;
emojiColorsPadding: 5px;
emojiColorsSep: 1px;
emojiColorsSepColor: #d5d5d5;
stickerPanRound: 3px; stickerPanRound: 3px;
stickerPanPadding: 2px; stickerPanPadding: 2px;
stickerPanDelete: sprite(158px, 197px, 12px, 12px); stickerPanDelete: sprite(123px, 132px, 12px, 12px);
stickerPanDeleteOpacity: 0.5; stickerPanDeleteOpacity: 0.5;
mvBgColor: #222; mvBgColor: #222;
@ -1654,7 +1685,7 @@ mvDocLink: linkButton(btnDefLink) {
mvDeltaFromLastAction: 5px; mvDeltaFromLastAction: 5px;
mvSwipeDistance: 80px; mvSwipeDistance: 80px;
medviewSaveMsgCheck: sprite(341px, 174px, 22px, 18px); medviewSaveMsgCheck: sprite(311px, 309px, 22px, 18px);
medviewSaveMsgFont: font(16px); medviewSaveMsgFont: font(16px);
medviewSaveMsgPadding: margins(55px, 19px, 29px, 20px); medviewSaveMsgPadding: margins(55px, 19px, 29px, 20px);
medviewSaveMsgCheckPos: point(23px, 21px); medviewSaveMsgCheckPos: point(23px, 21px);
@ -1664,7 +1695,7 @@ medviewSaveMsgShown: 2000;
medviewSaveMsgHiding: 2500; medviewSaveMsgHiding: 2500;
medviewSaveMsg: #000000b2; medviewSaveMsg: #000000b2;
mvTransparentBrush: sprite(148px, 197px, 8px, 8px); mvTransparentBrush: sprite(113px, 128px, 8px, 8px);
overviewPhotoSkip: 10px; overviewPhotoSkip: 10px;
overviewPhotoMinSize: 100px; overviewPhotoMinSize: 100px;

File diff suppressed because it is too large Load diff

View file

@ -132,7 +132,7 @@ int main(int argc, const char * argv[]) {
} }
if (update) { if (update) {
writeLog(@"Starting update files iteration!"); writeLog([@"Starting update files iteration, path: " stringByAppendingString: [workDir stringByAppendingString:@"tupdates/ready"]]);
NSFileManager *fileManager = [NSFileManager defaultManager]; NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *srcDir = [workDir stringByAppendingString:@"tupdates/ready/"]; NSString *srcDir = [workDir stringByAppendingString:@"tupdates/ready/"];
@ -142,6 +142,7 @@ int main(int argc, const char * argv[]) {
includingPropertiesForKeys:keys includingPropertiesForKeys:keys
options:0 options:0
errorHandler:^(NSURL *url, NSError *error) { errorHandler:^(NSURL *url, NSError *error) {
writeLog([[[@"Error in enumerating " stringByAppendingString:[url absoluteString]] stringByAppendingString: @" error is: "] stringByAppendingString: [error description]]);
return NO; return NO;
}]; }];
for (NSURL *url in enumerator) { for (NSURL *url in enumerator) {

View file

@ -73,9 +73,9 @@ namespace {
HistoryItem *hoveredItem = 0, *pressedItem = 0, *hoveredLinkItem = 0, *pressedLinkItem = 0, *contextItem = 0, *mousedItem = 0; HistoryItem *hoveredItem = 0, *pressedItem = 0, *hoveredLinkItem = 0, *pressedLinkItem = 0, *contextItem = 0, *mousedItem = 0;
QPixmap *sprite = 0, *emojis = 0; QPixmap *sprite = 0, *emojis = 0, *emojisLarge = 0;
typedef QMap<uint32, QPixmap> EmojisMap; typedef QMap<uint64, QPixmap> EmojisMap;
EmojisMap mainEmojisMap; EmojisMap mainEmojisMap;
QMap<int32, EmojisMap> otherEmojisMap; QMap<int32, EmojisMap> otherEmojisMap;
@ -1528,11 +1528,15 @@ namespace App {
} }
if (cRetina()) ::sprite->setDevicePixelRatio(cRetinaFactor()); if (cRetina()) ::sprite->setDevicePixelRatio(cRetinaFactor());
} }
emojiInit();
if (!::emojis) { if (!::emojis) {
::emojis = new QPixmap(st::emojisFile); ::emojis = new QPixmap(QLatin1String(EName));
if (cRetina()) ::emojis->setDevicePixelRatio(cRetinaFactor()); if (cRetina()) ::emojis->setDevicePixelRatio(cRetinaFactor());
} }
initEmoji(); if (!::emojisLarge) {
::emojisLarge = new QPixmap(QLatin1String(EmojiNames[EIndex + 1]));
if (cRetina()) ::emojisLarge->setDevicePixelRatio(cRetinaFactor());
}
} }
void deinitMedia(bool completely) { void deinitMedia(bool completely) {
@ -1548,6 +1552,8 @@ namespace App {
::sprite = 0; ::sprite = 0;
delete ::emojis; delete ::emojis;
::emojis = 0; ::emojis = 0;
delete ::emojisLarge;
::emojisLarge = 0;
mainEmojisMap.clear(); mainEmojisMap.clear();
otherEmojisMap.clear(); otherEmojisMap.clear();
@ -1616,19 +1622,25 @@ namespace App {
return *::emojis; return *::emojis;
} }
const QPixmap &emojiSingle(const EmojiData *emoji, int32 fontHeight) { const QPixmap &emojisLarge() {
return *::emojisLarge;
}
const QPixmap &emojiSingle(EmojiPtr emoji, int32 fontHeight) {
EmojisMap *map = &(fontHeight == st::taDefFlat.font->height ? mainEmojisMap : otherEmojisMap[fontHeight]); EmojisMap *map = &(fontHeight == st::taDefFlat.font->height ? mainEmojisMap : otherEmojisMap[fontHeight]);
EmojisMap::const_iterator i = map->constFind(emoji->code); EmojisMap::const_iterator i = map->constFind(emojiKey(emoji));
if (i == map->cend()) { if (i == map->cend()) {
QImage img(st::emojiImgSize + st::emojiPadding * cIntRetinaFactor() * 2, fontHeight * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); QImage img(ESize + st::emojiPadding * cIntRetinaFactor() * 2, fontHeight * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
if (cRetina()) img.setDevicePixelRatio(cRetinaFactor()); if (cRetina()) img.setDevicePixelRatio(cRetinaFactor());
{ {
QPainter p(&img); QPainter p(&img);
QPainter::CompositionMode m = p.compositionMode();
p.setCompositionMode(QPainter::CompositionMode_Source); p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(0, 0, img.width(), img.height(), Qt::transparent); p.fillRect(0, 0, img.width(), img.height(), Qt::transparent);
p.drawPixmap(QPoint(st::emojiPadding * cIntRetinaFactor(), (fontHeight * cIntRetinaFactor() - st::emojiImgSize) / 2), App::emojis(), QRect(emoji->x, emoji->y, st::emojiImgSize, st::emojiImgSize)); p.setCompositionMode(m);
emojiDraw(p, emoji, st::emojiPadding * cIntRetinaFactor(), (fontHeight * cIntRetinaFactor() - ESize) / 2);
} }
i = map->insert(emoji->code, QPixmap::fromImage(img, Qt::ColorOnly)); i = map->insert(emojiKey(emoji), QPixmap::fromImage(img, Qt::ColorOnly));
} }
return i.value(); return i.value();
} }

View file

@ -156,7 +156,8 @@ namespace App {
const QPixmap &sprite(); const QPixmap &sprite();
const QPixmap &emojis(); const QPixmap &emojis();
const QPixmap &emojiSingle(const EmojiData *emoji, int32 fontHeight); const QPixmap &emojisLarge();
const QPixmap &emojiSingle(EmojiPtr emoji, int32 fontHeight);
void initMedia(); void initMedia();
void deinitMedia(bool completely = true); void deinitMedia(bool completely = true);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 528 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1,003 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 531 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 956 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 532 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 219 KiB

View file

@ -84,7 +84,7 @@ void EmojiBox::fillBlocks() {
BlockRow currentRow; BlockRow currentRow;
currentRow.reserve(replacesInRow); currentRow.reserve(replacesInRow);
for (uint32 i = 0; i < replacesCount; ++i) { for (uint32 i = 0; i < replacesCount; ++i) {
Block block(getEmoji(replaces[i].code), QString::fromUtf8(replaces[i].replace)); Block block(emojiGet(replaces[i].code), QString::fromUtf8(replaces[i].replace));
currentRow.push_back(block); currentRow.push_back(block);
if (uint32(currentRow.size()) == replacesInRow) { if (uint32(currentRow.size()) == replacesInRow) {
_blocks.push_back(currentRow); _blocks.push_back(currentRow);
@ -125,8 +125,7 @@ void EmojiBox::paintEvent(QPaintEvent *e) {
int32 rowSize = i->size(), left = (width() - rowSize * st::emojiReplaceWidth) / 2; int32 rowSize = i->size(), left = (width() - rowSize * st::emojiReplaceWidth) / 2;
for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) { for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) {
if (j->emoji) { if (j->emoji) {
QPoint pos(left + (st::emojiReplaceWidth - st::emojiSize) / 2, top + (st::emojiReplaceHeight - _blockHeight) / 2); emojiDraw(p, j->emoji, left + (st::emojiReplaceWidth - st::emojiSize) / 2, top + (st::emojiReplaceHeight - _blockHeight) / 2);
p.drawPixmap(pos, App::emojis(), QRect(j->emoji->x, j->emoji->y, st::emojiImgSize, st::emojiImgSize));
} }
QRect trect(left, top + (st::emojiReplaceHeight + _blockHeight) / 2 - st::emojiTextFont->height, st::emojiReplaceWidth, st::emojiTextFont->height); QRect trect(left, top + (st::emojiReplaceHeight + _blockHeight) / 2 - st::emojiTextFont->height, st::emojiReplaceWidth, st::emojiTextFont->height);
p.drawText(trect, j->text, QTextOption(Qt::AlignHCenter | Qt::AlignTop)); p.drawText(trect, j->text, QTextOption(Qt::AlignHCenter | Qt::AlignTop));

File diff suppressed because it is too large Load diff

View file

@ -132,7 +132,68 @@ private:
}; };
class EmojiPanInner : public QWidget, public Animated { static const int EmojiColorsCount = 5;
class EmojiColorPicker : public TWidget, public Animated {
Q_OBJECT
public:
EmojiColorPicker(QWidget *parent);
void showEmoji(uint32 code);
void paintEvent(QPaintEvent *e);
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
bool animStep(float64 ms);
void showStart();
void clearSelection(bool fast = false);
public slots:
void hideStart(bool fast = false);
signals:
void emojiSelected(EmojiPtr emoji);
void hidden();
private:
void drawVariant(Painter &p, int variant);
void updateSelected();
bool _ignoreShow;
EmojiPtr _variants[EmojiColorsCount + 1];
typedef QMap<int32, uint64> EmojiAnimations; // index - showing, -index - hiding
EmojiAnimations _emojiAnimations;
float64 _hovers[EmojiColorsCount + 1];
int32 _selected, _pressedSel;
QPoint _lastMousePos;
bool _hiding;
QPixmap _cache;
anim::fvalue a_opacity;
QTimer _hideTimer;
BoxShadow _shadow;
};
class EmojiPanInner : public TWidget, public Animated {
Q_OBJECT Q_OBJECT
public: public:
@ -145,39 +206,67 @@ public:
void mouseReleaseEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e); void mouseMoveEvent(QMouseEvent *e);
void leaveEvent(QEvent *e); void leaveEvent(QEvent *e);
void leaveToChildEvent(QEvent *e);
void enterFromChildEvent(QEvent *e);
bool animStep(float64 ms); bool animStep(float64 ms);
void hideFinish();
void showEmojiPack(DBIEmojiTab packIndex); void showEmojiPack(DBIEmojiTab packIndex);
void clearSelection(bool fast = false); void clearSelection(bool fast = false);
DBIEmojiTab currentTab(int yOffset) const;
void refreshStickers();
void refreshRecent();
void setScrollTop(int top);
public slots: public slots:
void updateSelected(); void updateSelected();
void onSaveConfig(); void onSaveConfig();
void onShowPicker();
void onPickerHidden();
void onColorSelected(EmojiPtr emoji);
signals: signals:
void emojiSelected(EmojiPtr emoji); void emojiSelected(EmojiPtr emoji);
void stickerSelected(DocumentData *sticker); void stickerSelected(DocumentData *sticker);
void scrollToY(int y);
void disableScroll(bool dis);
private: private:
int countHeight();
void selectEmoji(EmojiPtr emoji);
typedef QMap<int32, uint64> EmojiAnimations; // index - showing, -index - hiding typedef QMap<int32, uint64> EmojiAnimations; // index - showing, -index - hiding
EmojiAnimations _emojiAnimations; EmojiAnimations _emojiAnimations;
int _top;
int _counts[emojiTabCount], _count;
StickerPack _stickers; StickerPack _stickers;
QVector<bool> _isUserGen; QVector<bool> _isUserGen;
QVector<EmojiPtr> _emojis; QVector<EmojiPtr> _emojis[emojiTabCount];
QVector<float64> _hovers; QVector<float64> _hovers[emojiTabCount + 1]; // + stickers hovers and stickers-x hovers
DBIEmojiTab _tab; float64 _stickerWidth;
int32 _selected, _xSelected, _pressedSel, _xPressedSel; int32 _esize, _stickerSize;
int32 _selected, _pressedSel, _pickerSel;
QPoint _lastMousePos; QPoint _lastMousePos;
QTimer _saveConfigTimer; QTimer _saveConfigTimer;
EmojiColorPicker _picker;
QTimer _showPickerTimer;
}; };
class EmojiPan : public TWidget, public Animated { class EmojiPan : public TWidget, public Animated {
@ -203,6 +292,8 @@ public:
bool eventFilter(QObject *obj, QEvent *e); bool eventFilter(QObject *obj, QEvent *e);
void refreshStickers();
public slots: public slots:
void hideStart(); void hideStart();
@ -212,6 +303,7 @@ public slots:
void onWndActiveChanged(); void onWndActiveChanged();
void onTabChange(); void onTabChange();
void onScroll();
signals: signals:
@ -224,6 +316,8 @@ private:
void showAll(); void showAll();
void hideAll(); void hideAll();
bool _noTabUpdate;
int32 _width, _height; int32 _width, _height;
bool _hiding; bool _hiding;
QPixmap _cache; QPixmap _cache;
@ -234,7 +328,7 @@ private:
BoxShadow _shadow; BoxShadow _shadow;
FlatRadiobutton _recent, _people, _nature, _objects, _places, _symbols, _stickers; FlatRadiobutton _recent, _people, _nature, _food, _celebration, _activity, _travel, _objects, _stickers;
int32 _emojiPack; int32 _emojiPack;
ScrollArea _scroll; ScrollArea _scroll;

File diff suppressed because it is too large Load diff

View file

@ -19,10 +19,94 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include "gui/text.h" #include "gui/text.h"
void initEmoji(); void emojiInit();
EmojiPtr getEmoji(uint32 code); EmojiPtr emojiGet(uint32 code);
EmojiPtr emojiGet(uint32 code, uint32 code2);
EmojiPtr emojiGet(EmojiPtr emoji, uint32 color);
EmojiPtr emojiGet(const QChar *from, const QChar *end);
QString emojiGetSequence(int index);
void findEmoji(const QChar *ch, const QChar *e, const QChar *&newEmojiEnd, uint32 &emojiCode); inline uint64 emojiKey(EmojiPtr emoji) {
uint64 key = emoji->code;
if (emoji->code2) {
key = (key << 32) | uint64(emoji->code2);
} else if (emoji->color && ((emoji->color & 0xFFFF0000U) != 0xFFFF0000U)) {
key = (key << 32) | uint64(emoji->color);
}
return key;
}
inline EmojiPtr emojiFromKey(uint64 key) {
uint32 code = uint32(key >> 32), code2 = uint32(key & 0xFFFFFFFFLLU);
if (!code && code2) {
code = code2;
code2 = 0;
}
EmojiPtr emoji = emojiGet(code);
if (emoji == TwoSymbolEmoji) {
return emojiGet(code, code2);
} else if (emoji && emoji->color && code2) {
return emojiGet(emoji, code2);
}
return emoji;
}
inline EmojiPtr emojiFromUrl(const QString &url) {
return emojiFromKey(url.midRef(10).toULongLong(0, 16)); // skip emoji://e.
}
inline EmojiPtr emojiFromText(const QChar *ch, const QChar *e, int &len) {
QString tmp(ch, e - ch);
QByteArray tmp2 = tmp.toUtf8();
const char *tmp3 = tmp2.constData();
EmojiPtr emoji = 0;
if (ch + 1 < e && ((ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) || (((ch->unicode() >= 48 && ch->unicode() < 58) || ch->unicode() == 35) && (ch + 1)->unicode() == 0x20E3))) {
uint32 code = (ch->unicode() << 16) | (ch + 1)->unicode();
emoji = emojiGet(code);
if (emoji) {
if (emoji == TwoSymbolEmoji) { // check two symbol
if (ch + 3 >= e) {
emoji = 0;
} else {
uint32 code2 = ((uint32((ch + 2)->unicode()) << 16) | uint32((ch + 3)->unicode()));
emoji = emojiGet(code, code2);
}
} else {
if (ch + 2 < e && (ch + 2)->unicode() == 0x200D) { // check sequence
EmojiPtr seq = emojiGet(ch, e);
if (seq) {
emoji = seq;
}
}
}
}
} else if (ch < e) {
emoji = emojiGet(ch->unicode());
Q_ASSERT(emoji != TwoSymbolEmoji);
}
if (emoji) {
len = emoji->len + ((ch + emoji->len < e && (ch + emoji->len)->unicode() == 0xFE0F) ? 1 : 0);
if (emoji->color && (ch + len + 1 < e && (ch + len)->isHighSurrogate() && (ch + len + 1)->isLowSurrogate())) { // color
uint32 color = ((uint32((ch + len)->unicode()) << 16) | uint32((ch + len + 1)->unicode()));
EmojiPtr col = emojiGet(emoji, color);
if (col && col != emoji) {
len += col->len - emoji->len;
emoji = col;
if (ch + len < e && (ch + len)->unicode() == 0xFE0F) {
++len;
}
}
}
}
return emoji;
}
extern int EmojiSizes[5], EIndex, ESize;
extern const char *EmojiNames[5], *EName;
void emojiFind(const QChar *ch, const QChar *e, const QChar *&newEmojiEnd, uint32 &emojiCode);
inline bool emojiEdge(const QChar *ch) { inline bool emojiEdge(const QChar *ch) {
return true; return true;
@ -48,7 +132,7 @@ inline QString replaceEmojis(const QString &text) {
uint32 emojiCode = 0; uint32 emojiCode = 0;
const QChar *newEmojiEnd = 0; const QChar *newEmojiEnd = 0;
if (canFindEmoji) { if (canFindEmoji) {
findEmoji(ch, e, newEmojiEnd, emojiCode); emojiFind(ch, e, newEmojiEnd, emojiCode);
} }
while (currentLink < lnkCount && ch >= lnkRanges[currentLink].from + lnkRanges[currentLink].len) { while (currentLink < lnkCount && ch >= lnkRanges[currentLink].from + lnkRanges[currentLink].len) {
@ -91,4 +175,5 @@ inline QString replaceEmojis(const QString &text) {
return result; return result;
} }
int emojiPackCount(DBIEmojiTab tab);
EmojiPack emojiPack(DBIEmojiTab tab); EmojiPack emojiPack(DBIEmojiTab tab);

View file

@ -174,8 +174,7 @@ EmojiPtr FlatTextarea::getSingleEmoji() const {
if (!text.isEmpty()) { if (!text.isEmpty()) {
QTextCharFormat format = fragment.charFormat(); QTextCharFormat format = fragment.charFormat();
QString imageName = static_cast<const QTextImageFormat*>(&format)->name(); return emojiFromUrl(static_cast<const QTextImageFormat*>(&format)->name());
return getEmoji(imageName.mid(8).toUInt(0, 16));
} }
return 0; return 0;
} }
@ -288,7 +287,7 @@ void FlatTextarea::getSingleEmojiFragment(QString &text, QTextFragment &fragment
} }
if (f.isImageFormat() && !t.isEmpty() && t.at(0).unicode() == QChar::ObjectReplacementCharacter) { if (f.isImageFormat() && !t.isEmpty() && t.at(0).unicode() == QChar::ObjectReplacementCharacter) {
QString imageName = static_cast<QTextImageFormat*>(&f)->name(); QString imageName = static_cast<QTextImageFormat*>(&f)->name();
if (imageName.midRef(0, 8) == qsl("emoji://")) { if (imageName.startsWith(QLatin1String("emoji://e."))) {
fragment = fr; fragment = fr;
text = t; text = t;
return; return;
@ -372,10 +371,8 @@ QString FlatTextarea::getText(int32 start, int32 end) const {
case QChar::ObjectReplacementCharacter: case QChar::ObjectReplacementCharacter:
if (emojiText.isEmpty() && f.isImageFormat()) { if (emojiText.isEmpty() && f.isImageFormat()) {
QString imageName = static_cast<QTextImageFormat*>(&f)->name(); QString imageName = static_cast<QTextImageFormat*>(&f)->name();
if (imageName.midRef(0, 8) == qsl("emoji://")) { if (imageName.startsWith(QLatin1String("emoji://e."))) {
uint32 index = imageName.mid(8).toUInt(0, 16); if (EmojiPtr emoji = emojiFromUrl(imageName)) {
const EmojiData *emoji = getEmoji(index);
if (emoji) {
emojiText = textEmojiString(emoji); emojiText = textEmojiString(emoji);
} }
} }
@ -520,7 +517,7 @@ void FlatTextarea::insertEmoji(EmojiPtr emoji, QTextCursor c) {
c.removeSelectedText(); c.removeSelectedText();
QPixmap img(App::emojiSingle(emoji, _st.font->height)); QPixmap img(App::emojiSingle(emoji, _st.font->height));
QString url = qsl("emoji://") + QString::number(emoji->code, 16); QString url = qsl("emoji://e.") + QString::number(emojiKey(emoji), 16);
document()->addResource(QTextDocument::ImageResource, QUrl(url), QVariant(img)); document()->addResource(QTextDocument::ImageResource, QUrl(url), QVariant(img));
QTextImageFormat imageFormat; QTextImageFormat imageFormat;
imageFormat.setWidth(img.width() / cIntRetinaFactor()); imageFormat.setWidth(img.width() / cIntRetinaFactor());
@ -546,33 +543,20 @@ void FlatTextarea::processDocumentContentsChange(int position, int charsAdded) {
QTextFragment fragment(iter.fragment()); QTextFragment fragment(iter.fragment());
if (!fragment.isValid()) continue; if (!fragment.isValid()) continue;
int32 p = fragment.position(), e = p + fragment.length(); int32 fp = fragment.position(), fe = fp + fragment.length();
if (p >= end || e <= start) { if (fp >= end || fe <= start) {
continue; continue;
} }
QString t(fragment.text()); QString t(fragment.text());
for (const QChar *ch = t.constData(), *e = ch + t.size(); ch != e; ++ch) { const QChar *ch = t.constData(), *e = ch + t.size();
if (ch + 1 < e && (ch->isHighSurrogate() || (((ch->unicode() >= 48 && ch->unicode() < 58) || ch->unicode() == 35) && (ch + 1)->unicode() == 0x20E3))) { for (; ch != e; ++ch) {
emoji = getEmoji((ch->unicode() << 16) | (ch + 1)->unicode()); emoji = emojiFromText(ch, e, emojiLen);
if (emoji) { if (emoji) {
if (emoji->len == 4 && (ch + 3 >= e || ((uint32((ch + 2)->unicode()) << 16) | uint32((ch + 3)->unicode())) != emoji->code2)) { emojiPosition = fp + (ch - t.constData());
emoji = 0; break;
} else {
emojiPosition = p + (ch - t.constData());
emojiLen = emoji->len + ((ch + emoji->len < e && (ch + emoji->len)->unicode() == 0xFE0F) ? 1 : 0);
break;
}
}
++ch;
} else {
emoji = getEmoji(ch->unicode());
if (emoji) {
emojiPosition = p + (ch - t.constData());
emojiLen = emoji->len + ((ch + emoji->len < e && (ch + emoji->len)->unicode() == 0xFE0F) ? 1 : 0);
break;
}
} }
if (ch + 1 < e && ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) ++ch;
} }
if (emoji) break; if (emoji) break;
} }

View file

@ -94,7 +94,7 @@ void ScrollBar::updateBar(bool force) {
} }
if (newBar != _bar) { if (newBar != _bar) {
_bar = newBar; _bar = newBar;
update(); parentWidget()->update(geometry());
} }
if (_vertical) { if (_vertical) {
bool newTopSh = (_st->topsh < 0) || (_area->scrollTop() > _st->topsh), newBottomSh = (_st->bottomsh < 0) || (_area->scrollTop() < _area->scrollTopMax() - _st->bottomsh); bool newTopSh = (_st->topsh < 0) || (_area->scrollTop() > _st->topsh), newBottomSh = (_st->bottomsh < 0) || (_area->scrollTop() < _area->scrollTopMax() - _st->bottomsh);
@ -143,7 +143,7 @@ bool ScrollBar::animStep(float64 ms) {
a_bg.update(dt, anim::linear); a_bg.update(dt, anim::linear);
a_bar.update(dt, anim::linear); a_bar.update(dt, anim::linear);
} }
update(); parentWidget()->update(geometry());
return res; return res;
} }
@ -253,19 +253,16 @@ void ScrollBar::resizeEvent(QResizeEvent *e) {
} }
ScrollArea::ScrollArea(QWidget *parent, const style::flatScroll &st, bool handleTouch) : QScrollArea(parent), ScrollArea::ScrollArea(QWidget *parent, const style::flatScroll &st, bool handleTouch) : QScrollArea(parent),
_st(st), _disabled(false), _st(st),
hor(this, false, &_st), vert(this, true, &_st), topSh(this, &_st), bottomSh(this, &_st), hor(this, false, &_st), vert(this, true, &_st), topSh(this, &_st), bottomSh(this, &_st),
_touchEnabled(handleTouch), _touchScroll(false), _touchPress(false), _touchRightButton(false), _touchEnabled(handleTouch), _touchScroll(false), _touchPress(false), _touchRightButton(false),
_touchScrollState(TouchScrollManual), _touchPrevPosValid(false), _touchWaitingAcceleration(false), _touchScrollState(TouchScrollManual), _touchPrevPosValid(false), _touchWaitingAcceleration(false),
_touchSpeedTime(0), _touchAccelerationTime(0), _touchTime(0), _widgetAcceptsTouch(false) { _touchSpeedTime(0), _touchAccelerationTime(0), _touchTime(0), _widgetAcceptsTouch(false) {
connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SIGNAL(scrolled())); connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(onScrolled()));
connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SIGNAL(scrolled())); connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(onScrolled()));
connect(&vert, SIGNAL(topShadowVisibility(bool)), &topSh, SLOT(changeVisibility(bool))); connect(&vert, SIGNAL(topShadowVisibility(bool)), &topSh, SLOT(changeVisibility(bool)));
connect(&vert, SIGNAL(bottomShadowVisibility(bool)), &bottomSh, SLOT(changeVisibility(bool))); connect(&vert, SIGNAL(bottomShadowVisibility(bool)), &bottomSh, SLOT(changeVisibility(bool)));
vert.updateBar(true); vert.updateBar(true);
if (_st.hiding) {
connect(this, SIGNAL(scrolled()), this, SLOT(onScrolled()));
}
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@ -292,19 +289,31 @@ void ScrollArea::touchDeaccelerate(int32 elapsed) {
} }
void ScrollArea::onScrolled() { void ScrollArea::onScrolled() {
bool em = false;
int32 horValue = horizontalScrollBar()->value(), vertValue = verticalScrollBar()->value(); int32 horValue = horizontalScrollBar()->value(), vertValue = verticalScrollBar()->value();
if (_horValue != horValue) { if (_horValue != horValue) {
_horValue = horValue; if (_disabled) {
if (_st.hiding) { horizontalScrollBar()->setValue(_horValue);
hor.hideTimeout(_st.hiding); } else {
_horValue = horValue;
if (_st.hiding) {
hor.hideTimeout(_st.hiding);
}
em = true;
} }
} }
if (_vertValue != vertValue) { if (_vertValue != vertValue) {
_vertValue = vertValue; if (_disabled) {
if (_st.hiding) { verticalScrollBar()->setValue(_vertValue);
vert.hideTimeout(_st.hiding); } else {
_vertValue = vertValue;
if (_st.hiding) {
vert.hideTimeout(_st.hiding);
}
em = true;
} }
} }
if (em) emit scrolled();
} }
int ScrollArea::scrollWidth() const { int ScrollArea::scrollWidth() const {
@ -528,6 +537,21 @@ void ScrollArea::touchScrollUpdated(const QPoint &screenPos) {
touchUpdateSpeed(); touchUpdateSpeed();
} }
void ScrollArea::disableScroll(bool dis) {
_disabled = dis;
if (_disabled) {
hor.hideTimeout(0);
vert.hideTimeout(0);
}
}
void ScrollArea::scrollContentsBy(int dx, int dy) {
if (_disabled) {
return;
}
QScrollArea::scrollContentsBy(dx, dy);
}
bool ScrollArea::touchScroll(const QPoint &delta) { bool ScrollArea::touchScroll(const QPoint &delta) {
int32 scTop = scrollTop(), scMax = scrollTopMax(), scNew = snap(scTop - delta.y(), 0, scMax); int32 scTop = scrollTop(), scMax = scrollTopMax(), scNew = snap(scTop - delta.y(), 0, scMax);
if (scNew == scTop) return false; if (scNew == scTop) return false;
@ -559,6 +583,7 @@ void ScrollArea::keyPressEvent(QKeyEvent *e) {
} }
void ScrollArea::enterEvent(QEvent *e) { void ScrollArea::enterEvent(QEvent *e) {
if (_disabled) return;
if (_st.hiding) { if (_st.hiding) {
hor.hideTimeout(_st.hiding); hor.hideTimeout(_st.hiding);
vert.hideTimeout(_st.hiding); vert.hideTimeout(_st.hiding);

View file

@ -134,6 +134,7 @@ public:
public slots: public slots:
void scrollToY(int toTop, int toBottom = -1); void scrollToY(int toTop, int toBottom = -1);
void disableScroll(bool dis);
void onScrolled(); void onScrolled();
void onTouchTimer(); void onTouchTimer();
@ -146,6 +147,10 @@ signals:
void scrollFinished(); void scrollFinished();
void geometryChanged(); void geometryChanged();
protected:
void scrollContentsBy(int dx, int dy);
private: private:
bool touchScroll(const QPoint &delta); bool touchScroll(const QPoint &delta);
@ -156,6 +161,8 @@ private:
void touchUpdateSpeed(); void touchUpdateSpeed();
void touchDeaccelerate(int32 elapsed); void touchDeaccelerate(int32 elapsed);
bool _disabled;
style::flatScroll _st; style::flatScroll _st;
ScrollBar hor, vert; ScrollBar hor, vert;
ScrollShadow topSh, bottomSh; ScrollShadow topSh, bottomSh;

View file

@ -240,20 +240,25 @@ const QChar *textSkipCommand(const QChar *from, const QChar *end, bool canLink)
} }
QString textEmojiString(EmojiPtr emoji) { QString textEmojiString(EmojiPtr emoji) {
if ((emoji->code & 0xFFFF0000U) == 0xFFFF0000U) { // sequence
return emojiGetSequence(emoji->code & 0xFFFFU);
}
QString result; QString result;
result.reserve(emoji->len + (emoji->postfix ? 1 : 0)); result.reserve(emoji->len + (emoji->postfix ? 1 : 0));
switch (emoji->len) { if (!(emoji->code >> 16)) {
case 1: result.append(QChar(emoji->code & 0xFFFF)); break; result.append(QChar(emoji->code & 0xFFFF));
case 2: } else {
result.append(QChar((emoji->code >> 16) & 0xFFFF)); result.append(QChar((emoji->code >> 16) & 0xFFFF));
result.append(QChar(emoji->code & 0xFFFF)); result.append(QChar(emoji->code & 0xFFFF));
break; if (emoji->code2) {
case 4: result.append(QChar((emoji->code2 >> 16) & 0xFFFF));
result.append(QChar((emoji->code >> 16) & 0xFFFF)); result.append(QChar(emoji->code2 & 0xFFFF));
result.append(QChar(emoji->code & 0xFFFF)); }
result.append(QChar((emoji->code2 >> 16) & 0xFFFF)); }
result.append(QChar(emoji->code2 & 0xFFFF)); if (emoji->color && ((emoji->color & 0xFFFF0000U) != 0xFFFF0000U)) {
break; result.append(QChar((emoji->color >> 16) & 0xFFFF));
result.append(QChar(emoji->color & 0xFFFF));
} }
if (emoji->postfix) result.append(QChar(emoji->postfix)); if (emoji->postfix) result.append(QChar(emoji->postfix));
return result; return result;
@ -515,24 +520,15 @@ public:
} }
void parseEmojiFromCurrent() { void parseEmojiFromCurrent() {
const EmojiData *e = getEmoji(chInt); int len = 0, skipped = (chInt > 0xFFFFU) ? 1 : 0;
EmojiPtr e = emojiFromText(ptr - skipped, end, len);
if (!e) return; if (!e) return;
if (e->len > 2) { for (int l = len - skipped - 1; l > 0; --l) {
if (ptr + 2 >= end || e->code2 != ((uint32((ptr + 1)->unicode()) << 16) | uint32((ptr + 2)->unicode()))) {
return;
} else {
_t->_text.push_back(*++ptr);
_t->_text.push_back(*++ptr);
}
}
int emojiLen = e->len;
if (ptr + 1 < end && (ptr + 1)->unicode() == 0xFE0F) {
_t->_text.push_back(*++ptr); _t->_text.push_back(*++ptr);
++emojiLen;
} }
createBlock(-emojiLen); createBlock(-len);
emoji = e; emoji = e;
} }
@ -1326,7 +1322,7 @@ public:
} }
} }
} }
_p->drawPixmap(QPoint((glyphX + int(st::emojiPadding)).toInt(), _y + _yDelta + emojiY), App::emojis(), QRect(static_cast<EmojiBlock*>(currentBlock)->emoji->x, static_cast<EmojiBlock*>(currentBlock)->emoji->y, st::emojiImgSize, st::emojiImgSize)); emojiDraw(*_p, static_cast<EmojiBlock*>(currentBlock)->emoji, (glyphX + int(st::emojiPadding)).toInt(), _y + _yDelta + emojiY);
// } else if (_p && currentBlock->type() == TextBlockSkip) { // debug // } else if (_p && currentBlock->type() == TextBlockSkip) { // debug
// _p->fillRect(QRect(x.toInt(), _y, currentBlock->width(), static_cast<SkipBlock*>(currentBlock)->height()), QColor(0, 0, 0, 32)); // _p->fillRect(QRect(x.toInt(), _y, currentBlock->width(), static_cast<SkipBlock*>(currentBlock)->height()), QColor(0, 0, 0, 32));
} }
@ -4050,29 +4046,19 @@ bool textSplit(QString &sendingText, QString &leftText, int32 limit) {
} }
} }
} }
EmojiPtr e = 0; int elen = 0;
if (ch->isHighSurrogate()) { EmojiPtr e = emojiFromText(ch, end, elen);
if (ch + 1 < end && (ch + 1)->isLowSurrogate()) {
e = getEmoji((ch->unicode() << 16) | (ch + 1)->unicode());
if (!e) {
++ch;
}
}
} else {
if (ch + 1 < end) {
if (((ch->unicode() >= 48 && ch->unicode() < 58) || ch->unicode() == 35) && (ch + 1)->unicode() == 0x20E3) {
e = getEmoji((ch->unicode() << 16) | (ch + 1)->unicode());
} else if ((ch + 1)->unicode() == 0xFE0F) {
e = getEmoji(ch->unicode());
}
}
}
if (e) { if (e) {
ch += (e->len - 1); for (int i = 0; i < elen; ++i, ++ch, ++s) {
if (ch + 1 < end && (ch + 1)->unicode() == 0xFE0F) { if (ch->isHighSurrogate() && i + 1 < elen && (ch + 1)->isLowSurrogate()) {
++ch; ++ch;
++s; ++i;
}
} }
--ch;
--s;
} else if (ch->isHighSurrogate() && ch + 1 < end && (ch + 1)->isLowSurrogate()) {
++ch;
} }
if (s >= limit) { if (s >= limit) {
sendingText = leftText.mid(0, good - start); sendingText = leftText.mid(0, good - start);
@ -4250,3 +4236,7 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some
return lnkRanges; return lnkRanges;
} }
void emojiDraw(QPainter &p, EmojiPtr e, int x, int y) {
p.drawPixmap(QPoint(x, y), App::emojis(), QRect(e->x * ESize, e->y * ESize, ESize, ESize));
}

View file

@ -49,6 +49,8 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich = false);
#include "gui/emoji_config.h" #include "gui/emoji_config.h"
void emojiDraw(QPainter &p, EmojiPtr e, int x, int y);
#include "../../../QtStatic/qtbase/src/gui/text/qfontengine_p.h" #include "../../../QtStatic/qtbase/src/gui/text/qfontengine_p.h"
enum TextBlockType { enum TextBlockType {

View file

@ -3448,9 +3448,9 @@ void HistoryWebPage::draw(QPainter &p, const HistoryItem *parent, bool selected,
p.fillRect(QRect(width - pixwidth, 0, pixwidth, pixheight), st::black->b); p.fillRect(QRect(width - pixwidth, 0, pixwidth, pixheight), st::black->b);
} }
if (_pixw > pixwidth) { if (_pixw > pixwidth) {
p.drawPixmap(QRect(width - pixwidth, (pixheight - _pixh) / 2, pixwidth, _pixh), pix, QRect((_pixw - pixwidth) / 2, 0, pixwidth, _pixh)); p.drawPixmap(QRect(width - pixwidth, (pixheight - _pixh) / 2, pixwidth, _pixh), pix, QRect(cIntRetinaFactor() * (_pixw - pixwidth) / 2, 0, cIntRetinaFactor() * pixwidth, cIntRetinaFactor() * _pixh));
} else if (_pixh > pixheight) { } else if (_pixh > pixheight) {
p.drawPixmap(QRect(width - pixwidth + (pixwidth - _pixw) / 2, 0, _pixw, pixheight), pix, QRect(0, (_pixh - pixheight) / 2, _pixw, pixheight)); p.drawPixmap(QRect(width - pixwidth + (pixwidth - _pixw) / 2, 0, _pixw, pixheight), pix, QRect(0, cIntRetinaFactor() * (_pixh - pixheight) / 2, cIntRetinaFactor() * _pixw, cIntRetinaFactor() * pixheight));
} else { } else {
p.drawPixmap(QPoint(width - pixwidth + (pixwidth - _pixw) / 2, (pixheight - _pixh) / 2), pix); p.drawPixmap(QPoint(width - pixwidth + (pixwidth - _pixw) / 2, (pixheight - _pixh) / 2), pix);
} }

View file

@ -1763,9 +1763,7 @@ void HistoryWidget::updateTyping(bool typing) {
//} //}
void HistoryWidget::updateRecentStickers() { void HistoryWidget::updateRecentStickers() {
if (cEmojiTab() == dbietStickers) { _emojiPan.refreshStickers();
_emojiPan.onTabChange();
}
} }
void HistoryWidget::typingDone(const MTPBool &result, mtpRequestId req) { void HistoryWidget::typingDone(const MTPBool &result, mtpRequestId req) {
@ -1852,7 +1850,6 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
} }
cSetRecentStickers(add); cSetRecentStickers(add);
Local::writeRecentStickers(); Local::writeRecentStickers();
_emojiPan.onTabChange();
} }
const QVector<MTPStickerPack> &packs(d.vpacks.c_vector().v); const QVector<MTPStickerPack> &packs(d.vpacks.c_vector().v);
@ -1862,23 +1859,11 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
QString emoticon(qs(p.vemoticon)); QString emoticon(qs(p.vemoticon));
EmojiPtr e = 0; EmojiPtr e = 0;
for (const QChar *ch = emoticon.constData(), *end = emoticon.constEnd(); ch != end; ++ch) { for (const QChar *ch = emoticon.constData(), *end = emoticon.constEnd(); ch != end; ++ch) {
if (ch->isHighSurrogate()) { int len = 0;
if (ch + 1 < end && (ch + 1)->isLowSurrogate()) { e = emojiFromText(ch, end, len);
e = getEmoji((ch->unicode() << 16) | (ch + 1)->unicode());
if (!e) {
++ch;
}
}
} else {
if (ch + 1 < end) {
if (((ch->unicode() >= 48 && ch->unicode() < 58) || ch->unicode() == 35) && (ch + 1)->unicode() == 0x20E3) {
e = getEmoji((ch->unicode() << 16) | (ch + 1)->unicode());
} else if ((ch + 1)->unicode() == 0xFE0F) {
e = getEmoji(ch->unicode());
}
}
}
if (e) break; if (e) break;
if (ch + 1 < end && ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) ++ch;
} }
if (e) { if (e) {
const QVector<MTPlong> docs(p.vdocuments.c_vector().v); const QVector<MTPlong> docs(p.vdocuments.c_vector().v);
@ -1912,7 +1897,7 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
} }
// updateStickerPan(); // updateStickerPan();
_emojiPan.onTabChange(); _emojiPan.refreshStickers();
} }
} }

View file

@ -905,24 +905,62 @@ namespace {
if (!_checkStreamStatus(stream)) return false; if (!_checkStreamStatus(stream)) return false;
switch (v) { switch (v) {
case dbietRecent: cSetEmojiTab(dbietRecent); break; case dbietRecent : cSetEmojiTab(dbietRecent ); break;
case dbietPeople: cSetEmojiTab(dbietPeople); break; case dbietPeople : cSetEmojiTab(dbietPeople ); break;
case dbietNature: cSetEmojiTab(dbietNature); break; case dbietNature : cSetEmojiTab(dbietNature ); break;
case dbietObjects: cSetEmojiTab(dbietObjects); break; case dbietFood : cSetEmojiTab(dbietFood ); break;
case dbietPlaces: cSetEmojiTab(dbietPlaces); break; case dbietCelebration: cSetEmojiTab(dbietCelebration); break;
case dbietSymbols: cSetEmojiTab(dbietSymbols); break; case dbietActivity : cSetEmojiTab(dbietActivity ); break;
case dbietStickers: cSetEmojiTab(dbietStickers); break; case dbietTravel : cSetEmojiTab(dbietTravel ); break;
case dbietObjects : cSetEmojiTab(dbietObjects ); break;
case dbietStickers : cSetEmojiTab(dbietStickers ); break;
}
} break;
case dbiRecentEmojisOld: {
RecentEmojisPreloadOld v;
stream >> v;
if (!_checkStreamStatus(stream)) return false;
if (!v.isEmpty()) {
RecentEmojisPreload p;
p.reserve(v.size());
for (int i = 0; i < v.size(); ++i) {
uint64 e(v.at(i).first);
switch (e) {
case 0xD83CDDEFLLU: e = 0xD83CDDEFD83CDDF5LLU; break;
case 0xD83CDDF0LLU: e = 0xD83CDDF0D83CDDF7LLU; break;
case 0xD83CDDE9LLU: e = 0xD83CDDE9D83CDDEALLU; break;
case 0xD83CDDE8LLU: e = 0xD83CDDE8D83CDDF3LLU; break;
case 0xD83CDDFALLU: e = 0xD83CDDFAD83CDDF8LLU; break;
case 0xD83CDDEBLLU: e = 0xD83CDDEBD83CDDF7LLU; break;
case 0xD83CDDEALLU: e = 0xD83CDDEAD83CDDF8LLU; break;
case 0xD83CDDEELLU: e = 0xD83CDDEED83CDDF9LLU; break;
case 0xD83CDDF7LLU: e = 0xD83CDDF7D83CDDFALLU; break;
case 0xD83CDDECLLU: e = 0xD83CDDECD83CDDE7LLU; break;
}
p.push_back(qMakePair(e, v.at(i).second));
}
cSetRecentEmojisPreload(p);
} }
} break; } break;
case dbiRecentEmojis: { case dbiRecentEmojis: {
RecentEmojiPreload v; RecentEmojisPreload v;
stream >> v; stream >> v;
if (!_checkStreamStatus(stream)) return false; if (!_checkStreamStatus(stream)) return false;
cSetRecentEmojisPreload(v); cSetRecentEmojisPreload(v);
} break; } break;
case dbiEmojiVariants: {
EmojiColorVariants v;
stream >> v;
if (!_checkStreamStatus(stream)) return false;
cSetEmojiVariants(v);
} break;
case dbiDialogLastPath: { case dbiDialogLastPath: {
QString path; QString path;
stream >> path; stream >> path;
@ -1140,7 +1178,8 @@ namespace {
uint32 size = 11 * (sizeof(quint32) + sizeof(qint32)); uint32 size = 11 * (sizeof(quint32) + sizeof(qint32));
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath()); size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath());
size += sizeof(quint32) + sizeof(qint32) + cGetRecentEmojis().size() * (sizeof(uint32) + sizeof(ushort)); size += sizeof(quint32) + sizeof(qint32) + cGetRecentEmojis().size() * (sizeof(uint64) + sizeof(ushort));
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
size += sizeof(quint32) + _stringSize(cDialogLastPath()); size += sizeof(quint32) + _stringSize(cDialogLastPath());
EncryptedDescriptor data(size); EncryptedDescriptor data(size);
@ -1158,13 +1197,15 @@ namespace {
data.stream << quint32(dbiEmojiTab) << qint32(cEmojiTab()); data.stream << quint32(dbiEmojiTab) << qint32(cEmojiTab());
data.stream << quint32(dbiDialogLastPath) << cDialogLastPath(); data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
RecentEmojiPreload v; RecentEmojisPreload v;
v.reserve(cGetRecentEmojis().size()); v.reserve(cGetRecentEmojis().size());
for (RecentEmojiPack::const_iterator i = cGetRecentEmojis().cbegin(), e = cGetRecentEmojis().cend(); i != e; ++i) { for (RecentEmojiPack::const_iterator i = cGetRecentEmojis().cbegin(), e = cGetRecentEmojis().cend(); i != e; ++i) {
v.push_back(qMakePair(i->first->code, i->second)); v.push_back(qMakePair(emojiKey(i->first), i->second));
} }
data.stream << quint32(dbiRecentEmojis) << v; data.stream << quint32(dbiRecentEmojis) << v;
data.stream << quint32(dbiEmojiVariants) << cEmojiVariants();
FileWriteDescriptor file(_userSettingsKey); FileWriteDescriptor file(_userSettingsKey);
file.writeEncrypted(data); file.writeEncrypted(data);
} }

View file

@ -86,7 +86,8 @@ bool gHasPasscode = false;
DBIEmojiTab gEmojiTab = dbietRecent; DBIEmojiTab gEmojiTab = dbietRecent;
RecentEmojiPack gRecentEmojis; RecentEmojiPack gRecentEmojis;
RecentEmojiPreload gRecentEmojisPreload; RecentEmojisPreload gRecentEmojisPreload;
EmojiColorVariants gEmojiVariants;
AllStickers gStickers; AllStickers gStickers;
QByteArray gStickersHash; QByteArray gStickersHash;
@ -185,22 +186,22 @@ void settingsParseArgs(int argc, char *argv[]) {
} }
} }
const RecentEmojiPack &cGetRecentEmojis() { RecentEmojiPack &cGetRecentEmojis() {
if (cRecentEmojis().isEmpty()) { if (cRecentEmojis().isEmpty()) {
RecentEmojiPack r; RecentEmojiPack r;
if (!cRecentEmojisPreload().isEmpty()) { if (!cRecentEmojisPreload().isEmpty()) {
RecentEmojiPreload p(cRecentEmojisPreload()); RecentEmojisPreload p(cRecentEmojisPreload());
cSetRecentEmojisPreload(RecentEmojiPreload()); cSetRecentEmojisPreload(RecentEmojisPreload());
r.reserve(p.size()); r.reserve(p.size());
for (RecentEmojiPreload::const_iterator i = p.cbegin(), e = p.cend(); i != e; ++i) { for (RecentEmojisPreload::const_iterator i = p.cbegin(), e = p.cend(); i != e; ++i) {
uint32 code = ((i->first & 0xFFFFU) == 0xFE0FU) ? ((i->first >> 16) & 0xFFFFU) : i->first; uint64 code = ((!(i->first & 0xFFFFFFFF00000000LLU) && (i->first & 0xFFFFU) == 0xFE0FU)) ? ((i->first >> 16) & 0xFFFFU) : i->first;
EmojiPtr ep(getEmoji(code)); EmojiPtr ep(emojiFromKey(code));
if (!ep) continue; if (!ep) continue;
if (ep->postfix) { if (ep->postfix) {
int32 j = 0, l = r.size(); int32 j = 0, l = r.size();
for (; j < l; ++j) { for (; j < l; ++j) {
if (r[j].first->code == code) { if (emojiKey(r[j].first) == code) {
break; break;
} }
} }
@ -211,47 +212,47 @@ const RecentEmojiPack &cGetRecentEmojis() {
r.push_back(qMakePair(ep, i->second)); r.push_back(qMakePair(ep, i->second));
} }
} }
uint32 defaultRecent[] = { uint64 defaultRecent[] = {
0xD83DDE02U, 0xD83DDE02LLU,
0xD83DDE18U, 0xD83DDE18LLU,
0x2764U, 0x2764LLU,
0xD83DDE0DU, 0xD83DDE0DLLU,
0xD83DDE0AU, 0xD83DDE0ALLU,
0xD83DDE01U, 0xD83DDE01LLU,
0xD83DDC4DU, 0xD83DDC4DLLU,
0x263AU, 0x263ALLU,
0xD83DDE14U, 0xD83DDE14LLU,
0xD83DDE04U, 0xD83DDE04LLU,
0xD83DDE2DU, 0xD83DDE2DLLU,
0xD83DDC8BU, 0xD83DDC8BLLU,
0xD83DDE12U, 0xD83DDE12LLU,
0xD83DDE33U, 0xD83DDE33LLU,
0xD83DDE1CU, 0xD83DDE1CLLU,
0xD83DDE48U, 0xD83DDE48LLU,
0xD83DDE09U, 0xD83DDE09LLU,
0xD83DDE03U, 0xD83DDE03LLU,
0xD83DDE22U, 0xD83DDE22LLU,
0xD83DDE1DU, 0xD83DDE1DLLU,
0xD83DDE31U, 0xD83DDE31LLU,
0xD83DDE21U, 0xD83DDE21LLU,
0xD83DDE0FU, 0xD83DDE0FLLU,
0xD83DDE1EU, 0xD83DDE1ELLU,
0xD83DDE05U, 0xD83DDE05LLU,
0xD83DDE1AU, 0xD83DDE1ALLU,
0xD83DDE4AU, 0xD83DDE4ALLU,
0xD83DDE0CU, 0xD83DDE0CLLU,
0xD83DDE00U, 0xD83DDE00LLU,
0xD83DDE0BU, 0xD83DDE0BLLU,
0xD83DDE06U, 0xD83DDE06LLU,
0xD83DDC4CU, 0xD83DDC4CLLU,
0xD83DDE10U, 0xD83DDE10LLU,
0xD83DDE15U, 0xD83DDE15LLU,
}; };
for (int32 i = 0, s = sizeof(defaultRecent) / sizeof(defaultRecent[0]); i < s; ++i) { for (int32 i = 0, s = sizeof(defaultRecent) / sizeof(defaultRecent[0]); i < s; ++i) {
if (r.size() >= EmojiPadPerRow * EmojiPadRowsPerPage) break; if (r.size() >= EmojiPadPerRow * EmojiPadRowsPerPage) break;
EmojiPtr ep(getEmoji(defaultRecent[i])); EmojiPtr ep(emojiGet(defaultRecent[i]));
if (!ep) continue; if (!ep || ep == TwoSymbolEmoji) continue;
int32 j = 0, l = r.size(); int32 j = 0, l = r.size();
for (; j < l; ++j) { for (; j < l; ++j) {
@ -265,5 +266,5 @@ const RecentEmojiPack &cGetRecentEmojis() {
} }
cSetRecentEmojis(r); cSetRecentEmojis(r);
} }
return cRecentEmojis(); return cRefRecentEmojis();
} }

View file

@ -41,6 +41,11 @@ inline void cSet##Name(const Type &Name) { \
g##Name = Name; \ g##Name = Name; \
} }
#define DeclareRefSetting(Type, Name) DeclareSetting(Type, Name) \
inline Type &cRef##Name() { \
return g##Name; \
}
DeclareSetting(bool, Rtl); DeclareSetting(bool, Rtl);
DeclareSetting(Qt::LayoutDirection, LangDir); DeclareSetting(Qt::LayoutDirection, LangDir);
inline bool rtl() { inline bool rtl() {
@ -153,23 +158,28 @@ T convertScale(T v) {
DeclareSetting(DBIEmojiTab, EmojiTab); DeclareSetting(DBIEmojiTab, EmojiTab);
struct EmojiData { struct EmojiData {
EmojiData(uint16 x, uint16 y, uint32 code, uint32 code2, uint16 len, uint16 postfix = 0) : x(x), y(y), code(code), code2(code2), len(len), postfix(postfix) { EmojiData(uint16 x, uint16 y, uint32 code, uint32 code2, uint16 len, uint16 postfix, uint32 color) : x(x), y(y), code(code), code2(code2), len(len), postfix(postfix), color(color) {
} }
uint16 x, y; uint16 x, y;
uint32 code, code2; uint32 code, code2;
uint16 len; uint16 len;
uint16 postfix; uint16 postfix;
uint32 color;
}; };
typedef const EmojiData *EmojiPtr; typedef const EmojiData *EmojiPtr;
static EmojiPtr TwoSymbolEmoji = EmojiPtr(0x01);
typedef QVector<EmojiPtr> EmojiPack; typedef QVector<EmojiPtr> EmojiPack;
typedef QVector<QPair<uint32, ushort> > RecentEmojiPreload; typedef QVector<QPair<uint32, ushort> > RecentEmojisPreloadOld;
typedef QVector<QPair<uint64, ushort> > RecentEmojisPreload;
typedef QVector<QPair<EmojiPtr, ushort> > RecentEmojiPack; typedef QVector<QPair<EmojiPtr, ushort> > RecentEmojiPack;
DeclareSetting(RecentEmojiPack, RecentEmojis); typedef QMap<uint32, uint64> EmojiColorVariants;
DeclareSetting(RecentEmojiPreload, RecentEmojisPreload); DeclareRefSetting(RecentEmojiPack, RecentEmojis);
DeclareSetting(RecentEmojisPreload, RecentEmojisPreload);
DeclareRefSetting(EmojiColorVariants, EmojiVariants);
const RecentEmojiPack &cGetRecentEmojis(); RecentEmojiPack &cGetRecentEmojis();
struct DocumentData; struct DocumentData;
typedef QVector<DocumentData*> StickerPack; typedef QVector<DocumentData*> StickerPack;

View file

@ -10,10 +10,11 @@
<file>art/sprite_125x.png</file> <file>art/sprite_125x.png</file>
<file>art/sprite_150x.png</file> <file>art/sprite_150x.png</file>
<file>art/sprite_200x.png</file> <file>art/sprite_200x.png</file>
<file>art/emoji.png</file> <file>art/emoji.webp</file>
<file>art/emoji_125x.png</file> <file>art/emoji_125x.webp</file>
<file>art/emoji_150x.png</file> <file>art/emoji_150x.webp</file>
<file>art/emoji_200x.png</file> <file>art/emoji_200x.webp</file>
<file>art/emoji_250x.webp</file>
<file>art/blank.gif</file> <file>art/blank.gif</file>
<file>art/icon256.png</file> <file>art/icon256.png</file>
<file>art/iconbig256.png</file> <file>art/iconbig256.png</file>

View file

@ -10,10 +10,11 @@
<file>art/sprite_125x.png</file> <file>art/sprite_125x.png</file>
<file>art/sprite_150x.png</file> <file>art/sprite_150x.png</file>
<file>art/sprite_200x.png</file> <file>art/sprite_200x.png</file>
<file>art/emoji.png</file> <file>art/emoji.webp</file>
<file>art/emoji_125x.png</file> <file>art/emoji_125x.webp</file>
<file>art/emoji_150x.png</file> <file>art/emoji_150x.webp</file>
<file>art/emoji_200x.png</file> <file>art/emoji_200x.webp</file>
<file>art/emoji_250x.webp</file>
<file>art/blank.gif</file> <file>art/blank.gif</file>
<file>art/icon256.png</file> <file>art/icon256.png</file>
</qresource> </qresource>

View file

@ -249,7 +249,7 @@ enum DataBlockId {
dbiDownloadPath = 21, dbiDownloadPath = 21,
dbiScale = 22, dbiScale = 22,
dbiEmojiTab = 23, dbiEmojiTab = 23,
dbiRecentEmojis = 24, dbiRecentEmojisOld = 24,
dbiLoggedPhoneNumber = 25, dbiLoggedPhoneNumber = 25,
dbiMutedPeers = 26, dbiMutedPeers = 26,
// 27 reserved // 27 reserved
@ -261,6 +261,8 @@ enum DataBlockId {
dbiTileBackground = 33, dbiTileBackground = 33,
dbiAutoLock = 34, dbiAutoLock = 34,
dbiDialogLastPath = 35, dbiDialogLastPath = 35,
dbiRecentEmojis = 36,
dbiEmojiVariants = 37,
dbiEncryptedWithSalt = 333, dbiEncryptedWithSalt = 333,
dbiEncrypted = 444, dbiEncrypted = 444,
@ -318,14 +320,21 @@ enum DBIScale {
}; };
enum DBIEmojiTab { enum DBIEmojiTab {
dbietRecent = -1, dbietRecent = -1,
dbietPeople = 0, dbietPeople = 0,
dbietNature = 1, dbietNature = 1,
dbietObjects = 2, dbietFood = 2,
dbietPlaces = 3, dbietCelebration = 3,
dbietSymbols = 4, dbietActivity = 4,
dbietStickers = 666, dbietTravel = 5,
dbietObjects = 6,
dbietStickers = 666,
}; };
static const int emojiTabCount = 8;
static const int emojiTabShift = 100000;
inline DBIEmojiTab emojiTabAtIndex(int index) {
return (index < 0 || index >= emojiTabCount) ? dbietRecent : DBIEmojiTab(index - 1);
}
enum DBIPlatform { enum DBIPlatform {
dbipWindows = 0, dbipWindows = 0,

View file

@ -61,18 +61,19 @@ compiler_rcc_make_all: GeneratedFiles/qrc_telegram.cpp
compiler_rcc_clean: compiler_rcc_clean:
-$(DEL_FILE) GeneratedFiles/qrc_telegram.cpp -$(DEL_FILE) GeneratedFiles/qrc_telegram.cpp
GeneratedFiles/qrc_telegram.cpp: SourceFiles/telegram.qrc \ GeneratedFiles/qrc_telegram.cpp: SourceFiles/telegram.qrc \
SourceFiles/art/emoji.png \ SourceFiles/art/emoji.webp \
SourceFiles/art/blank.gif \ SourceFiles/art/blank.gif \
SourceFiles/art/bg.jpg \ SourceFiles/art/bg.jpg \
SourceFiles/art/sprite_150x.png \ SourceFiles/art/sprite_150x.png \
SourceFiles/art/sprite.png \ SourceFiles/art/sprite.png \
SourceFiles/art/icon256.png \ SourceFiles/art/icon256.png \
SourceFiles/art/emoji_150x.png \ SourceFiles/art/emoji_150x.webp \
SourceFiles/art/sprite_200x.png \ SourceFiles/art/sprite_200x.png \
SourceFiles/art/newmsg.wav \ SourceFiles/art/newmsg.wav \
SourceFiles/art/sprite_125x.png \ SourceFiles/art/sprite_125x.png \
SourceFiles/art/emoji_200x.png \ SourceFiles/art/emoji_200x.webp \
SourceFiles/art/emoji_125x.png \ SourceFiles/art/emoji_250x.webp \
SourceFiles/art/emoji_125x.webp \
SourceFiles/art/fonts/OpenSans-Regular.ttf \ SourceFiles/art/fonts/OpenSans-Regular.ttf \
SourceFiles/art/fonts/OpenSans-Bold.ttf \ SourceFiles/art/fonts/OpenSans-Bold.ttf \
SourceFiles/art/fonts/OpenSans-Semibold.ttf \ SourceFiles/art/fonts/OpenSans-Semibold.ttf \