mirror of https://github.com/procxx/kepka.git
				
				
				
			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:
		
							parent
							
								
									dcba07b9b7
								
							
						
					
					
						commit
						662d0d0764
					
				|  | @ -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; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) { | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue