Added emoji picker to touchbar.

- Added independent size of emoji for touchbar.
 - Added rpl::event_stream for recent emoji updates.
This commit is contained in:
23rd 2019-06-16 19:56:48 +03:00 committed by John Preston
parent dcba07b9b7
commit 662d0d0764
3 changed files with 235 additions and 73 deletions

View File

@ -9,30 +9,32 @@
#import "mac_touchbar.h" #import "mac_touchbar.h"
#import <QuartzCore/QuartzCore.h> #import <QuartzCore/QuartzCore.h>
#include "platform/mac/mac_utilities.h" #include "apiwrap.h"
#include "auth_session.h" #include "auth_session.h"
#include "chat_helpers/emoji_list_widget.h"
#include "core/application.h" #include "core/application.h"
#include "core/sandbox.h" #include "core/sandbox.h"
#include "data/data_document.h"
#include "data/data_file_origin.h"
#include "data/data_folder.h" #include "data/data_folder.h"
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "dialogs/dialogs_layout.h" #include "dialogs/dialogs_layout.h"
#include "emoji_config.h"
#include "history/history.h" #include "history/history.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "platform/mac/mac_utilities.h"
#include "stickers.h"
#include "styles/style_dialogs.h"
#include "styles/style_media_player.h" #include "styles/style_media_player.h"
#include "styles/style_settings.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "ui/empty_userpic.h" #include "ui/empty_userpic.h"
#include "styles/style_dialogs.h" #include "ui/widgets/input_fields.h"
#include "styles/style_settings.h"
#include "stickers.h"
#include "data/data_document.h"
#include "data/data_file_origin.h"
#include "chat_helpers/stickers_list_widget.h"
#include "apiwrap.h"
NSImage *qt_mac_create_nsimage(const QPixmap &pm); NSImage *qt_mac_create_nsimage(const QPixmap &pm);
@ -55,6 +57,9 @@ constexpr auto kCommandLink = 0x014;
constexpr auto kCommandPopoverInput = 0x020; constexpr auto kCommandPopoverInput = 0x020;
constexpr auto kCommandPopoverStickers = 0x021; constexpr auto kCommandPopoverStickers = 0x021;
constexpr auto kCommandScrubberStickers = 0x022;
constexpr auto kCommandPopoverEmoji = 0x023;
constexpr auto kCommandScrubberEmoji = 0x024;
constexpr auto kMs = 1000; constexpr auto kMs = 1000;
@ -96,15 +101,26 @@ const NSTouchBarItemIdentifier kLinkItemIdentifier = [NSString stringWithFormat:
const NSTouchBarItemIdentifier kPopoverStickersItemIdentifier = [NSString stringWithFormat:@"%@.popoverStickers", kCustomizationIdMain]; const NSTouchBarItemIdentifier kPopoverStickersItemIdentifier = [NSString stringWithFormat:@"%@.popoverStickers", kCustomizationIdMain];
const NSTouchBarItemIdentifier kScrubberStickersItemIdentifier = [NSString stringWithFormat:@"%@.scrubberStickers", kCustomizationIdMain]; const NSTouchBarItemIdentifier kScrubberStickersItemIdentifier = [NSString stringWithFormat:@"%@.scrubberStickers", kCustomizationIdMain];
const NSTouchBarItemIdentifier kStickerItemIdentifier = [NSString stringWithFormat:@"%@.stickerItem", kCustomizationIdMain]; const NSTouchBarItemIdentifier kStickerItemIdentifier = [NSString stringWithFormat:@"%@.stickerItem", kCustomizationIdMain];
const NSTouchBarItemIdentifier kStickerTitleItemIdentifier = [NSString stringWithFormat:@"%@.stickerTitleItem", kCustomizationIdMain]; const NSTouchBarItemIdentifier kPopoverEmojiItemIdentifier = [NSString stringWithFormat:@"%@.popoverEmoji", kCustomizationIdMain];
const NSTouchBarItemIdentifier kScrubberEmojiItemIdentifier = [NSString stringWithFormat:@"%@.scrubberEmoji", kCustomizationIdMain];
const NSTouchBarItemIdentifier kEmojiItemIdentifier = [NSString stringWithFormat:@"%@.emojiItem", kCustomizationIdMain];
const NSTouchBarItemIdentifier kPickerTitleItemIdentifier = [NSString stringWithFormat:@"%@.pickerTitleItem", kCustomizationIdMain];
struct StickerScrubberItem { struct PickerScrubberItem {
StickerScrubberItem(QString title) : title(title) { PickerScrubberItem(QString title) : title(title) {
} }
StickerScrubberItem(DocumentData* document) : document(document) { PickerScrubberItem(DocumentData* document) : document(document) {
}
PickerScrubberItem(EmojiPtr emoji) : emoji(emoji) {
} }
QString title = QString(); QString title = QString();
DocumentData* document = nullptr; DocumentData* document = nullptr;
EmojiPtr emoji = nullptr;
};
enum ScrubberItemType {
Emoji,
Sticker,
}; };
using Platform::Q2NSString; using Platform::Q2NSString;
@ -118,6 +134,22 @@ NSImage *CreateNSImageFromStyleIcon(const style::icon &icon, int size = kIdealIc
return image; return image;
} }
NSImage *CreateNSImageFromEmoji(EmojiPtr emoji) {
const auto s = kIdealIconSize * cIntRetinaFactor();
auto pixmap = QPixmap(s, s);
pixmap.setDevicePixelRatio(cRetinaFactor());
pixmap.fill(Qt::black);
Painter paint(&pixmap);
PainterHighQualityEnabler hq(paint);
Ui::Emoji::Draw(
paint,
std::move(emoji),
Ui::Emoji::GetSizeTouchbar(),
0,
0);
return [qt_mac_create_nsimage(pixmap) autorelease];
}
int WidthFromString(NSString *s) { int WidthFromString(NSString *s) {
return (int)ceil( return (int)ceil(
[[NSTextField labelWithString:s] frame].size.width) * 1.2; [[NSTextField labelWithString:s] frame].size.width) * 1.2;
@ -131,6 +163,10 @@ NSString *NSStringFromQString(QString s) {
return [NSString stringWithUTF8String:s.toUtf8().constData()]; return [NSString stringWithUTF8String:s.toUtf8().constData()];
} }
inline bool IsSticker(ScrubberItemType type) {
return type == ScrubberItemType::Sticker;
}
inline bool CurrentSongExists() { inline bool CurrentSongExists() {
return Media::Player::instance()->current(kSongType).audio() != nullptr; return Media::Player::instance()->current(kSongType).audio() != nullptr;
} }
@ -243,7 +279,7 @@ void SendKeyEvent(int command) {
QApplication::postEvent(focused, new QKeyEvent(QEvent::KeyRelease, key, modifier)); QApplication::postEvent(focused, new QKeyEvent(QEvent::KeyRelease, key, modifier));
} }
void AppendStickerSet(std::vector<StickerScrubberItem> &to, uint64 setId) { void AppendStickerSet(std::vector<PickerScrubberItem> &to, uint64 setId) {
auto &sets = Auth().data().stickerSets(); auto &sets = Auth().data().stickerSets();
auto it = sets.constFind(setId); auto it = sets.constFind(setId);
if (it == sets.cend() || it->stickers.isEmpty()) { if (it == sets.cend() || it->stickers.isEmpty()) {
@ -256,15 +292,15 @@ void AppendStickerSet(std::vector<StickerScrubberItem> &to, uint64 setId) {
return; return;
} }
to.emplace_back(StickerScrubberItem(it->title.isEmpty() to.emplace_back(PickerScrubberItem(it->title.isEmpty()
? it->shortName ? it->shortName
: it->title)); : it->title));
for (auto sticker : it->stickers) { for (const auto sticker : it->stickers) {
to.emplace_back(StickerScrubberItem(sticker)); to.emplace_back(PickerScrubberItem(sticker));
} }
} }
void AppendRecentStickers(std::vector<StickerScrubberItem> &to) { void AppendRecentStickers(std::vector<PickerScrubberItem> &to) {
const auto &sets = Auth().data().stickerSets(); const auto &sets = Auth().data().stickerSets();
const auto cloudIt = sets.constFind(Stickers::CloudRecentSetId); const auto cloudIt = sets.constFind(Stickers::CloudRecentSetId);
const auto favedIt = sets.constFind(Stickers::FavedSetId); const auto favedIt = sets.constFind(Stickers::FavedSetId);
@ -272,21 +308,21 @@ void AppendRecentStickers(std::vector<StickerScrubberItem> &to) {
? cloudIt->stickers.size() ? cloudIt->stickers.size()
: 0; : 0;
if (cloudCount > 0) { if (cloudCount > 0) {
to.emplace_back(StickerScrubberItem(cloudIt->title)); to.emplace_back(PickerScrubberItem(cloudIt->title));
auto count = 0; auto count = 0;
for (const auto document : cloudIt->stickers) { for (const auto document : cloudIt->stickers) {
if (Stickers::IsFaved(document)) { if (Stickers::IsFaved(document)) {
continue; continue;
} }
to.emplace_back(StickerScrubberItem(document)); to.emplace_back(PickerScrubberItem(document));
} }
} }
for (auto recent : Stickers::GetRecentPack()) { for (const auto recent : Stickers::GetRecentPack()) {
to.emplace_back(StickerScrubberItem(recent.first)); to.emplace_back(PickerScrubberItem(recent.first));
} }
} }
void AppendFavedStickers(std::vector<StickerScrubberItem> &to) { void AppendFavedStickers(std::vector<PickerScrubberItem> &to) {
const auto &sets = Auth().data().stickerSets(); const auto &sets = Auth().data().stickerSets();
const auto it = sets.constFind(Stickers::FavedSetId); const auto it = sets.constFind(Stickers::FavedSetId);
const auto count = (it != sets.cend()) const auto count = (it != sets.cend())
@ -295,9 +331,27 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
if (!count) { if (!count) {
return; return;
} }
to.emplace_back(StickerScrubberItem(it->title)); to.emplace_back(PickerScrubberItem(it->title));
for (const auto document : it->stickers) { for (const auto document : it->stickers) {
to.emplace_back(StickerScrubberItem(document)); to.emplace_back(PickerScrubberItem(document));
}
}
void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
// Get 'Recent' string.
const auto recent = Auth().data().stickerSets()
.constFind(Stickers::CloudRecentSetId)->title;
for (auto i = 0; i != ChatHelpers::kEmojiSectionCount; ++i) {
const auto section = Ui::Emoji::GetSection(
static_cast<Ui::Emoji::Section>(i));
const auto title = i
? lang(LangKey(lng_emoji_category1 + i))
: recent;
to.emplace_back(title);
for (const auto &emoji : section) {
to.emplace_back(PickerScrubberItem(emoji));
}
} }
} }
@ -488,10 +542,10 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
@interface StickerScrubberItemView : NSScrubberItemView @interface PickerScrubberItemView : NSScrubberItemView
@property (strong) NSImageView *imageView; @property (strong) NSImageView *imageView;
@end @end
@implementation StickerScrubberItemView { @implementation PickerScrubberItemView {
rpl::lifetime _lifetime; rpl::lifetime _lifetime;
Data::FileOrigin _origin; Data::FileOrigin _origin;
QSize _dimensions; QSize _dimensions;
@ -552,7 +606,7 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
@end @end
@interface StickersCustomTouchBarItem: NSCustomTouchBarItem @interface PickerCustomTouchBarItem: NSCustomTouchBarItem
<NSScrubberDelegate, <NSScrubberDelegate,
NSScrubberDataSource, NSScrubberDataSource,
NSScrubberFlowLayoutDelegate> NSScrubberFlowLayoutDelegate>
@ -560,19 +614,20 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
#pragma mark - #pragma mark -
@implementation StickersCustomTouchBarItem { @implementation PickerCustomTouchBarItem {
Fn<void()> _stickerSent; std::vector<PickerScrubberItem> _stickers;
std::vector<StickerScrubberItem> _stickers; NSPopoverTouchBarItem *_parentPopover;
} }
- (id) init:(Fn<void()>)stickerSent { - (id) init:(ScrubberItemType)type popover:(NSPopoverTouchBarItem *)popover {
self = [super initWithIdentifier:kScrubberStickersItemIdentifier]; self = [super initWithIdentifier:IsSticker(type)
? kScrubberStickersItemIdentifier
: kScrubberEmojiItemIdentifier];
if (!self) { if (!self) {
return self; return self;
} }
_stickerSent = std::move(stickerSent); _parentPopover = popover;
[self updateStickers]; IsSticker(type) ? [self updateStickers] : [self updateEmoji];
NSScrubber *scrubber = [[[NSScrubber alloc] initWithFrame:NSZeroRect] autorelease]; NSScrubber *scrubber = [[[NSScrubber alloc] initWithFrame:NSZeroRect] autorelease];
NSScrubberFlowLayout *layout = [[[NSScrubberFlowLayout alloc] init] autorelease]; NSScrubberFlowLayout *layout = [[[NSScrubberFlowLayout alloc] init] autorelease];
layout.itemSpacing = 10; layout.itemSpacing = 10;
@ -583,8 +638,9 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
scrubber.floatsSelectionViews = true; scrubber.floatsSelectionViews = true;
scrubber.showsAdditionalContentIndicators = true; scrubber.showsAdditionalContentIndicators = true;
scrubber.itemAlignment = NSScrubberAlignmentCenter; scrubber.itemAlignment = NSScrubberAlignmentCenter;
[scrubber registerClass:[StickerScrubberItemView class] forItemIdentifier:kStickerItemIdentifier]; [scrubber registerClass:[PickerScrubberItemView class] forItemIdentifier:kStickerItemIdentifier];
[scrubber registerClass:[NSScrubberTextItemView class] forItemIdentifier:kStickerTitleItemIdentifier]; [scrubber registerClass:[NSScrubberTextItemView class] forItemIdentifier:kPickerTitleItemIdentifier];
[scrubber registerClass:[NSScrubberImageItemView class] forItemIdentifier:kEmojiItemIdentifier];
self.view = scrubber; self.view = scrubber;
return self; return self;
@ -601,14 +657,18 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
} }
- (NSScrubberItemView *)scrubber:(NSScrubber *)scrubber viewForItemAtIndex:(NSInteger)index { - (NSScrubberItemView *)scrubber:(NSScrubber *)scrubber viewForItemAtIndex:(NSInteger)index {
const auto document = _stickers[index].document; const auto item = _stickers[index];
if (document) { if (const auto document = item.document) {
StickerScrubberItemView *itemView = [scrubber makeItemWithIdentifier:kStickerItemIdentifier owner:nil]; PickerScrubberItemView *itemView = [scrubber makeItemWithIdentifier:kStickerItemIdentifier owner:nil];
[itemView addDocument:document]; [itemView addDocument:document];
return itemView; return itemView;
} else if (const auto emoji = item.emoji) {
NSScrubberImageItemView *itemView = [scrubber makeItemWithIdentifier:kEmojiItemIdentifier owner:nil];
itemView.imageView.image = CreateNSImageFromEmoji(emoji);
return itemView;
} else { } else {
NSScrubberTextItemView *itemView = [scrubber makeItemWithIdentifier:kStickerTitleItemIdentifier owner:nil]; NSScrubberTextItemView *itemView = [scrubber makeItemWithIdentifier:kPickerTitleItemIdentifier owner:nil];
itemView.textField.stringValue = NSStringFromQString(_stickers[index].title); itemView.textField.stringValue = NSStringFromQString(item.title);
return itemView; return itemView;
} }
} }
@ -616,34 +676,51 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
- (NSSize)scrubber:(NSScrubber *)scrubber layout:(NSScrubberFlowLayout *)layout sizeForItemAtIndex:(NSInteger)index { - (NSSize)scrubber:(NSScrubber *)scrubber layout:(NSScrubberFlowLayout *)layout sizeForItemAtIndex:(NSInteger)index {
if (const auto t = _stickers[index].title; !t.isEmpty()) { if (const auto t = _stickers[index].title; !t.isEmpty()) {
return NSMakeSize( return NSMakeSize(
WidthFromString(NSStringFromQString(t)) + 20, kScrubberHeight); WidthFromString(NSStringFromQString(t)) + 30, kScrubberHeight);
} }
return NSMakeSize(kScrubberHeight, kScrubberHeight); return NSMakeSize(kScrubberHeight, kScrubberHeight);
} }
- (void)scrubber:(NSScrubber *)scrubber didSelectItemAtIndex:(NSInteger)index { - (void)scrubber:(NSScrubber *)scrubber didSelectItemAtIndex:(NSInteger)index {
if (const auto document = _stickers[index].document) { const auto controller = App::wnd()->sessionController();
const auto controller = App::wnd()->sessionController(); if (const auto history = controller->activeChatCurrent().history()) {
if (const auto history = controller->activeChatCurrent().history()) { Fn<void()> callback;
Core::Sandbox::Instance().customEnterFromEventLoop([=] { if (const auto document = _stickers[index].document) {
callback = [=] {
Auth().api().sendExistingDocument( Auth().api().sendExistingDocument(
document, document,
document->stickerSetOrigin(), document->stickerSetOrigin(),
{}, {},
ApiWrap::SendOptions(history)); ApiWrap::SendOptions(history));
}); };
_stickerSent();
} }
if (const auto emoji = _stickers[index].emoji) {
callback = [=] {
if (const auto inputField = qobject_cast<Ui::InputField*>(
QApplication::focusWidget()->parentWidget())) {
Ui::InsertEmojiAtCursor(inputField->textCursor(), emoji);
Ui::Emoji::AddRecent(emoji);
}
};
}
if (!callback) {
return;
}
Core::Sandbox::Instance().customEnterFromEventLoop(
std::move(callback));
if (_parentPopover) {
[_parentPopover dismissPopover:nil];
}
scrubber.selectedIndex = -1;
} }
} }
- (void)updateStickers { - (void)updateStickers {
std::vector<StickerScrubberItem> temp; std::vector<PickerScrubberItem> temp;
temp.reserve(Auth().data().stickerSetsOrder().size() + 3);
AppendFavedStickers(temp); AppendFavedStickers(temp);
AppendRecentStickers(temp); AppendRecentStickers(temp);
auto count = 0; auto count = 0;
for (auto setId : Auth().data().stickerSetsOrder()) { for (const auto setId : Auth().data().stickerSetsOrder()) {
AppendStickerSet(temp, setId); AppendStickerSet(temp, setId);
if (++count == kMaxStickerSets) { if (++count == kMaxStickerSets) {
break; break;
@ -652,6 +729,12 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
_stickers = std::move(temp); _stickers = std::move(temp);
} }
- (void)updateEmoji {
std::vector<PickerScrubberItem> temp;
AppendEmojiPacks(temp);
_stickers = std::move(temp);
}
@end @end
@ -762,8 +845,18 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
kScrubberStickersItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ kScrubberStickersItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
@"type": kTypeScrubber, @"type": kTypeScrubber,
@"name": @"Stickers", @"name": @"Stickers",
@"cmd": [NSNumber numberWithInt:kCommandPopoverStickers], @"cmd": [NSNumber numberWithInt:kCommandScrubberStickers],
@"image": CreateNSImageFromStyleIcon(st::settingsIconStickers, iconSize), }],
kPopoverEmojiItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
@"type": kTypePopover,
@"name": @"Emoji",
@"cmd": [NSNumber numberWithInt:kCommandPopoverEmoji],
@"image": CreateNSImageFromStyleIcon(st::settingsIconEmoji, iconSize * 2),
}],
kScrubberEmojiItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
@"type": kTypeScrubber,
@"name": @"Emoji",
@"cmd": [NSNumber numberWithInt:kCommandScrubberEmoji],
}] }]
}; };
@ -824,21 +917,28 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
&& key.history() && key.history()
&& key.peer()->canWrite(); && key.peer()->canWrite();
[self showItem:kPopoverStickersItemIdentifier show:show]; [self showItem:kPopoverStickersItemIdentifier show:show];
[self showItem:kPopoverEmojiItemIdentifier show:show];
}, _lifetime); }, _lifetime);
} }
} }
}, _lifetimeSessionControllerChecker); }, _lifetimeSessionControllerChecker);
Auth().data().stickersUpdated( rpl::merge(
Auth().data().stickersUpdated(),
Auth().data().recentStickersUpdated()
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
[self updateStickerTouchBar: [self updatePickerPopover:
[_touchBarMain itemForIdentifier:kPopoverStickersItemIdentifier]]; [_touchBarMain itemForIdentifier:kPopoverStickersItemIdentifier]
type:ScrubberItemType::Sticker];
}, _lifetime); }, _lifetime);
Auth().data().recentStickersUpdated( rpl::merge(
Ui::Emoji::UpdatedRecent(),
Ui::Emoji::Updated()
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
[self updateStickerTouchBar: [self updatePickerPopover:
[_touchBarMain itemForIdentifier:kPopoverStickersItemIdentifier]]; [_touchBarMain itemForIdentifier:kPopoverEmojiItemIdentifier]
type:ScrubberItemType::Emoji];
}, _lifetime); }, _lifetime);
[self updatePinnedButtons]; [self updatePinnedButtons];
@ -898,16 +998,22 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
item.pressAndHoldTouchBar = secondaryTouchBar; item.pressAndHoldTouchBar = secondaryTouchBar;
item.popoverTouchBar = secondaryTouchBar; item.popoverTouchBar = secondaryTouchBar;
} else if (command == kCommandPopoverStickers) { } else if (command == kCommandPopoverStickers) {
[self updateStickerTouchBar:item]; [self updatePickerPopover:item type:ScrubberItemType::Sticker];
} else if (command == kCommandPopoverEmoji) {
[self updatePickerPopover:item type:ScrubberItemType::Emoji];
} }
return item; return item;
} else if (isType(kTypeScrubber)) { } else if (isType(kTypeScrubber)) {
StickersCustomTouchBarItem *item = [[StickersCustomTouchBarItem alloc] const auto isSticker = ([dictionaryItem[@"cmd"] intValue]
init:[=] { == kCommandScrubberStickers);
NSPopoverTouchBarItem *item = [_touchBarMain itemForIdentifier:kPopoverStickersItemIdentifier]; const auto type = isSticker
[item dismissPopover:nil]; ? ScrubberItemType::Sticker
[self updateStickerTouchBar:item]; : ScrubberItemType::Emoji;
}]; const auto popover = isSticker
? [_touchBarMain itemForIdentifier:kPopoverStickersItemIdentifier]
: nil;
PickerCustomTouchBarItem *item = [[PickerCustomTouchBarItem alloc]
init:type popover:popover];
return item; return item;
} else if (isType(kTypePinned)) { } else if (isType(kTypePinned)) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
@ -995,14 +1101,19 @@ void AppendFavedStickers(std::vector<StickerScrubberItem> &to) {
_touchBarMain.defaultItemIdentifiers = items; _touchBarMain.defaultItemIdentifiers = items;
} }
- (void) updateStickerTouchBar:(NSPopoverTouchBarItem *)item { - (void) updatePickerPopover:(NSPopoverTouchBarItem *)item
type:(ScrubberItemType)type {
NSTouchBar *secondaryTouchBar = [[NSTouchBar alloc] init]; NSTouchBar *secondaryTouchBar = [[NSTouchBar alloc] init];
secondaryTouchBar.delegate = self; secondaryTouchBar.delegate = self;
[[StickersCustomTouchBarItem alloc] init:[=] { const auto popover = IsSticker(type)
[item dismissPopover:nil]; ? item
[self updateStickerTouchBar:item]; : nil;
}]; [[PickerCustomTouchBarItem alloc] init:type popover:popover];
secondaryTouchBar.defaultItemIdentifiers = @[kScrubberStickersItemIdentifier]; const auto identifier = IsSticker(type)
? kScrubberStickersItemIdentifier
: kScrubberEmojiItemIdentifier;
secondaryTouchBar.defaultItemIdentifiers = @[identifier];
item.popoverTouchBar = secondaryTouchBar; item.popoverTouchBar = secondaryTouchBar;
} }

View File

@ -29,6 +29,8 @@ constexpr auto kSetVersion = uint32(1);
constexpr auto kCacheVersion = uint32(3); constexpr auto kCacheVersion = uint32(3);
constexpr auto kMaxId = uint32(1 << 8); constexpr auto kMaxId = uint32(1 << 8);
constexpr auto kScaleForTouchBar = 150;
const auto kSets = { const auto kSets = {
Set{ 0, 0, 0, "Mac", ":/gui/emoji/set0_preview.webp" }, Set{ 0, 0, 0, "Mac", ":/gui/emoji/set0_preview.webp" },
Set{ 1, 246, 7'336'383, "Android", ":/gui/emoji/set1_preview.webp" }, Set{ 1, 246, 7'336'383, "Android", ":/gui/emoji/set1_preview.webp" },
@ -87,6 +89,13 @@ auto InstanceNormal = std::unique_ptr<Instance>();
auto InstanceLarge = std::unique_ptr<Instance>(); auto InstanceLarge = std::unique_ptr<Instance>();
auto Universal = std::shared_ptr<UniversalImages>(); auto Universal = std::shared_ptr<UniversalImages>();
auto Updates = rpl::event_stream<>(); auto Updates = rpl::event_stream<>();
auto UpdatesRecent = rpl::event_stream<>();
#if defined Q_OS_MAC && !defined OS_MAC_OLD
auto TouchbarSize = -1;
auto TouchbarInstance = std::unique_ptr<Instance>();
auto TouchbarEmoji = (Instance*)nullptr;
#endif
auto MainEmojiMap = std::map<int, QPixmap>(); auto MainEmojiMap = std::map<int, QPixmap>();
auto OtherEmojiMap = std::map<int, std::map<int, QPixmap>>(); auto OtherEmojiMap = std::map<int, std::map<int, QPixmap>>();
@ -521,6 +530,17 @@ void Init() {
InstanceNormal = std::make_unique<Instance>(SizeNormal); InstanceNormal = std::make_unique<Instance>(SizeNormal);
InstanceLarge = std::make_unique<Instance>(SizeLarge); InstanceLarge = std::make_unique<Instance>(SizeLarge);
#if defined Q_OS_MAC && !defined OS_MAC_OLD
if (cScale() != kScaleForTouchBar) {
TouchbarSize = int(ConvertScale(18 * 4 / 3.,
kScaleForTouchBar * cIntRetinaFactor()));
TouchbarInstance = std::make_unique<Instance>(TouchbarSize);
TouchbarEmoji = TouchbarInstance.get();
} else {
TouchbarEmoji = InstanceLarge.get();
}
#endif
} }
void Clear() { void Clear() {
@ -529,6 +549,10 @@ void Clear() {
InstanceNormal = nullptr; InstanceNormal = nullptr;
InstanceLarge = nullptr; InstanceLarge = nullptr;
#if defined Q_OS_MAC && !defined OS_MAC_OLD
TouchbarInstance = nullptr;
TouchbarEmoji = nullptr;
#endif
} }
void ClearIrrelevantCache() { void ClearIrrelevantCache() {
@ -621,6 +645,14 @@ int GetSizeLarge() {
return SizeLarge; return SizeLarge;
} }
#if defined Q_OS_MAC && !defined OS_MAC_OLD
int GetSizeTouchbar() {
return (cScale() == kScaleForTouchBar)
? GetSizeLarge()
: TouchbarSize;
}
#endif
int One::variantsCount() const { int One::variantsCount() const {
return hasVariants() ? 5 : 0; return hasVariants() ? 5 : 0;
} }
@ -841,6 +873,11 @@ void AddRecent(EmojiPtr emoji) {
qSwap(*i, *(i - 1)); qSwap(*i, *(i - 1));
} }
} }
UpdatesRecent.fire({});
}
rpl::producer<> UpdatedRecent() {
return UpdatesRecent.events();
} }
const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight) { const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight) {
@ -857,6 +894,7 @@ const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight) {
image.fill(Qt::transparent); image.fill(Qt::transparent);
{ {
QPainter p(&image); QPainter p(&image);
PainterHighQualityEnabler hq(p);
Draw( Draw(
p, p,
emoji, emoji,
@ -872,6 +910,15 @@ const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight) {
} }
void Draw(QPainter &p, EmojiPtr emoji, int size, int x, int y) { void Draw(QPainter &p, EmojiPtr emoji, int size, int x, int y) {
#if defined Q_OS_MAC && !defined OS_MAC_OLD
const auto s = (cScale() == kScaleForTouchBar)
? SizeLarge
: TouchbarSize;
if (size == s) {
TouchbarEmoji->draw(p, emoji, x, y);
return;
}
#endif
if (size == SizeNormal) { if (size == SizeNormal) {
InstanceNormal->draw(p, emoji, x, y); InstanceNormal->draw(p, emoji, x, y);
} else if (size == SizeLarge) { } else if (size == SizeLarge) {

View File

@ -44,6 +44,9 @@ rpl::producer<> Updated();
int GetSizeNormal(); int GetSizeNormal();
int GetSizeLarge(); int GetSizeLarge();
#if defined Q_OS_MAC && !defined OS_MAC_OLD
int GetSizeTouchbar();
#endif
class One { class One {
struct CreationTag { struct CreationTag {
@ -156,6 +159,7 @@ inline int ColorIndexFromOldKey(uint64 oldKey) {
void ReplaceInText(TextWithEntities &result); void ReplaceInText(TextWithEntities &result);
RecentEmojiPack &GetRecent(); RecentEmojiPack &GetRecent();
void AddRecent(EmojiPtr emoji); void AddRecent(EmojiPtr emoji);
rpl::producer<> UpdatedRecent();
const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight); const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight);
void Draw(QPainter &p, EmojiPtr emoji, int size, int x, int y); void Draw(QPainter &p, EmojiPtr emoji, int size, int x, int y);