mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Added sticker picker to touchbar.
This commit is contained in:
parent
a4d83b679a
commit
dcba07b9b7
6 changed files with 394 additions and 38 deletions
|
@ -5229,6 +5229,7 @@ void ApiWrap::sendExistingDocument(
|
||||||
main->finishForwarding(history);
|
main->finishForwarding(history);
|
||||||
if (document->sticker()) {
|
if (document->sticker()) {
|
||||||
main->incrementSticker(document);
|
main->incrementSticker(document);
|
||||||
|
_session->data().notifyRecentStickersUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1397,6 +1397,14 @@ rpl::producer<> Session::stickersUpdated() const {
|
||||||
return _stickersUpdated.events();
|
return _stickersUpdated.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::notifyRecentStickersUpdated() {
|
||||||
|
_recentStickersUpdated.fire({});
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> Session::recentStickersUpdated() const {
|
||||||
|
return _recentStickersUpdated.events();
|
||||||
|
}
|
||||||
|
|
||||||
void Session::notifySavedGifsUpdated() {
|
void Session::notifySavedGifsUpdated() {
|
||||||
_savedGifsUpdated.fire({});
|
_savedGifsUpdated.fire({});
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,8 @@ public:
|
||||||
|
|
||||||
void notifyStickersUpdated();
|
void notifyStickersUpdated();
|
||||||
[[nodiscard]] rpl::producer<> stickersUpdated() const;
|
[[nodiscard]] rpl::producer<> stickersUpdated() const;
|
||||||
|
void notifyRecentStickersUpdated();
|
||||||
|
[[nodiscard]] rpl::producer<> recentStickersUpdated() const;
|
||||||
void notifySavedGifsUpdated();
|
void notifySavedGifsUpdated();
|
||||||
[[nodiscard]] rpl::producer<> savedGifsUpdated() const;
|
[[nodiscard]] rpl::producer<> savedGifsUpdated() const;
|
||||||
void notifyPinnedDialogsOrderUpdated();
|
void notifyPinnedDialogsOrderUpdated();
|
||||||
|
@ -244,6 +246,9 @@ public:
|
||||||
return stickersUpdateNeeded(_lastRecentStickersUpdate, now);
|
return stickersUpdateNeeded(_lastRecentStickersUpdate, now);
|
||||||
}
|
}
|
||||||
void setLastRecentStickersUpdate(crl::time update) {
|
void setLastRecentStickersUpdate(crl::time update) {
|
||||||
|
if (update) {
|
||||||
|
notifyRecentStickersUpdated();
|
||||||
|
}
|
||||||
_lastRecentStickersUpdate = update;
|
_lastRecentStickersUpdate = update;
|
||||||
}
|
}
|
||||||
bool favedStickersUpdateNeeded(crl::time now) const {
|
bool favedStickersUpdateNeeded(crl::time now) const {
|
||||||
|
@ -839,6 +844,7 @@ private:
|
||||||
rpl::event_stream<DialogsRowReplacement> _dialogsRowReplacements;
|
rpl::event_stream<DialogsRowReplacement> _dialogsRowReplacements;
|
||||||
|
|
||||||
rpl::event_stream<> _stickersUpdated;
|
rpl::event_stream<> _stickersUpdated;
|
||||||
|
rpl::event_stream<> _recentStickersUpdated;
|
||||||
rpl::event_stream<> _savedGifsUpdated;
|
rpl::event_stream<> _savedGifsUpdated;
|
||||||
rpl::event_stream<> _pinnedDialogsOrderUpdated;
|
rpl::event_stream<> _pinnedDialogsOrderUpdated;
|
||||||
crl::time _lastStickersUpdate = 0;
|
crl::time _lastStickersUpdate = 0;
|
||||||
|
|
|
@ -27,6 +27,6 @@ enum class TouchBarType {
|
||||||
- (id _Nonnull) init:(NSView * _Nonnull)view;
|
- (id _Nonnull) init:(NSView * _Nonnull)view;
|
||||||
- (void) handleTrackStateChange:(Media::Player::TrackState)state;
|
- (void) handleTrackStateChange:(Media::Player::TrackState)state;
|
||||||
- (void) setTouchBar:(Platform::TouchBarType)type;
|
- (void) setTouchBar:(Platform::TouchBarType)type;
|
||||||
- (void) showInputFieldItems:(bool)show;
|
- (void) showInputFieldItem:(bool)show;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -27,6 +27,12 @@
|
||||||
#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 "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);
|
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/
|
//https://developer.apple.com/design/human-interface-guidelines/macos/touch-bar/touch-bar-icons-and-images/
|
||||||
constexpr auto kIdealIconSize = 36;
|
constexpr auto kIdealIconSize = 36;
|
||||||
constexpr auto kMaximumIconSize = 44;
|
constexpr auto kMaximumIconSize = 44;
|
||||||
|
constexpr auto kScrubberHeight = 30;
|
||||||
|
|
||||||
constexpr auto kCommandPlayPause = 0x002;
|
constexpr auto kCommandPlayPause = 0x002;
|
||||||
constexpr auto kCommandPlaylistPrevious = 0x003;
|
constexpr auto kCommandPlaylistPrevious = 0x003;
|
||||||
|
@ -47,6 +54,7 @@ constexpr auto kCommandClear = 0x013;
|
||||||
constexpr auto kCommandLink = 0x014;
|
constexpr auto kCommandLink = 0x014;
|
||||||
|
|
||||||
constexpr auto kCommandPopoverInput = 0x020;
|
constexpr auto kCommandPopoverInput = 0x020;
|
||||||
|
constexpr auto kCommandPopoverStickers = 0x021;
|
||||||
|
|
||||||
constexpr auto kMs = 1000;
|
constexpr auto kMs = 1000;
|
||||||
|
|
||||||
|
@ -55,6 +63,16 @@ constexpr auto kSongType = AudioMsgId::Type::Song;
|
||||||
constexpr auto kSavedMessagesId = 0;
|
constexpr auto kSavedMessagesId = 0;
|
||||||
constexpr auto kArchiveId = -1;
|
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 *kCustomizationIdPlayer = @"telegram.touchbar";
|
||||||
const NSString *kCustomizationIdMain = @"telegram.touchbarMain";
|
const NSString *kCustomizationIdMain = @"telegram.touchbarMain";
|
||||||
const NSTouchBarItemIdentifier kSavedMessagesItemIdentifier = [NSString stringWithFormat:@"%@.savedMessages", kCustomizationIdMain];
|
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 kClearItemIdentifier = [NSString stringWithFormat:@"%@.clear", kCustomizationIdMain];
|
||||||
const NSTouchBarItemIdentifier kLinkItemIdentifier = [NSString stringWithFormat:@"%@.link", 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;
|
using Platform::Q2NSString;
|
||||||
|
|
||||||
NSImage *CreateNSImageFromStyleIcon(const style::icon &icon, int size = kIdealIconSize) {
|
NSImage *CreateNSImageFromStyleIcon(const style::icon &icon, int size = kIdealIconSize) {
|
||||||
|
@ -86,6 +118,19 @@ NSImage *CreateNSImageFromStyleIcon(const style::icon &icon, int size = kIdealIc
|
||||||
return image;
|
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() {
|
inline bool CurrentSongExists() {
|
||||||
return Media::Player::instance()->current(kSongType).audio() != nullptr;
|
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));
|
QApplication::postEvent(focused, new QKeyEvent(QEvent::KeyRelease, key, modifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppendStickerSet(std::vector<StickerScrubberItem> &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<StickerScrubberItem> &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<StickerScrubberItem> &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
|
} // namespace
|
||||||
|
|
||||||
@interface PinnedDialogButton : NSCustomTouchBarItem
|
@interface PinnedDialogButton : NSCustomTouchBarItem
|
||||||
|
@ -384,6 +487,174 @@ void SendKeyEvent(int command) {
|
||||||
@end
|
@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
|
||||||
|
<NSScrubberDelegate,
|
||||||
|
NSScrubberDataSource,
|
||||||
|
NSScrubberFlowLayoutDelegate>
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
|
@implementation StickersCustomTouchBarItem {
|
||||||
|
Fn<void()> _stickerSent;
|
||||||
|
std::vector<StickerScrubberItem> _stickers;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) init:(Fn<void()>)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<StickerScrubberItem> 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()<NSTouchBarDelegate>
|
@interface TouchBar()<NSTouchBarDelegate>
|
||||||
@end // @interface TouchBar
|
@end // @interface TouchBar
|
||||||
|
|
||||||
|
@ -401,6 +672,7 @@ void SendKeyEvent(int command) {
|
||||||
double _position;
|
double _position;
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
rpl::lifetime _lifetimeSessionControllerChecker;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) init:(NSView *)view {
|
- (id) init:(NSView *)view {
|
||||||
|
@ -415,39 +687,39 @@ void SendKeyEvent(int command) {
|
||||||
_parentView = view;
|
_parentView = view;
|
||||||
self.touchBarItems = @{
|
self.touchBarItems = @{
|
||||||
kPinnedPanelItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
kPinnedPanelItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||||
@"type": @"pinned",
|
@"type": kTypePinned,
|
||||||
}],
|
}],
|
||||||
kSeekBarItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
kSeekBarItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||||
@"type": @"slider",
|
@"type": kTypeSlider,
|
||||||
@"name": @"Seek Bar"
|
@"name": @"Seek Bar"
|
||||||
}],
|
}],
|
||||||
kPlayItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
kPlayItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||||
@"type": @"button",
|
@"type": kTypeButton,
|
||||||
@"name": @"Play Button",
|
@"name": @"Play Button",
|
||||||
@"cmd": [NSNumber numberWithInt:kCommandPlayPause],
|
@"cmd": [NSNumber numberWithInt:kCommandPlayPause],
|
||||||
@"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerPause, iconSize),
|
@"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerPause, iconSize),
|
||||||
@"imageAlt": CreateNSImageFromStyleIcon(st::touchBarIconPlayerPlay, iconSize),
|
@"imageAlt": CreateNSImageFromStyleIcon(st::touchBarIconPlayerPlay, iconSize),
|
||||||
}],
|
}],
|
||||||
kPreviousItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
kPreviousItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||||
@"type": @"button",
|
@"type": kTypeButton,
|
||||||
@"name": @"Previous Playlist Item",
|
@"name": @"Previous Playlist Item",
|
||||||
@"cmd": [NSNumber numberWithInt:kCommandPlaylistPrevious],
|
@"cmd": [NSNumber numberWithInt:kCommandPlaylistPrevious],
|
||||||
@"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerPrevious, iconSize),
|
@"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerPrevious, iconSize),
|
||||||
}],
|
}],
|
||||||
kNextItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
kNextItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||||
@"type": @"button",
|
@"type": kTypeButton,
|
||||||
@"name": @"Next Playlist Item",
|
@"name": @"Next Playlist Item",
|
||||||
@"cmd": [NSNumber numberWithInt:kCommandPlaylistNext],
|
@"cmd": [NSNumber numberWithInt:kCommandPlaylistNext],
|
||||||
@"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerNext, iconSize),
|
@"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerNext, iconSize),
|
||||||
}],
|
}],
|
||||||
kCommandClosePlayerItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
kCommandClosePlayerItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||||
@"type": @"button",
|
@"type": kTypeButton,
|
||||||
@"name": @"Close Player",
|
@"name": @"Close Player",
|
||||||
@"cmd": [NSNumber numberWithInt:kCommandClosePlayer],
|
@"cmd": [NSNumber numberWithInt:kCommandClosePlayer],
|
||||||
@"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerClose, iconSize),
|
@"image": CreateNSImageFromStyleIcon(st::touchBarIconPlayerClose, iconSize),
|
||||||
}],
|
}],
|
||||||
kCurrentPositionItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
kCurrentPositionItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||||
@"type": @"text",
|
@"type": kTypeText,
|
||||||
@"name": @"Current Position"
|
@"name": @"Current Position"
|
||||||
}],
|
}],
|
||||||
kBoldItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
kBoldItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||||
|
@ -476,10 +748,22 @@ void SendKeyEvent(int command) {
|
||||||
@"cmd": [NSNumber numberWithInt:kCommandLink],
|
@"cmd": [NSNumber numberWithInt:kCommandLink],
|
||||||
}],
|
}],
|
||||||
kPopoverInputItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
kPopoverInputItemIdentifier: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||||
@"type": @"popover",
|
@"type": kTypePopover,
|
||||||
@"name": @"Input Field",
|
@"name": @"Input Field",
|
||||||
@"cmd": [NSNumber numberWithInt:kCommandPopoverInput],
|
@"cmd": [NSNumber numberWithInt:kCommandPopoverInput],
|
||||||
@"image": [NSImage imageNamed:NSImageNameTouchBarTextItalicTemplate],
|
@"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()];
|
[self toggleArchiveButton:folder->chatsList()->empty()];
|
||||||
}, _lifetime);
|
}, _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];
|
[self updatePinnedButtons];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -533,7 +850,10 @@ void SendKeyEvent(int command) {
|
||||||
makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
|
makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
|
||||||
const id dictionaryItem = self.touchBarItems[identifier];
|
const id dictionaryItem = self.touchBarItems[identifier];
|
||||||
const id type = dictionaryItem[@"type"];
|
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];
|
NSSliderTouchBarItem *item = [[NSSliderTouchBarItem alloc] initWithIdentifier:identifier];
|
||||||
item.slider.minValue = 0.0f;
|
item.slider.minValue = 0.0f;
|
||||||
item.slider.maxValue = 1.0f;
|
item.slider.maxValue = 1.0f;
|
||||||
|
@ -542,24 +862,19 @@ void SendKeyEvent(int command) {
|
||||||
item.customizationLabel = dictionaryItem[@"name"];
|
item.customizationLabel = dictionaryItem[@"name"];
|
||||||
[dictionaryItem setObject:item.slider forKey:@"view"];
|
[dictionaryItem setObject:item.slider forKey:@"view"];
|
||||||
return item;
|
return item;
|
||||||
} else if ([type isEqualToString:@"button"]) {
|
} else if (isType(kTypeButton) || isType(kTypeTextButton)) {
|
||||||
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
|
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
|
||||||
NSImage *image = dictionaryItem[@"image"];
|
NSButton *button = isType(kTypeButton)
|
||||||
NSButton *button = [NSButton buttonWithImage:image target:self action:@selector(buttonAction:)];
|
? [NSButton buttonWithImage:dictionaryItem[@"image"]
|
||||||
|
target:self action:@selector(buttonAction:)]
|
||||||
|
: [NSButton buttonWithTitle:dictionaryItem[@"name"]
|
||||||
|
target:self action:@selector(buttonAction:)];
|
||||||
button.tag = [dictionaryItem[@"cmd"] intValue];
|
button.tag = [dictionaryItem[@"cmd"] intValue];
|
||||||
item.view = button;
|
item.view = button;
|
||||||
item.customizationLabel = dictionaryItem[@"name"];
|
item.customizationLabel = dictionaryItem[@"name"];
|
||||||
[dictionaryItem setObject:button forKey:@"view"];
|
[dictionaryItem setObject:button forKey:@"view"];
|
||||||
return item;
|
return item;
|
||||||
} else if ([type isEqualToString:@"textButton"]) {
|
} else if (isType(kTypeText)) {
|
||||||
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"]) {
|
|
||||||
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
|
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
|
||||||
NSTextField *text = [NSTextField labelWithString:@"00:00 / 00:00"];
|
NSTextField *text = [NSTextField labelWithString:@"00:00 / 00:00"];
|
||||||
text.alignment = NSTextAlignmentCenter;
|
text.alignment = NSTextAlignmentCenter;
|
||||||
|
@ -567,25 +882,34 @@ void SendKeyEvent(int command) {
|
||||||
item.customizationLabel = dictionaryItem[@"name"];
|
item.customizationLabel = dictionaryItem[@"name"];
|
||||||
[dictionaryItem setObject:text forKey:@"view"];
|
[dictionaryItem setObject:text forKey:@"view"];
|
||||||
return item;
|
return item;
|
||||||
} else if ([type isEqualToString:@"popover"]) {
|
} else if (isType(kTypePopover)) {
|
||||||
NSPopoverTouchBarItem *item = [[NSPopoverTouchBarItem alloc] initWithIdentifier:identifier];
|
NSPopoverTouchBarItem *item = [[NSPopoverTouchBarItem alloc] initWithIdentifier:identifier];
|
||||||
item.collapsedRepresentationImage = dictionaryItem[@"image"];
|
item.collapsedRepresentationImage = dictionaryItem[@"image"];
|
||||||
|
const auto command = [dictionaryItem[@"cmd"] intValue];
|
||||||
NSTouchBar *secondaryTouchBar = [[NSTouchBar alloc] init];
|
if (command == kCommandPopoverInput) {
|
||||||
secondaryTouchBar.delegate = self;
|
NSTouchBar *secondaryTouchBar = [[NSTouchBar alloc] init];
|
||||||
if ([dictionaryItem[@"cmd"] intValue] == kCommandPopoverInput) {
|
secondaryTouchBar.delegate = self;
|
||||||
secondaryTouchBar.defaultItemIdentifiers = @[
|
secondaryTouchBar.defaultItemIdentifiers = @[
|
||||||
kBoldItemIdentifier,
|
kBoldItemIdentifier,
|
||||||
kItalicItemIdentifier,
|
kItalicItemIdentifier,
|
||||||
kMonospaceItemIdentifier,
|
kMonospaceItemIdentifier,
|
||||||
kLinkItemIdentifier,
|
kLinkItemIdentifier,
|
||||||
kClearItemIdentifier];
|
kClearItemIdentifier];
|
||||||
|
item.pressAndHoldTouchBar = secondaryTouchBar;
|
||||||
|
item.popoverTouchBar = secondaryTouchBar;
|
||||||
|
} else if (command == kCommandPopoverStickers) {
|
||||||
|
[self updateStickerTouchBar:item];
|
||||||
}
|
}
|
||||||
|
|
||||||
item.pressAndHoldTouchBar = secondaryTouchBar;
|
|
||||||
item.popoverTouchBar = secondaryTouchBar;
|
|
||||||
return item;
|
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];
|
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
|
||||||
_mainPinnedButtons = [[NSMutableArray alloc] init];
|
_mainPinnedButtons = [[NSMutableArray alloc] init];
|
||||||
NSStackView *stackView = [[NSStackView alloc] init];
|
NSStackView *stackView = [[NSStackView alloc] init];
|
||||||
|
@ -655,15 +979,33 @@ void SendKeyEvent(int command) {
|
||||||
_touchBarType = type;
|
_touchBarType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) showInputFieldItems:(bool)show {
|
- (void) showInputFieldItem:(bool)show {
|
||||||
NSMutableArray *items = [NSMutableArray arrayWithObject:kPinnedPanelItemIdentifier];
|
[self showItem:kPopoverInputItemIdentifier show:show];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) showItem:(NSTouchBarItemIdentifier)item show:(bool)show {
|
||||||
|
NSMutableArray *items = [NSMutableArray arrayWithArray:_touchBarMain.defaultItemIdentifiers];
|
||||||
if (show) {
|
if (show) {
|
||||||
[items addObject:kPopoverInputItemIdentifier];
|
if (![items containsObject:item]) {
|
||||||
_touchBarMain.principalItemIdentifier = kPopoverInputItemIdentifier;
|
[items addObject:item];
|
||||||
|
}
|
||||||
|
} else if ([items containsObject:item]) {
|
||||||
|
[items removeObject:item];
|
||||||
}
|
}
|
||||||
_touchBarMain.defaultItemIdentifiers = items;
|
_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.
|
// Main Touchbar.
|
||||||
|
|
||||||
- (void) toggleArchiveButton:(bool)hide {
|
- (void) toggleArchiveButton:(bool)hide {
|
||||||
|
@ -791,7 +1133,6 @@ void SendKeyEvent(int command) {
|
||||||
|
|
||||||
NSString *fString = [[textField.stringValue componentsSeparatedByCharactersInSet:
|
NSString *fString = [[textField.stringValue componentsSeparatedByCharactersInSet:
|
||||||
[NSCharacterSet decimalDigitCharacterSet]] componentsJoinedByString:@"0"];
|
[NSCharacterSet decimalDigitCharacterSet]] componentsJoinedByString:@"0"];
|
||||||
NSSize size = [[NSTextField labelWithString:fString] frame].size;
|
|
||||||
|
|
||||||
NSLayoutConstraint *con =
|
NSLayoutConstraint *con =
|
||||||
[NSLayoutConstraint constraintWithItem:field
|
[NSLayoutConstraint constraintWithItem:field
|
||||||
|
@ -800,7 +1141,7 @@ void SendKeyEvent(int command) {
|
||||||
toItem:nil
|
toItem:nil
|
||||||
attribute:NSLayoutAttributeNotAnAttribute
|
attribute:NSLayoutAttributeNotAnAttribute
|
||||||
multiplier:1.0
|
multiplier:1.0
|
||||||
constant:(int)ceil(size.width) * 1.2];
|
constant:WidthFromString(fString)];
|
||||||
[field addConstraint:con];
|
[field addConstraint:con];
|
||||||
[item setObject:con forKey:@"constrain"];
|
[item setObject:con forKey:@"constrain"];
|
||||||
}
|
}
|
||||||
|
|
|
@ -768,7 +768,7 @@ void MainWindow::updateGlobalMenuHook() {
|
||||||
canDelete = list->canDeleteSelected();
|
canDelete = list->canDeleteSelected();
|
||||||
}
|
}
|
||||||
if (_private->_touchBar) {
|
if (_private->_touchBar) {
|
||||||
[_private->_touchBar showInputFieldItems:showTouchBarItem];
|
[_private->_touchBar showInputFieldItem:showTouchBarItem];
|
||||||
}
|
}
|
||||||
App::wnd()->updateIsActive(0);
|
App::wnd()->updateIsActive(0);
|
||||||
const auto logged = account().sessionExists();
|
const auto logged = account().sessionExists();
|
||||||
|
|
Loading…
Add table
Reference in a new issue