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:
David Sinclair 2018-10-31 20:05:11 -07:00
parent 127944927f
commit fe65f038a6
5 changed files with 109 additions and 11 deletions

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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>

View file

@ -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>