Refactored ability to display media preview from touchbar.

This commit is contained in:
23rd 2019-09-11 16:34:38 +03:00 committed by John Preston
parent 664162982c
commit 9bf8b619fe

View file

@ -74,6 +74,17 @@ constexpr auto kArchiveId = -1;
constexpr auto kMaxStickerSets = 5; constexpr auto kMaxStickerSets = 5;
constexpr auto kGestureStateProcessed = {
NSGestureRecognizerStateChanged,
NSGestureRecognizerStateBegan,
};
constexpr auto kGestureStateFinished = {
NSGestureRecognizerStateEnded,
NSGestureRecognizerStateCancelled,
NSGestureRecognizerStateFailed,
};
NSString *const kTypePinned = @"pinned"; NSString *const kTypePinned = @"pinned";
NSString *const kTypeSlider = @"slider"; NSString *const kTypeSlider = @"slider";
NSString *const kTypeButton = @"button"; NSString *const kTypeButton = @"button";
@ -641,9 +652,11 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
@end // @interface PickerScrubberItemView @end // @interface PickerScrubberItemView
@implementation PickerScrubberItemView { @implementation PickerScrubberItemView {
rpl::lifetime _lifetime; rpl::lifetime _lifetime;
Data::FileOrigin _origin;
QSize _dimensions; QSize _dimensions;
Image *_image; Image *_image;
@public
Data::FileOrigin fileOrigin;
DocumentData *documentData;
} }
- (instancetype)initWithFrame:(NSRect)frameRect { - (instancetype)initWithFrame:(NSRect)frameRect {
@ -667,9 +680,10 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
if (!_image) { if (!_image) {
return; return;
} }
fileOrigin = document->stickerSetOrigin();
documentData = std::move(document);
_dimensions = document->dimensions; _dimensions = document->dimensions;
_origin = document->stickerSetOrigin(); _image->load(fileOrigin);
_image->load(_origin);
if (_image->loaded()) { if (_image->loaded()) {
[self updateImage]; [self updateImage];
return; return;
@ -689,7 +703,7 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
.scaled(kCircleDiameter, kCircleDiameter, Qt::KeepAspectRatio); .scaled(kCircleDiameter, kCircleDiameter, Qt::KeepAspectRatio);
_imageView.image = [qt_mac_create_nsimage( _imageView.image = [qt_mac_create_nsimage(
_image->pixSingle( _image->pixSingle(
_origin, fileOrigin,
size.width(), size.width(),
size.height(), size.height(),
kCircleDiameter, kCircleDiameter,
@ -711,9 +725,7 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
@implementation PickerCustomTouchBarItem { @implementation PickerCustomTouchBarItem {
std::vector<PickerScrubberItem> _stickers; std::vector<PickerScrubberItem> _stickers;
NSPopoverTouchBarItem *_parentPopover; NSPopoverTouchBarItem *_parentPopover;
std::unique_ptr<base::Timer> _previewTimer; DocumentId _lastPreviewedSticker;
int _highlightedIndex;
bool _previewShown;
} }
- (id) init:(ScrubberItemType)type popover:(NSPopoverTouchBarItem *)popover { - (id) init:(ScrubberItemType)type popover:(NSPopoverTouchBarItem *)popover {
@ -739,18 +751,65 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
[scrubber registerClass:[NSScrubberTextItemView class] forItemIdentifier:kPickerTitleItemIdentifier]; [scrubber registerClass:[NSScrubberTextItemView class] forItemIdentifier:kPickerTitleItemIdentifier];
[scrubber registerClass:[NSScrubberImageItemView class] forItemIdentifier:kEmojiItemIdentifier]; [scrubber registerClass:[NSScrubberImageItemView class] forItemIdentifier:kEmojiItemIdentifier];
_previewShown = false; if (IsSticker(type)) {
_highlightedIndex = 0; auto *gesture = [[NSPressGestureRecognizer alloc]
_previewTimer = !IsSticker(type) initWithTarget:self
? nullptr action:@selector(gesturePreviewHandler:)];
: std::make_unique<base::Timer>([=] { gesture.allowedTouchTypes = NSTouchTypeMaskDirect;
[self showPreview]; gesture.minimumPressDuration = QApplication::startDragTime() / 1000.;
}); gesture.allowableMovement = 0;
[scrubber addGestureRecognizer:gesture];
}
_lastPreviewedSticker = 0;
self.view = scrubber; self.view = scrubber;
return self; return self;
} }
- (void)gesturePreviewHandler:(NSPressGestureRecognizer *)gesture {
const auto customEnter = [](const auto callback) {
Core::Sandbox::Instance().customEnterFromEventLoop([=] {
if (App::wnd()) {
callback();
}
});
};
const auto checkState = [&](const auto &states) {
return ranges::find(states, gesture.state) != end(states);
};
if (checkState(kGestureStateProcessed)) {
NSScrollView *scrollView = self.view;
auto *container = scrollView.documentView.subviews.firstObject;
if (!container) {
return;
}
const auto point = [gesture locationInView:(std::move(container))];
for (PickerScrubberItemView *item in container.subviews) {
const auto &doc = item->documentData;
const auto &origin = item->fileOrigin
? item->fileOrigin
: Data::FileOrigin();
if (![item isMemberOfClass:[PickerScrubberItemView class]]
|| !doc
|| (doc->id == _lastPreviewedSticker)
|| !NSPointInRect(point, item.frame)) {
continue;
}
_lastPreviewedSticker = doc->id;
customEnter([origin = std::move(origin), doc = std::move(doc)] {
App::wnd()->showMediaPreview(origin, doc);
});
break;
}
} else if (checkState(kGestureStateFinished)) {
customEnter([] { App::wnd()->hideMediaPreview(); });
_lastPreviewedSticker = 0;
}
}
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { - (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
// Has not been implemented. // Has not been implemented.
} }
@ -765,7 +824,7 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
const auto item = _stickers[index]; const auto item = _stickers[index];
if (const auto document = item.document) { if (const auto document = item.document) {
PickerScrubberItemView *itemView = [scrubber makeItemWithIdentifier:kStickerItemIdentifier owner:nil]; PickerScrubberItemView *itemView = [scrubber makeItemWithIdentifier:kStickerItemIdentifier owner:nil];
[itemView addDocument:document]; [itemView addDocument:(std::move(document))];
return itemView; return itemView;
} else if (const auto emoji = item.emoji) { } else if (const auto emoji = item.emoji) {
NSScrubberImageItemView *itemView = [scrubber makeItemWithIdentifier:kEmojiItemIdentifier owner:nil]; NSScrubberImageItemView *itemView = [scrubber makeItemWithIdentifier:kEmojiItemIdentifier owner:nil];
@ -791,12 +850,6 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
return; return;
} }
scrubber.selectedIndex = -1; scrubber.selectedIndex = -1;
if (_previewShown && [self hidePreview]) {
return;
}
if (_previewTimer) {
_previewTimer->cancel();
}
const auto chat = GetActiveChat(); const auto chat = GetActiveChat();
const auto callback = [&]() -> bool { const auto callback = [&]() -> bool {
@ -828,47 +881,6 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
} }
} }
- (void)scrubber:(NSScrubber *)scrubber didHighlightItemAtIndex:(NSInteger)index {
if (_previewTimer) {
_previewTimer->callOnce(QApplication::startDragTime());
_highlightedIndex = index;
}
}
- (void)scrubber:(NSScrubber *)scrubber didChangeVisibleRange:(NSRange)visibleRange {
[self didCancelInteractingWithScrubber:scrubber];
}
- (void)didCancelInteractingWithScrubber:(NSScrubber *)scrubber {
if (_previewTimer) {
_previewTimer->cancel();
}
if (_previewShown) {
[self hidePreview];
}
}
- (void)showPreview {
if (const auto document = _stickers[_highlightedIndex].document) {
if (const auto w = App::wnd()) {
w->showMediaPreview(document->stickerSetOrigin(), document);
_previewShown = true;
}
}
}
- (bool)hidePreview {
if (const auto w = App::wnd()) {
Core::Sandbox::Instance().customEnterFromEventLoop([=] {
w->hideMediaPreview();
});
_previewShown = false;
_highlightedIndex = 0;
return true;
}
return false;
}
- (void)updateStickers { - (void)updateStickers {
std::vector<PickerScrubberItem> temp; std::vector<PickerScrubberItem> temp;
if (const auto error = RestrictionToSendStickers()) { if (const auto error = RestrictionToSendStickers()) {