From dcba07b9b7652c35d520094b3ff5adaadf6a247f Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 12 Jun 2019 22:49:28 +0300 Subject: [PATCH] Added sticker picker to touchbar. --- Telegram/SourceFiles/apiwrap.cpp | 1 + Telegram/SourceFiles/data/data_session.cpp | 8 + Telegram/SourceFiles/data/data_session.h | 6 + .../SourceFiles/platform/mac/mac_touchbar.h | 2 +- .../SourceFiles/platform/mac/mac_touchbar.mm | 413 ++++++++++++++++-- .../platform/mac/main_window_mac.mm | 2 +- 6 files changed, 394 insertions(+), 38 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 5bb6dc850..10466fcc7 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -5229,6 +5229,7 @@ void ApiWrap::sendExistingDocument( main->finishForwarding(history); if (document->sticker()) { main->incrementSticker(document); + _session->data().notifyRecentStickersUpdated(); } } } diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 46da45468..902716381 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -1397,6 +1397,14 @@ rpl::producer<> Session::stickersUpdated() const { return _stickersUpdated.events(); } +void Session::notifyRecentStickersUpdated() { + _recentStickersUpdated.fire({}); +} + +rpl::producer<> Session::recentStickersUpdated() const { + return _recentStickersUpdated.events(); +} + void Session::notifySavedGifsUpdated() { _savedGifsUpdated.fire({}); } diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 6834bf262..7cc8a67c5 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -229,6 +229,8 @@ public: void notifyStickersUpdated(); [[nodiscard]] rpl::producer<> stickersUpdated() const; + void notifyRecentStickersUpdated(); + [[nodiscard]] rpl::producer<> recentStickersUpdated() const; void notifySavedGifsUpdated(); [[nodiscard]] rpl::producer<> savedGifsUpdated() const; void notifyPinnedDialogsOrderUpdated(); @@ -244,6 +246,9 @@ public: return stickersUpdateNeeded(_lastRecentStickersUpdate, now); } void setLastRecentStickersUpdate(crl::time update) { + if (update) { + notifyRecentStickersUpdated(); + } _lastRecentStickersUpdate = update; } bool favedStickersUpdateNeeded(crl::time now) const { @@ -839,6 +844,7 @@ private: rpl::event_stream _dialogsRowReplacements; rpl::event_stream<> _stickersUpdated; + rpl::event_stream<> _recentStickersUpdated; rpl::event_stream<> _savedGifsUpdated; rpl::event_stream<> _pinnedDialogsOrderUpdated; crl::time _lastStickersUpdate = 0; diff --git a/Telegram/SourceFiles/platform/mac/mac_touchbar.h b/Telegram/SourceFiles/platform/mac/mac_touchbar.h index f9e75832c..149c4a697 100644 --- a/Telegram/SourceFiles/platform/mac/mac_touchbar.h +++ b/Telegram/SourceFiles/platform/mac/mac_touchbar.h @@ -27,6 +27,6 @@ enum class TouchBarType { - (id _Nonnull) init:(NSView * _Nonnull)view; - (void) handleTrackStateChange:(Media::Player::TrackState)state; - (void) setTouchBar:(Platform::TouchBarType)type; -- (void) showInputFieldItems:(bool)show; +- (void) showInputFieldItem:(bool)show; @end diff --git a/Telegram/SourceFiles/platform/mac/mac_touchbar.mm b/Telegram/SourceFiles/platform/mac/mac_touchbar.mm index 97061bce7..84e11b6dd 100644 --- a/Telegram/SourceFiles/platform/mac/mac_touchbar.mm +++ b/Telegram/SourceFiles/platform/mac/mac_touchbar.mm @@ -27,6 +27,12 @@ #include "window/window_session_controller.h" #include "ui/empty_userpic.h" #include "styles/style_dialogs.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); @@ -34,6 +40,7 @@ namespace { //https://developer.apple.com/design/human-interface-guidelines/macos/touch-bar/touch-bar-icons-and-images/ constexpr auto kIdealIconSize = 36; constexpr auto kMaximumIconSize = 44; +constexpr auto kScrubberHeight = 30; constexpr auto kCommandPlayPause = 0x002; constexpr auto kCommandPlaylistPrevious = 0x003; @@ -47,6 +54,7 @@ constexpr auto kCommandClear = 0x013; constexpr auto kCommandLink = 0x014; constexpr auto kCommandPopoverInput = 0x020; +constexpr auto kCommandPopoverStickers = 0x021; constexpr auto kMs = 1000; @@ -55,6 +63,16 @@ constexpr auto kSongType = AudioMsgId::Type::Song; constexpr auto kSavedMessagesId = 0; constexpr auto kArchiveId = -1; +constexpr auto kMaxStickerSets = 5; + +NSString *const kTypePinned = @"pinned"; +NSString *const kTypeSlider = @"slider"; +NSString *const kTypeButton = @"button"; +NSString *const kTypeText = @"text"; +NSString *const kTypeTextButton = @"textButton"; +NSString *const kTypePopover = @"popover"; +NSString *const kTypeScrubber = @"scrubber"; + const NSString *kCustomizationIdPlayer = @"telegram.touchbar"; const NSString *kCustomizationIdMain = @"telegram.touchbarMain"; const NSTouchBarItemIdentifier kSavedMessagesItemIdentifier = [NSString stringWithFormat:@"%@.savedMessages", kCustomizationIdMain]; @@ -75,6 +93,20 @@ const NSTouchBarItemIdentifier kMonospaceItemIdentifier = [NSString stringWithFo const NSTouchBarItemIdentifier kClearItemIdentifier = [NSString stringWithFormat:@"%@.clear", kCustomizationIdMain]; const NSTouchBarItemIdentifier kLinkItemIdentifier = [NSString stringWithFormat:@"%@.link", kCustomizationIdMain]; +const NSTouchBarItemIdentifier kPopoverStickersItemIdentifier = [NSString stringWithFormat:@"%@.popoverStickers", kCustomizationIdMain]; +const NSTouchBarItemIdentifier kScrubberStickersItemIdentifier = [NSString stringWithFormat:@"%@.scrubberStickers", kCustomizationIdMain]; +const NSTouchBarItemIdentifier kStickerItemIdentifier = [NSString stringWithFormat:@"%@.stickerItem", kCustomizationIdMain]; +const NSTouchBarItemIdentifier kStickerTitleItemIdentifier = [NSString stringWithFormat:@"%@.stickerTitleItem", kCustomizationIdMain]; + +struct StickerScrubberItem { + StickerScrubberItem(QString title) : title(title) { + } + StickerScrubberItem(DocumentData* document) : document(document) { + } + QString title = QString(); + DocumentData* document = nullptr; +}; + using Platform::Q2NSString; NSImage *CreateNSImageFromStyleIcon(const style::icon &icon, int size = kIdealIconSize) { @@ -86,6 +118,19 @@ NSImage *CreateNSImageFromStyleIcon(const style::icon &icon, int size = kIdealIc return image; } +int WidthFromString(NSString *s) { + return (int)ceil( + [[NSTextField labelWithString:s] frame].size.width) * 1.2; +} + +NSString *NSStringFromLang(LangKey key) { + return [NSString stringWithUTF8String:lang(key).toUtf8().constData()]; +} + +NSString *NSStringFromQString(QString s) { + return [NSString stringWithUTF8String:s.toUtf8().constData()]; +} + inline bool CurrentSongExists() { return Media::Player::instance()->current(kSongType).audio() != nullptr; } @@ -198,6 +243,64 @@ void SendKeyEvent(int command) { QApplication::postEvent(focused, new QKeyEvent(QEvent::KeyRelease, key, modifier)); } +void AppendStickerSet(std::vector &to, uint64 setId) { + auto &sets = Auth().data().stickerSets(); + auto it = sets.constFind(setId); + if (it == sets.cend() || it->stickers.isEmpty()) { + return; + } + if (it->flags & MTPDstickerSet::Flag::f_archived) { + return; + } + if (!(it->flags & MTPDstickerSet::Flag::f_installed_date)) { + return; + } + + to.emplace_back(StickerScrubberItem(it->title.isEmpty() + ? it->shortName + : it->title)); + for (auto sticker : it->stickers) { + to.emplace_back(StickerScrubberItem(sticker)); + } +} + +void AppendRecentStickers(std::vector &to) { + const auto &sets = Auth().data().stickerSets(); + const auto cloudIt = sets.constFind(Stickers::CloudRecentSetId); + const auto favedIt = sets.constFind(Stickers::FavedSetId); + const auto cloudCount = (cloudIt != sets.cend()) + ? cloudIt->stickers.size() + : 0; + if (cloudCount > 0) { + to.emplace_back(StickerScrubberItem(cloudIt->title)); + auto count = 0; + for (const auto document : cloudIt->stickers) { + if (Stickers::IsFaved(document)) { + continue; + } + to.emplace_back(StickerScrubberItem(document)); + } + } + for (auto recent : Stickers::GetRecentPack()) { + to.emplace_back(StickerScrubberItem(recent.first)); + } +} + +void AppendFavedStickers(std::vector &to) { + const auto &sets = Auth().data().stickerSets(); + const auto it = sets.constFind(Stickers::FavedSetId); + const auto count = (it != sets.cend()) + ? it->stickers.size() + : 0; + if (!count) { + return; + } + to.emplace_back(StickerScrubberItem(it->title)); + for (const auto document : it->stickers) { + to.emplace_back(StickerScrubberItem(document)); + } +} + } // namespace @interface PinnedDialogButton : NSCustomTouchBarItem @@ -384,6 +487,174 @@ void SendKeyEvent(int command) { @end + +@interface StickerScrubberItemView : NSScrubberItemView +@property (strong) NSImageView *imageView; +@end +@implementation StickerScrubberItemView { + rpl::lifetime _lifetime; + Data::FileOrigin _origin; + QSize _dimensions; + Image *_image; +} + +- (instancetype)initWithFrame:(NSRect)frameRect { + self = [super initWithFrame:frameRect]; + if (!self) { + return self; + } + _imageView = [NSImageView imageViewWithImage: + [[NSImage alloc] initWithSize:frameRect.size]]; + [self.imageView setAutoresizingMask: + (NSAutoresizingMaskOptions)(NSViewWidthSizable | NSViewHeightSizable)]; + [self addSubview:self.imageView]; + return self; +} + +- (void)addDocument:(DocumentData *)document { + if (!document->sticker()) { + return; + } + _image = document->getStickerSmall(); + if (!_image) { + return; + } + _dimensions = document->dimensions; + _origin = document->stickerSetOrigin(); + _image->load(_origin); + if (_image->loaded()) { + [self updateImage]; + return; + } + + base::ObservableViewer( + Auth().downloaderTaskFinished() + ) | rpl::start_with_next([=] { + if (_image->loaded()) { + [self updateImage]; + _lifetime.destroy(); + } + }, _lifetime); +} +- (void)updateImage { + const auto size = _dimensions + .scaled(kScrubberHeight, kScrubberHeight, Qt::KeepAspectRatio); + _imageView.image = [qt_mac_create_nsimage( + _image->pixSingle( + _origin, + size.width(), + size.height(), + kScrubberHeight, + kScrubberHeight, + ImageRoundRadius::None)) + autorelease]; +} +@end + + +@interface StickersCustomTouchBarItem: NSCustomTouchBarItem + +@end + +#pragma mark - + +@implementation StickersCustomTouchBarItem { + Fn _stickerSent; + std::vector _stickers; +} + +- (id) init:(Fn)stickerSent { + self = [super initWithIdentifier:kScrubberStickersItemIdentifier]; + if (!self) { + return self; + } + _stickerSent = std::move(stickerSent); + [self updateStickers]; + + NSScrubber *scrubber = [[[NSScrubber alloc] initWithFrame:NSZeroRect] autorelease]; + NSScrubberFlowLayout *layout = [[[NSScrubberFlowLayout alloc] init] autorelease]; + layout.itemSpacing = 10; + scrubber.scrubberLayout = layout; + scrubber.mode = NSScrubberModeFree; + scrubber.delegate = self; + scrubber.dataSource = self; + scrubber.floatsSelectionViews = true; + scrubber.showsAdditionalContentIndicators = true; + scrubber.itemAlignment = NSScrubberAlignmentCenter; + [scrubber registerClass:[StickerScrubberItemView class] forItemIdentifier:kStickerItemIdentifier]; + [scrubber registerClass:[NSScrubberTextItemView class] forItemIdentifier:kStickerTitleItemIdentifier]; + + self.view = scrubber; + return self; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + // Has not been implemented. +} + +#pragma mark - NSScrubberDelegate + +- (NSInteger)numberOfItemsForScrubber:(NSScrubber *)scrubber { + return _stickers.size(); +} + +- (NSScrubberItemView *)scrubber:(NSScrubber *)scrubber viewForItemAtIndex:(NSInteger)index { + const auto document = _stickers[index].document; + if (document) { + StickerScrubberItemView *itemView = [scrubber makeItemWithIdentifier:kStickerItemIdentifier owner:nil]; + [itemView addDocument:document]; + return itemView; + } else { + NSScrubberTextItemView *itemView = [scrubber makeItemWithIdentifier:kStickerTitleItemIdentifier owner:nil]; + itemView.textField.stringValue = NSStringFromQString(_stickers[index].title); + return itemView; + } +} + +- (NSSize)scrubber:(NSScrubber *)scrubber layout:(NSScrubberFlowLayout *)layout sizeForItemAtIndex:(NSInteger)index { + if (const auto t = _stickers[index].title; !t.isEmpty()) { + return NSMakeSize( + WidthFromString(NSStringFromQString(t)) + 20, kScrubberHeight); + } + return NSMakeSize(kScrubberHeight, kScrubberHeight); +} + +- (void)scrubber:(NSScrubber *)scrubber didSelectItemAtIndex:(NSInteger)index { + if (const auto document = _stickers[index].document) { + const auto controller = App::wnd()->sessionController(); + if (const auto history = controller->activeChatCurrent().history()) { + Core::Sandbox::Instance().customEnterFromEventLoop([=] { + Auth().api().sendExistingDocument( + document, + document->stickerSetOrigin(), + {}, + ApiWrap::SendOptions(history)); + }); + _stickerSent(); + } + } +} + +- (void)updateStickers { + std::vector temp; + temp.reserve(Auth().data().stickerSetsOrder().size() + 3); + AppendFavedStickers(temp); + AppendRecentStickers(temp); + auto count = 0; + for (auto setId : Auth().data().stickerSetsOrder()) { + AppendStickerSet(temp, setId); + if (++count == kMaxStickerSets) { + break; + } + } + _stickers = std::move(temp); +} + +@end + + @interface TouchBar() @end // @interface TouchBar @@ -401,6 +672,7 @@ void SendKeyEvent(int command) { double _position; rpl::lifetime _lifetime; + rpl::lifetime _lifetimeSessionControllerChecker; } - (id) init:(NSView *)view { @@ -415,39 +687,39 @@ void SendKeyEvent(int command) { _parentView = view; self.touchBarItems = @{ kPinnedPanelItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ - @"type": @"pinned", + @"type": kTypePinned, }], kSeekBarItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ - @"type": @"slider", + @"type": kTypeSlider, @"name": @"Seek Bar" }], kPlayItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ - @"type": @"button", + @"type": kTypeButton, @"name": @"Play Button", @"cmd": [NSNumber numberWithInt:kCommandPlayPause], @"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerPause, iconSize), @"imageAlt": CreateNSImageFromStyleIcon(st::touchBarIconPlayerPlay, iconSize), }], kPreviousItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ - @"type": @"button", + @"type": kTypeButton, @"name": @"Previous Playlist Item", @"cmd": [NSNumber numberWithInt:kCommandPlaylistPrevious], @"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerPrevious, iconSize), }], kNextItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ - @"type": @"button", + @"type": kTypeButton, @"name": @"Next Playlist Item", @"cmd": [NSNumber numberWithInt:kCommandPlaylistNext], @"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerNext, iconSize), }], kCommandClosePlayerItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ - @"type": @"button", + @"type": kTypeButton, @"name": @"Close Player", @"cmd": [NSNumber numberWithInt:kCommandClosePlayer], @"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerClose, iconSize), }], kCurrentPositionItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ - @"type": @"text", + @"type": kTypeText, @"name": @"Current Position" }], kBoldItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ @@ -476,10 +748,22 @@ void SendKeyEvent(int command) { @"cmd": [NSNumber numberWithInt:kCommandLink], }], kPopoverInputItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ - @"type": @"popover", + @"type": kTypePopover, @"name": @"Input Field", @"cmd": [NSNumber numberWithInt:kCommandPopoverInput], @"image": [NSImage imageNamed:NSImageNameTouchBarTextItalicTemplate], + }], + kPopoverStickersItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ + @"type": kTypePopover, + @"name": @"Stickers", + @"cmd": [NSNumber numberWithInt:kCommandPopoverStickers], + @"image": CreateNSImageFromStyleIcon(st::settingsIconStickers, iconSize * 2), + }], + kScrubberStickersItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{ + @"type": kTypeScrubber, + @"name": @"Stickers", + @"cmd": [NSNumber numberWithInt:kCommandPopoverStickers], + @"image": CreateNSImageFromStyleIcon(st::settingsIconStickers, iconSize), }] }; @@ -524,6 +808,39 @@ void SendKeyEvent(int command) { [self toggleArchiveButton:folder->chatsList()->empty()]; }, _lifetime); + + // At the time of this touchbar creation the sessionController does + // not yet exist. But at the time of chatsListChanges event + // the sessionController is valid and we can work with it. + // So _lifetimeSessionControllerChecker is needed only once. + Auth().data().chatsListChanges( + ) | rpl::start_with_next([=] { + if (const auto window = App::wnd()) { + if (const auto controller = window->sessionController()) { + _lifetimeSessionControllerChecker.destroy(); + controller->activeChatChanges( + ) | rpl::start_with_next([=](Dialogs::Key key) { + const auto show = key.peer() + && key.history() + && key.peer()->canWrite(); + [self showItem:kPopoverStickersItemIdentifier show:show]; + }, _lifetime); + } + } + }, _lifetimeSessionControllerChecker); + + Auth().data().stickersUpdated( + ) | rpl::start_with_next([=] { + [self updateStickerTouchBar: + [_touchBarMain itemForIdentifier:kPopoverStickersItemIdentifier]]; + }, _lifetime); + + Auth().data().recentStickersUpdated( + ) | rpl::start_with_next([=] { + [self updateStickerTouchBar: + [_touchBarMain itemForIdentifier:kPopoverStickersItemIdentifier]]; + }, _lifetime); + [self updatePinnedButtons]; return self; @@ -533,7 +850,10 @@ void SendKeyEvent(int command) { makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { const id dictionaryItem = self.touchBarItems[identifier]; const id type = dictionaryItem[@"type"]; - if ([type isEqualToString:@"slider"]) { + const auto isType = [type](NSString *string) { + return [type isEqualToString:string]; + }; + if (isType(kTypeSlider)) { NSSliderTouchBarItem *item = [[NSSliderTouchBarItem alloc] initWithIdentifier:identifier]; item.slider.minValue = 0.0f; item.slider.maxValue = 1.0f; @@ -542,24 +862,19 @@ void SendKeyEvent(int command) { item.customizationLabel = dictionaryItem[@"name"]; [dictionaryItem setObject:item.slider forKey:@"view"]; return item; - } else if ([type isEqualToString:@"button"]) { + } else if (isType(kTypeButton) || isType(kTypeTextButton)) { NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; - NSImage *image = dictionaryItem[@"image"]; - NSButton *button = [NSButton buttonWithImage:image target:self action:@selector(buttonAction:)]; + NSButton *button = isType(kTypeButton) + ? [NSButton buttonWithImage:dictionaryItem[@"image"] + target:self action:@selector(buttonAction:)] + : [NSButton buttonWithTitle:dictionaryItem[@"name"] + target:self action:@selector(buttonAction:)]; button.tag = [dictionaryItem[@"cmd"] intValue]; item.view = button; item.customizationLabel = dictionaryItem[@"name"]; [dictionaryItem setObject:button forKey:@"view"]; return item; - } else if ([type isEqualToString:@"textButton"]) { - NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; - NSButton *button = [NSButton buttonWithTitle:dictionaryItem[@"name"] target:self action:@selector(buttonAction:)]; - button.tag = [dictionaryItem[@"cmd"] intValue]; - item.view = button; - item.customizationLabel = dictionaryItem[@"name"]; - [dictionaryItem setObject:button forKey:@"view"]; - return item; - } else if ([type isEqualToString:@"text"]) { + } else if (isType(kTypeText)) { NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; NSTextField *text = [NSTextField labelWithString:@"00:00 / 00:00"]; text.alignment = NSTextAlignmentCenter; @@ -567,25 +882,34 @@ void SendKeyEvent(int command) { item.customizationLabel = dictionaryItem[@"name"]; [dictionaryItem setObject:text forKey:@"view"]; return item; - } else if ([type isEqualToString:@"popover"]) { + } else if (isType(kTypePopover)) { NSPopoverTouchBarItem *item = [[NSPopoverTouchBarItem alloc] initWithIdentifier:identifier]; item.collapsedRepresentationImage = dictionaryItem[@"image"]; - - NSTouchBar *secondaryTouchBar = [[NSTouchBar alloc] init]; - secondaryTouchBar.delegate = self; - if ([dictionaryItem[@"cmd"] intValue] == kCommandPopoverInput) { + const auto command = [dictionaryItem[@"cmd"] intValue]; + if (command == kCommandPopoverInput) { + NSTouchBar *secondaryTouchBar = [[NSTouchBar alloc] init]; + secondaryTouchBar.delegate = self; secondaryTouchBar.defaultItemIdentifiers = @[ kBoldItemIdentifier, kItalicItemIdentifier, kMonospaceItemIdentifier, kLinkItemIdentifier, kClearItemIdentifier]; + item.pressAndHoldTouchBar = secondaryTouchBar; + item.popoverTouchBar = secondaryTouchBar; + } else if (command == kCommandPopoverStickers) { + [self updateStickerTouchBar:item]; } - - item.pressAndHoldTouchBar = secondaryTouchBar; - item.popoverTouchBar = secondaryTouchBar; return item; - } else if ([type isEqualToString:@"pinned"]) { + } else if (isType(kTypeScrubber)) { + StickersCustomTouchBarItem *item = [[StickersCustomTouchBarItem alloc] + init:[=] { + NSPopoverTouchBarItem *item = [_touchBarMain itemForIdentifier:kPopoverStickersItemIdentifier]; + [item dismissPopover:nil]; + [self updateStickerTouchBar:item]; + }]; + return item; + } else if (isType(kTypePinned)) { NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; _mainPinnedButtons = [[NSMutableArray alloc] init]; NSStackView *stackView = [[NSStackView alloc] init]; @@ -655,15 +979,33 @@ void SendKeyEvent(int command) { _touchBarType = type; } -- (void) showInputFieldItems:(bool)show { - NSMutableArray *items = [NSMutableArray arrayWithObject:kPinnedPanelItemIdentifier]; +- (void) showInputFieldItem:(bool)show { + [self showItem:kPopoverInputItemIdentifier show:show]; +} + +- (void) showItem:(NSTouchBarItemIdentifier)item show:(bool)show { + NSMutableArray *items = [NSMutableArray arrayWithArray:_touchBarMain.defaultItemIdentifiers]; if (show) { - [items addObject:kPopoverInputItemIdentifier]; - _touchBarMain.principalItemIdentifier = kPopoverInputItemIdentifier; + if (![items containsObject:item]) { + [items addObject:item]; + } + } else if ([items containsObject:item]) { + [items removeObject:item]; } _touchBarMain.defaultItemIdentifiers = items; } +- (void) updateStickerTouchBar:(NSPopoverTouchBarItem *)item { + NSTouchBar *secondaryTouchBar = [[NSTouchBar alloc] init]; + secondaryTouchBar.delegate = self; + [[StickersCustomTouchBarItem alloc] init:[=] { + [item dismissPopover:nil]; + [self updateStickerTouchBar:item]; + }]; + secondaryTouchBar.defaultItemIdentifiers = @[kScrubberStickersItemIdentifier]; + item.popoverTouchBar = secondaryTouchBar; +} + // Main Touchbar. - (void) toggleArchiveButton:(bool)hide { @@ -791,7 +1133,6 @@ void SendKeyEvent(int command) { NSString *fString = [[textField.stringValue componentsSeparatedByCharactersInSet: [NSCharacterSet decimalDigitCharacterSet]] componentsJoinedByString:@"0"]; - NSSize size = [[NSTextField labelWithString:fString] frame].size; NSLayoutConstraint *con = [NSLayoutConstraint constraintWithItem:field @@ -800,7 +1141,7 @@ void SendKeyEvent(int command) { toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 - constant:(int)ceil(size.width) * 1.2]; + constant:WidthFromString(fString)]; [field addConstraint:con]; [item setObject:con forKey:@"constrain"]; } diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm index ec3d4f3f6..de3d5f559 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm @@ -768,7 +768,7 @@ void MainWindow::updateGlobalMenuHook() { canDelete = list->canDeleteSelected(); } if (_private->_touchBar) { - [_private->_touchBar showInputFieldItems:showTouchBarItem]; + [_private->_touchBar showInputFieldItem:showTouchBarItem]; } App::wnd()->updateIsActive(0); const auto logged = account().sessionExists();