mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-09-18 21:50:56 +00:00
iOS: #1137 (full screen reading)
Added a "Tap story" preference with "Toggle full screen" and "Do nothing" options; toggling is the default. This is only available on iPhone. When active, a single tap in a story, not on a link, image, movie, or button, will hide or show the status and navigation bars. On iPhones with a notch (iPhone X, XS, etc), the feed bar at the top is also hidden, so the story can scroll under the notch, using every bit of the screen.
This commit is contained in:
parent
127944927f
commit
fe65f038a6
5 changed files with 109 additions and 11 deletions
|
@ -232,6 +232,14 @@
|
|||
}];
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
return self.navigationController.navigationBarHidden && self.view.safeAreaInsets.top > 0.0;
|
||||
} else {
|
||||
return self.navigationController.navigationBarHidden;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)adjustLayout {
|
||||
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
|
||||
return;
|
||||
|
|
|
@ -104,12 +104,12 @@
|
|||
doubleTapGesture.delegate = self;
|
||||
[self.webView addGestureRecognizer:doubleTapGesture];
|
||||
|
||||
// UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
|
||||
// initWithTarget:self action:@selector(tap:)];
|
||||
// tapGesture.numberOfTapsRequired = 1;
|
||||
// tapGesture.delegate = self;
|
||||
// [tapGesture requireGestureRecognizerToFail:doubleTapGesture];
|
||||
// [self.webView addGestureRecognizer:tapGesture];
|
||||
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
|
||||
initWithTarget:self action:@selector(tap:)];
|
||||
tapGesture.numberOfTapsRequired = 1;
|
||||
tapGesture.delegate = self;
|
||||
[tapGesture requireGestureRecognizerToFail:doubleTapGesture];
|
||||
[self.webView addGestureRecognizer:tapGesture];
|
||||
|
||||
UITapGestureRecognizer *doubleDoubleTapGesture = [[UITapGestureRecognizer alloc]
|
||||
initWithTarget:self
|
||||
|
@ -166,10 +166,60 @@
|
|||
}
|
||||
|
||||
- (void)tap:(UITapGestureRecognizer *)gestureRecognizer {
|
||||
// NSLog(@"Gesture tap: %d (%d) - %d", gestureRecognizer.state, UIGestureRecognizerStateEnded, inDoubleTap);
|
||||
// NSLog(@"Gesture tap: %ld (%ld) - %d", (long)gestureRecognizer.state, (long)UIGestureRecognizerStateEnded, inDoubleTap);
|
||||
|
||||
if (gestureRecognizer.state == UIGestureRecognizerStateEnded && gestureRecognizer.numberOfTouches == 1) {
|
||||
[self tapImage:gestureRecognizer];
|
||||
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
|
||||
NSString *tapStory = [preferences stringForKey:@"tap_story"];
|
||||
|
||||
if (gestureRecognizer.state == UIGestureRecognizerStateEnded && gestureRecognizer.numberOfTouches == 1 && [tapStory isEqualToString:@"toggle_full_screen"] && UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
||||
CGPoint pt = [self pointForGesture:gestureRecognizer];
|
||||
if (pt.x == CGPointZero.x && pt.y == CGPointZero.y) return;
|
||||
// NSLog(@"Tapped point: %@", NSStringFromCGPoint(pt));
|
||||
NSString *tagName = [webView stringByEvaluatingJavaScriptFromString:
|
||||
[NSString stringWithFormat:@"linkAt(%li, %li, 'tagName');",
|
||||
(long)pt.x,(long)pt.y]];
|
||||
|
||||
// Special case to handle the story title, Train, Save, and Share buttons.
|
||||
if ([tagName isEqualToString:@"DIV"]) {
|
||||
NSString *identifier = [webView stringByEvaluatingJavaScriptFromString:
|
||||
[NSString stringWithFormat:@"linkAt(%li, %li, 'id');",
|
||||
(long)pt.x,(long)pt.y]];
|
||||
NSString *outerHTML = [webView stringByEvaluatingJavaScriptFromString:
|
||||
[NSString stringWithFormat:@"linkAt(%li, %li, 'outerHTML');",
|
||||
(long)pt.x,(long)pt.y]];
|
||||
|
||||
if (![identifier isEqualToString:@"NB-story"] && [outerHTML containsString:@"NB-"]) {
|
||||
tagName = @"A";
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore links, images, videos, and iframes (e.g. embedded YouTube videos).
|
||||
if (!inDoubleTap && ![@[@"A", @"IMG", @"VIDEO", @"IFRAME"] containsObject:tagName]) {
|
||||
BOOL isHidden = self.navigationController.navigationBarHidden;
|
||||
|
||||
[self.navigationController setNavigationBarHidden:!isHidden animated:YES];
|
||||
|
||||
if (@available(iOS 11.0, *)) {
|
||||
if (!isHidden && self.view.safeAreaInsets.top > 0.0 && self.webView.scrollView.contentOffset.y <= 0.0) {
|
||||
CGRect frame = self.webView.frame;
|
||||
self.webView.frame = CGRectMake(frame.origin.x, frame.origin.y + 40, frame.size.width, frame.size.height + 80);
|
||||
self.webView.scrollView.contentOffset = CGPointMake(0.0, 10.0);
|
||||
}
|
||||
}
|
||||
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
[self setNeedsStatusBarAppearanceUpdate];
|
||||
}];
|
||||
|
||||
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
[appDelegate.storyPageControl adjustDragBar:orientation];
|
||||
[appDelegate.storyPageControl reorientPages];
|
||||
|
||||
[self.view setNeedsLayout];
|
||||
[self.view layoutIfNeeded];
|
||||
}
|
||||
|
||||
// [self tapImage:gestureRecognizer];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -547,6 +597,16 @@
|
|||
self.feedTitleGradient = nil;
|
||||
}
|
||||
|
||||
if (self.navigationController.navigationBarHidden) {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
if (self.view.safeAreaInsets.top > 0.0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.feedTitleGradient = [appDelegate
|
||||
makeFeedTitleGradient:feed
|
||||
withRect:CGRectMake(0, -1, CGRectGetWidth(self.view.bounds), 21)]; // 1024 hack for self.webView.frame.size.width
|
||||
|
|
|
@ -426,6 +426,14 @@
|
|||
[self adjustDragBar:orientation];
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
return self.navigationController.navigationBarHidden && self.view.safeAreaInsets.top > 0.0;
|
||||
} else {
|
||||
return self.navigationController.navigationBarHidden;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)adjustDragBar:(UIInterfaceOrientation)orientation {
|
||||
// CGRect scrollViewFrame = self.scrollView.frame;
|
||||
// CGRect traverseViewFrame = self.traverseView.frame;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina3_5" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -464,6 +464,28 @@
|
|||
<key>DefaultValue</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string></string>
|
||||
<key>Type</key>
|
||||
<string>PSMultiValueSpecifier</string>
|
||||
<key>Title</key>
|
||||
<string>Tap story</string>
|
||||
<key>Titles</key>
|
||||
<array>
|
||||
<string>Toggle full screen</string>
|
||||
<string>Do nothing</string>
|
||||
</array>
|
||||
<key>DefaultValue</key>
|
||||
<string>toggle_full_screen</string>
|
||||
<key>Values</key>
|
||||
<array>
|
||||
<string>toggle_full_screen</string>
|
||||
<string>nothing</string>
|
||||
</array>
|
||||
<key>Key</key>
|
||||
<string>tap_story</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string></string>
|
||||
|
|
Loading…
Add table
Reference in a new issue