Showing image context menu on tap.

This commit is contained in:
Samuel Clay 2014-09-18 16:55:37 -07:00
parent 2ef7f4f724
commit 9726802a8d
4 changed files with 114 additions and 53 deletions

View file

@ -11,6 +11,10 @@
@interface EventWindow : UIWindow {
CGPoint tapLocation;
NSTimer *contextualMenuTimer;
BOOL unmoved;
UIView *tapDetectingView;
}
@property (nonatomic) UIView *tapDetectingView;
@end

View file

@ -10,28 +10,43 @@
@implementation EventWindow
- (void)tapAndHoldAction:(NSTimer*)timer
{
@synthesize tapDetectingView;
- (void)tapAndHoldAction:(NSTimer*)timer {
contextualMenuTimer = nil;
NSDictionary *coord = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:tapLocation.x],@"x",
[NSNumber numberWithFloat:tapLocation.y],@"y",nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"TapAndHoldNotification" object:coord];
}
- (void)tapAction {
contextualMenuTimer = nil;
NSDictionary *coord = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:tapLocation.x],@"x",
[NSNumber numberWithFloat:tapLocation.y],@"y",nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"TapNotification" object:coord];
}
- (void)sendEvent:(UIEvent *)event {
NSSet *touches = [event touchesForWindow:self];
[super sendEvent:event]; // Call super to make sure the event is processed as usual
if (!tapDetectingView) return;
if ([touches count] == 1) { // We're only interested in one-finger events
UITouch *touch = [touches anyObject];
if (touch.view != nil && ![touch.view isDescendantOfView:tapDetectingView]) {
return;
}
switch ([touch phase]) {
case UITouchPhaseBegan: // A finger touched the screen
tapLocation = [touch locationInView:self];
[contextualMenuTimer invalidate];
contextualMenuTimer = [NSTimer scheduledTimerWithTimeInterval:0.8
unmoved = YES;
contextualMenuTimer = [NSTimer scheduledTimerWithTimeInterval:0.7
target:self selector:@selector(tapAndHoldAction:)
userInfo:nil repeats:NO];
break;
@ -40,13 +55,21 @@
break;
case UITouchPhaseEnded:
[contextualMenuTimer invalidate];
if (unmoved) {
[self tapAction];
}
break;
case UITouchPhaseMoved:
case UITouchPhaseCancelled:
unmoved = NO;
[contextualMenuTimer invalidate];
contextualMenuTimer = nil;
break;
}
} else { // Multiple fingers are touching the screen
unmoved = NO;
[contextualMenuTimer invalidate];
contextualMenuTimer = nil;
}

View file

@ -101,6 +101,10 @@
selector:@selector(tapAndHold:)
name:@"TapAndHoldNotification"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(tapImage:)
name:@"TapNotification"
object:nil];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
@ -1448,8 +1452,84 @@ shouldStartLoadWithRequest:(NSURLRequest *)request
[appDelegate openTrainStory:[NSValue valueWithCGRect:frame]];
}
- (void)tapImage:(NSNotification *)notification {
CGPoint pt = [self pointForEvent:notification];
if (pt.x == CGPointZero.x && pt.y == CGPointZero.y) return;
NSString *tagName = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'tagName');",
(long)pt.x,(long)pt.y]];
if ([tagName isEqualToString:@"IMG"]) {
[self showImageMenu:pt];
}
}
- (void)tapAndHold:(NSNotification*)notification {
if (self != appDelegate.storyPageControl.currentPage) return;
CGPoint pt = [self pointForEvent:notification];
if (pt.x == CGPointZero.x && pt.y == CGPointZero.y) return;
NSString *tagName = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'tagName');",
(long)pt.x,(long)pt.y]];
if ([tagName isEqualToString:@"IMG"]) {
[self showImageMenu:pt];
}
if ([tagName isEqualToString:@"A"]) {
[self showLinkContextMenu:pt];
}
}
- (void)showImageMenu:(CGPoint)pt {
NSString *title = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'title');",
(long)pt.x,(long)pt.y]];
NSString *alt = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'alt');",
(long)pt.x,(long)pt.y]];
NSString *src = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'src');",
(long)pt.x,(long)pt.y]];
title = title.length ? title : alt;
activeLongPressUrl = [NSURL URLWithString:src];
UIActionSheet *actions = [[UIActionSheet alloc] initWithTitle:title.length ? title : nil
delegate:self
cancelButtonTitle:@"Done"
destructiveButtonTitle:nil
otherButtonTitles:nil];
actionSheetViewImageIndex = [actions addButtonWithTitle:@"View and zoom"];
actionSheetCopyImageIndex = [actions addButtonWithTitle:@"Copy image"];
actionSheetSaveImageIndex = [actions addButtonWithTitle:@"Save to camera roll"];
[actions showInView:appDelegate.storyPageControl.view];
}
- (void)showLinkContextMenu:(CGPoint)pt {
NSString *href = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'href');",
(long)pt.x,(long)pt.y]];
NSString *title = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'innerText');",
(long)pt.x,(long)pt.y]];
NSURL *url = [NSURL URLWithString:href];
if (!href || ![href length]) return;
[appDelegate showSendTo:appDelegate.storyPageControl
sender:nil
withUrl:url
authorName:nil
text:nil
title:title
feedTitle:nil
images:nil];
}
- (CGPoint)pointForEvent:(NSNotification*)notification {
if (self != appDelegate.storyPageControl.currentPage) return CGPointZero;
if (!self.view.window) return CGPointZero;
CGPoint pt;
NSDictionary *coord = [notification object];
@ -1468,55 +1548,7 @@ shouldStartLoadWithRequest:(NSURLRequest *)request
pt.x = pt.x * f;// + offset.x;
pt.y = pt.y * f;// + offset.y;
// get the Tags at the touch location
NSString *tagName = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'tagName');",
(long)pt.x,(long)pt.y]];
if ([tagName isEqualToString:@"IMG"]) {
NSString *title = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'title');",
(long)pt.x,(long)pt.y]];
NSString *alt = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'alt');",
(long)pt.x,(long)pt.y]];
NSString *src = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'src');",
(long)pt.x,(long)pt.y]];
title = title.length ? title : alt;
activeLongPressUrl = [NSURL URLWithString:src];
UIActionSheet *actions = [[UIActionSheet alloc] initWithTitle:title.length ? title : nil
delegate:self
cancelButtonTitle:@"Done"
destructiveButtonTitle:nil
otherButtonTitles:nil];
actionSheetViewImageIndex = [actions addButtonWithTitle:@"View and zoom"];
actionSheetCopyImageIndex = [actions addButtonWithTitle:@"Copy image"];
actionSheetSaveImageIndex = [actions addButtonWithTitle:@"Save to camera roll"];
[actions showInView:appDelegate.storyPageControl.view];
}
if ([tagName isEqualToString:@"A"]) {
NSString *href = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'href');",
(long)pt.x,(long)pt.y]];
NSString *title = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"linkAt(%li, %li, 'innerText');",
(long)pt.x,(long)pt.y]];
NSURL *url = [NSURL URLWithString:href];
if (!href || ![href length]) return;
[appDelegate showSendTo:appDelegate.storyPageControl
sender:nil
withUrl:url
authorName:nil
text:nil
title:title
feedTitle:nil
images:nil];
}
return pt;
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {

View file

@ -766,6 +766,8 @@
}
[self setNextPreviousButtons];
EventWindow *tapDetectingWindow = (EventWindow*)appDelegate.window;
tapDetectingWindow.tapDetectingView = currentPage.view;
[appDelegate changeActiveFeedDetailRow];
if (self.currentPage.pageIndex != location) {