#817 (three column layout)

- Since the UIPageViewController approach to paging had multiple issues that were proving impossible to work around, I decided to revert to the old UIScrollView-based approach.
This commit is contained in:
David Sinclair 2021-01-29 20:10:53 -08:00
parent 08477fdb51
commit f091832e6d
26 changed files with 904 additions and 1409 deletions

View file

@ -9,7 +9,12 @@
import UIKit
/// Manages the detail column of the split view, with the feed detail and/or the story pages.
class DetailViewController: DetailObjCViewController {
class DetailViewController: BaseViewController {
/// Returns the shared app delegate.
var appDelegate: NewsBlurAppDelegate {
return NewsBlurAppDelegate.shared()
}
/// Preference keys.
enum Key {
/// Layout of the story titles and story pages.
@ -81,6 +86,11 @@ class DetailViewController: DetailObjCViewController {
return layout == .top
}
/// Returns `true` if the window is in portrait orientation, otherwise `false`.
@objc var isPortraitOrientation: Bool {
return view.window?.windowScene?.interfaceOrientation.isPortrait ?? false
}
/// Position of the divider between the views.
var dividerPosition: CGFloat {
get {
@ -110,6 +120,9 @@ class DetailViewController: DetailObjCViewController {
/// Bottom container view.
@IBOutlet weak var bottomContainerView: UIView!
/// Draggable divider view.
@IBOutlet weak var dividerView: UIView!
/// Top container view top constraint. May need to adjust this for fullscreen on iPhone.
@IBOutlet weak var topContainerTopConstraint: NSLayoutConstraint!
@ -125,92 +138,17 @@ class DetailViewController: DetailObjCViewController {
/// The feed detail view controller, if using `top` or `bottom` layout. `nil` if using `left` layout.
var feedDetailViewController: FeedDetailViewController?
/// The horizontal page view controller.
var horizontalPageViewController: HorizontalPageViewController?
/// The horizontal page view controller. [Not currently used; might be used for #1351 (gestures in vertical scrolling).]
// var horizontalPageViewController: HorizontalPageViewController?
/// Enable paging upwards and/or downwards.
///
/// - Parameter up: Allow paging up to the previous story.
/// - Parameter down: Allow paging down to the next story.
@objc(allowPagingUp:down:) func allowPaging(up: Bool, down: Bool) {
horizontalPageViewController?.currentController?.allowPaging(up: up, down: down)
/// The story pages view controller, that manages the previous, current, and next story view controllers.
var storyPagesViewController: StoryPagesViewController? {
return appDelegate.storyPagesViewController
}
/// Returns the currently displayed story view controller, or `nil` if none.
@objc var currentStoryController: StoryDetailViewController? {
return horizontalPageViewController?.currentController?.currentController
}
/// Returns an array of all existing story view controllers.
@objc var storyControllers: [StoryDetailViewController] {
var controllers = [StoryDetailViewController]()
guard let pageViewController = horizontalPageViewController else {
return controllers
}
addStories(from: pageViewController.previousController, to: &controllers)
addStories(from: pageViewController.currentController, to: &controllers)
addStories(from: pageViewController.nextController, to: &controllers)
return controllers
}
/// Returns an array of the previous, current, and next vertical page view controllers, each with the previous, current, and next story view controllers. Note that the top-level array will always have three values, but the inner arrays may have 0-3, depending on usage. This is mainly for debugging use.
@objc var storyControllersMatrix: [[StoryDetailViewController]] {
guard let pageViewController = horizontalPageViewController else {
return [[]]
}
var previousVerticalControllers = [StoryDetailViewController]()
var currentVerticalControllers = [StoryDetailViewController]()
var nextVerticalControllers = [StoryDetailViewController]()
addStories(from: pageViewController.previousController, to: &previousVerticalControllers)
addStories(from: pageViewController.currentController, to: &currentVerticalControllers)
addStories(from: pageViewController.nextController, to: &nextVerticalControllers)
return [previousVerticalControllers, currentVerticalControllers, nextVerticalControllers]
}
/// Calls a closure for each story view controller.
///
/// - Parameter handler: The closure to call; it takes a story controller as a parameter.
@objc(updateStoryControllers:) func updateStoryControllers(handler:(StoryDetailViewController) -> Void) {
for controller in storyControllers {
handler(controller)
}
}
/// Resets all of the other story controllers from the current one.
@objc func resetOtherStoryControllers() {
horizontalPageViewController?.currentController = horizontalPageViewController?.currentController
// navigationItem.titleView = nil
}
/// Resets the page controllers to a blank state.
@objc func resetPageControllers() {
if let viewController = Storyboards.shared.controller(withIdentifier: .verticalPages) as? VerticalPageViewController {
viewController.horizontalPageViewController = horizontalPageViewController
viewController.currentController = makeStoryController(for: -2)
print("DetailViewController setViewControllers: \(String(describing: viewController))")
horizontalPageViewController?.setViewControllers([viewController], direction: .forward, animated: false, completion: nil)
}
}
/// Creates a new story view controller for the specified page index, and starts loading the content.
///
/// - Parameter pageIndex: The index of the story page.
/// - Returns: A new `StoryDetailViewController` instance.
func makeStoryController(for pageIndex: Int) -> StoryDetailViewController? {
let storyController = StoryDetailViewController(pageIndex: pageIndex)
applyNewIndex(pageIndex, pageController: storyController)
return storyController
return storyPagesViewController?.currentPage
}
/// Updates the layout; call this when the layout is changed in the preferences.
@ -221,7 +159,7 @@ class DetailViewController: DetailObjCViewController {
}
@objc func adjustForAutoscroll() {
if UIDevice.current.userInterfaceIdiom == .phone, !isNavigationBarHidden {
if UIDevice.current.userInterfaceIdiom == .phone, let controller = storyPagesViewController, !controller.isNavigationBarHidden {
topContainerTopConstraint.constant = -44
} else {
topContainerTopConstraint.constant = 0
@ -232,7 +170,6 @@ class DetailViewController: DetailObjCViewController {
super.viewDidLoad()
updateLayout(reload: false)
resetPageControllers()
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
@ -317,32 +254,30 @@ private extension DetailViewController {
dividerViewBottomConstraint.constant = dividerPosition
}
if horizontalPageViewController == nil {
horizontalPageViewController = Storyboards.shared.controller(withIdentifier: .horizontalPages) as? HorizontalPageViewController
horizontalPageViewController?.detailViewController = self
guard let storyPagesViewController = storyPagesViewController else {
return
}
let appropriateSuperview = isTop ? bottomContainerView : topContainerView
if horizontalPageViewController?.view.superview != appropriateSuperview {
add(viewController: horizontalPageViewController, top: !isTop)
if storyPagesViewController.view.superview != appropriateSuperview {
add(viewController: storyPagesViewController, top: !isTop)
adjustForAutoscroll()
if isTop {
bottomContainerView.addSubview(traverseView)
bottomContainerView.addSubview(autoscrollView)
} else {
topContainerView.addSubview(traverseView)
topContainerView.addSubview(autoscrollView)
}
// if isTop {
// bottomContainerView.addSubview(traverseView)
// bottomContainerView.addSubview(autoscrollView)
// } else {
// topContainerView.addSubview(traverseView)
// topContainerView.addSubview(autoscrollView)
// }
}
traverseTopContainerBottomConstraint.isActive = !isTop
traverseBottomContainerBottomConstraint.isActive = isTop
autoscrollTopContainerBottomConstraint.isActive = !isTop
autoscrollBottomContainerBottomConstraint.isActive = isTop
//
// traverseTopContainerBottomConstraint.isActive = !isTop
// traverseBottomContainerBottomConstraint.isActive = isTop
// autoscrollTopContainerBottomConstraint.isActive = !isTop
// autoscrollBottomContainerBottomConstraint.isActive = isTop
}
func add(viewController: UIViewController?, top: Bool) {
@ -380,20 +315,4 @@ private extension DetailViewController {
viewController.removeFromParent()
viewController.view.removeFromSuperview()
}
func addStories(from verticalPageController: VerticalPageViewController?, to controllers: inout [StoryDetailViewController]) {
guard let verticalPageController = verticalPageController else {
return
}
addStory(verticalPageController.previousController, to: &controllers)
addStory(verticalPageController.currentController, to: &controllers)
addStory(verticalPageController.nextController, to: &controllers)
}
func addStory(_ story: StoryDetailViewController?, to controllers: inout [StoryDetailViewController]) {
if let story = story {
controllers.append(story)
}
}
}

View file

@ -577,8 +577,8 @@
NSString *feedID = [coder decodeObjectOfClass:[NSString class] forKey:@"feed_id"];
if (folder != nil || feedID != nil) {
// self.restoringFolder = folder;
// self.restoringFeedID = feedID;
self.restoringFolder = folder;
self.restoringFeedID = feedID;
}
}
@ -632,7 +632,7 @@
[storiesCollection setStories:nil];
[storiesCollection setFeedUserProfiles:nil];
storiesCollection.storyCount = 0;
[appDelegate.detailViewController resetPageControllers];
[appDelegate.storyPagesViewController resetPages];
storiesCollection.inSearch = NO;
storiesCollection.searchQuery = nil;
@ -1179,10 +1179,10 @@
[self renderStories:confirmedNewStories];
if (!self.isPhoneOrCompact) {
[appDelegate.detailViewController resizeScrollView];
[appDelegate.detailViewController setStoryFromScroll:YES];
[appDelegate.storyPagesViewController resizeScrollView];
[appDelegate.storyPagesViewController setStoryFromScroll:YES];
}
[appDelegate.detailViewController advanceToNextUnread];
[appDelegate.storyPagesViewController advanceToNextUnread];
if (!storiesCollection.storyCount) {
if ([results objectForKey:@"message"] && ![[results objectForKey:@"message"] isKindOfClass:[NSNull class]]) {
@ -2275,7 +2275,7 @@ didEndSwipingSwipingWithState:(MCSwipeTableViewCellState)state
[viewController addThemeSegmentedControl];
UINavigationController *navController = self.navigationController ?: appDelegate.detailViewController.navigationController;
UINavigationController *navController = self.navigationController ?: appDelegate.storyPagesViewController.navigationController;
[viewController showFromNavigationController:navController barButtonItem:self.settingsBarButton];
}

View file

@ -96,7 +96,7 @@
self.selectedIndexPath = indexPath;
[appDelegate.detailViewController setFontStyle:style];
[appDelegate.storyPagesViewController setFontStyle:style];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

View file

@ -180,19 +180,19 @@
- (IBAction)changeFontSize:(id)sender {
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
if ([sender selectedSegmentIndex] == 0) {
[self.appDelegate.detailViewController changeFontSize:@"xs"];
[self.appDelegate.storyPagesViewController changeFontSize:@"xs"];
[userPreferences setObject:@"xs" forKey:@"story_font_size"];
} else if ([sender selectedSegmentIndex] == 1) {
[self.appDelegate.detailViewController changeFontSize:@"small"];
[self.appDelegate.storyPagesViewController changeFontSize:@"small"];
[userPreferences setObject:@"small" forKey:@"story_font_size"];
} else if ([sender selectedSegmentIndex] == 2) {
[self.appDelegate.detailViewController changeFontSize:@"medium"];
[self.appDelegate.storyPagesViewController changeFontSize:@"medium"];
[userPreferences setObject:@"medium" forKey:@"story_font_size"];
} else if ([sender selectedSegmentIndex] == 3) {
[self.appDelegate.detailViewController changeFontSize:@"large"];
[self.appDelegate.storyPagesViewController changeFontSize:@"large"];
[userPreferences setObject:@"large" forKey:@"story_font_size"];
} else if ([sender selectedSegmentIndex] == 4) {
[self.appDelegate.detailViewController changeFontSize:@"xl"];
[self.appDelegate.storyPagesViewController changeFontSize:@"xl"];
[userPreferences setObject:@"xl" forKey:@"story_font_size"];
}
[userPreferences synchronize];
@ -201,19 +201,19 @@
- (IBAction)changeLineSpacing:(id)sender {
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
if ([sender selectedSegmentIndex] == 0) {
[self.appDelegate.detailViewController changeLineSpacing:@"xs"];
[self.appDelegate.storyPagesViewController changeLineSpacing:@"xs"];
[userPreferences setObject:@"xs" forKey:@"story_line_spacing"];
} else if ([sender selectedSegmentIndex] == 1) {
[self.appDelegate.detailViewController changeLineSpacing:@"small"];
[self.appDelegate.storyPagesViewController changeLineSpacing:@"small"];
[userPreferences setObject:@"small" forKey:@"story_line_spacing"];
} else if ([sender selectedSegmentIndex] == 2) {
[self.appDelegate.detailViewController changeLineSpacing:@"medium"];
[self.appDelegate.storyPagesViewController changeLineSpacing:@"medium"];
[userPreferences setObject:@"medium" forKey:@"story_line_spacing"];
} else if ([sender selectedSegmentIndex] == 3) {
[self.appDelegate.detailViewController changeLineSpacing:@"large"];
[self.appDelegate.storyPagesViewController changeLineSpacing:@"large"];
[userPreferences setObject:@"large" forKey:@"story_line_spacing"];
} else if ([sender selectedSegmentIndex] == 4) {
[self.appDelegate.detailViewController changeLineSpacing:@"xl"];
[self.appDelegate.storyPagesViewController changeLineSpacing:@"xl"];
[userPreferences setObject:@"xl" forKey:@"story_line_spacing"];
}
[userPreferences synchronize];
@ -223,21 +223,21 @@
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
[userPreferences setBool:[sender selectedSegmentIndex] == 0 forKey:@"story_full_screen"];
[userPreferences synchronize];
[self.appDelegate.detailViewController changedFullscreen];
[self.appDelegate.storyPagesViewController changedFullscreen];
}
- (IBAction)changeAutoscroll:(id)sender {
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
[userPreferences setBool:[sender selectedSegmentIndex] == 1 forKey:@"story_autoscroll"];
[userPreferences synchronize];
[self.appDelegate.detailViewController changedAutoscroll];
[self.appDelegate.storyPagesViewController changedAutoscroll];
}
//- (IBAction)changeScrollOrientation:(id)sender {
// NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
// [userPreferences setBool:[sender selectedSegmentIndex] == 0 forKey:@"scroll_stories_horizontally"];
// [userPreferences synchronize];
// [self.appDelegate.detailViewController changedScrollOrientation];
// [self.appDelegate.storyPagesViewController changedScrollOrientation];
//}
- (IBAction)changeTheme:(id)sender {
@ -378,17 +378,17 @@
} else if (indexPath.row == 1) {
[self.appDelegate.storiesCollection toggleStorySaved];
[self.appDelegate.feedDetailViewController reloadData];
[self.appDelegate.detailViewController refreshHeaders];
[self.appDelegate.storyPagesViewController refreshHeaders];
} else if (indexPath.row == 2) {
[self.appDelegate.storiesCollection toggleStoryUnread];
[self.appDelegate.feedDetailViewController reloadData];
[self.appDelegate.detailViewController refreshHeaders];
[self.appDelegate.storyPagesViewController refreshHeaders];
} else if (indexPath.row == 3) {
[self.appDelegate.detailViewController openSendToDialog:self.appDelegate.detailViewController.fontSettingsButton];
[self.appDelegate.storyPagesViewController openSendToDialog:self.appDelegate.storyPagesViewController.fontSettingsButton];
} else if (indexPath.row == 4) {
[self.appDelegate openTrainStory:self.appDelegate.detailViewController.fontSettingsButton];
[self.appDelegate openTrainStory:self.appDelegate.storyPagesViewController.fontSettingsButton];
} else if (indexPath.row == 5) {
[self.appDelegate.detailViewController.currentStoryController openShareDialog];
[self.appDelegate.storyPagesViewController.currentPage openShareDialog];
} else if (indexPath.row == 6) {
[self showFontList];
}
@ -400,8 +400,8 @@
// [self.appDelegate.masterContainerViewController hidePopover];
// }
// } else {
// [self.appDelegate.detailViewController.popoverController dismissPopoverAnimated:YES];
// self.appDelegate.detailViewController.popoverController = nil;
// [self.appDelegate.storyPagesViewController.popoverController dismissPopoverAnimated:YES];
// self.appDelegate.storyPagesViewController.popoverController = nil;
// }
//
// [tableView deselectRowAtIndexPath:indexPath animated:YES];

View file

@ -8,6 +8,10 @@
import UIKit
// NOTE: This isn't currently used, but may be for #1351 (gestures in vertical scrolling).
//#warning("hack: this function is just for testing")
//func storyViewController() -> OriginalStoryViewController {
// let viewController = OriginalStoryViewController()
@ -24,53 +28,53 @@ import UIKit
// return viewController
//}
/// Delegate and data source of the story horizontal page view controller.
class HorizontalPageDelegate: NSObject {
}
extension HorizontalPageDelegate: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let pageViewController = pageViewController as? HorizontalPageViewController, let currentViewController = viewController as? VerticalPageViewController, let detailViewController = pageViewController.detailViewController else {
return nil
}
let pageIndex = (currentViewController.pageIndex ?? -1) - 1
let previousViewController = detailViewController.pageIndexIsValid(pageIndex) ? Storyboards.shared.controller(withIdentifier: .verticalPages) as? VerticalPageViewController : nil
pageViewController.previousController = previousViewController
previousViewController?.horizontalPageViewController = pageViewController
previousViewController?.currentController = detailViewController.makeStoryController(for: pageIndex)
return previousViewController
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let pageViewController = pageViewController as? HorizontalPageViewController, let currentViewController = viewController as? VerticalPageViewController, let detailViewController = pageViewController.detailViewController else {
return nil
}
var pageIndex = (currentViewController.pageIndex ?? -1) + 1
if pageIndex == -1 {
pageIndex = 0
}
let nextViewController = detailViewController.pageIndexIsValid(pageIndex) ? Storyboards.shared.controller(withIdentifier: .verticalPages) as? VerticalPageViewController : nil
pageViewController.nextController = nextViewController
nextViewController?.horizontalPageViewController = pageViewController
nextViewController?.currentController = detailViewController.makeStoryController(for: pageIndex)
return nextViewController
}
}
extension HorizontalPageDelegate: UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
guard let pageViewController = pageViewController as? HorizontalPageViewController, let detailViewController = pageViewController.detailViewController else {
return
}
detailViewController.setStoryFromScroll(false)
}
}
///// Delegate and data source of the story horizontal page view controller.
//class HorizontalPageDelegate: NSObject {
//}
//
//extension HorizontalPageDelegate: UIPageViewControllerDataSource {
// func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
// guard let pageViewController = pageViewController as? HorizontalPageViewController, let currentViewController = viewController as? VerticalPageViewController, let detailViewController = pageViewController.detailViewController else {
// return nil
// }
//
// let pageIndex = (currentViewController.pageIndex ?? -1) - 1
// let previousViewController = detailViewController.pageIndexIsValid(pageIndex) ? Storyboards.shared.controller(withIdentifier: .verticalPages) as? VerticalPageViewController : nil
//
// pageViewController.previousController = previousViewController
// previousViewController?.horizontalPageViewController = pageViewController
// previousViewController?.currentController = detailViewController.makeStoryController(for: pageIndex)
//
// return previousViewController
// }
//
// func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
// guard let pageViewController = pageViewController as? HorizontalPageViewController, let currentViewController = viewController as? VerticalPageViewController, let detailViewController = pageViewController.detailViewController else {
// return nil
// }
//
// var pageIndex = (currentViewController.pageIndex ?? -1) + 1
//
// if pageIndex == -1 {
// pageIndex = 0
// }
//
// let nextViewController = detailViewController.pageIndexIsValid(pageIndex) ? Storyboards.shared.controller(withIdentifier: .verticalPages) as? VerticalPageViewController : nil
//
// pageViewController.nextController = nextViewController
// nextViewController?.horizontalPageViewController = pageViewController
// nextViewController?.currentController = detailViewController.makeStoryController(for: pageIndex)
//
// return nextViewController
// }
//}
//
//extension HorizontalPageDelegate: UIPageViewControllerDelegate {
// func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
// guard let pageViewController = pageViewController as? HorizontalPageViewController, let detailViewController = pageViewController.detailViewController else {
// return
// }
//
// detailViewController.setStoryFromScroll(false)
// }
//}

View file

@ -8,55 +8,59 @@
import UIKit
/// Manages horizontal story pages. An instance of this is contained within `DetailViewController`.
class HorizontalPageViewController: UIPageViewController {
/// Weak reference to owning detail view controller.
weak var detailViewController: DetailViewController?
/// The currently displayed vertical page view controller. Call `setCurrentController(_:direction:animated:completion:)` instead to animate to the page. Shouldn't be `nil`, but could be if not set up yet.
var currentController: VerticalPageViewController? {
get {
return viewControllers?.first as? VerticalPageViewController
}
set {
if let viewController = newValue {
setCurrentController(viewController)
}
}
}
/// The previous vertical page view controller, if it has been requested, otherwise `nil`.
var previousController: VerticalPageViewController?
/// The next vertical page view controller, if it has been requested, otherwise `nil`.
var nextController: VerticalPageViewController?
/// Clear the previous and next vertical page view controllers.
func reset() {
previousController = nil
nextController = nil
}
/// Sets the currently displayed vertical page view controller.
///
/// - Parameter controller: The vertical page view controller to display.
/// - Parameter direction: The navigation direction. Defaults to `.forward`.
/// - Parameter animated: Whether or not to animate it. Defaults to `false`.
/// - Parameter completion: A closure to call when the animation completes. Defaults to `nil`.
func setCurrentController(_ controller: VerticalPageViewController, direction: UIPageViewController.NavigationDirection = .forward, animated: Bool = false, completion: ((Bool) -> Void)? = nil) {
setViewControllers([controller], direction: direction, animated: animated, completion: completion)
}
override func setViewControllers(_ viewControllers: [UIViewController]?, direction: UIPageViewController.NavigationDirection, animated: Bool, completion: ((Bool) -> Void)? = nil) {
guard self.viewControllers != viewControllers else {
print("HorizontalPageViewController setViewControllers: \(String(describing: viewControllers)), ignoring as already set")
return
}
reset()
print("HorizontalPageViewController setViewControllers: \(String(describing: viewControllers)), current: \(String(describing: self.viewControllers))")
super.setViewControllers(viewControllers, direction: direction, animated: animated, completion: completion)
}
}
// NOTE: This isn't currently used, but may be for #1351 (gestures in vertical scrolling).
///// Manages horizontal story pages. An instance of this is contained within `DetailViewController`.
//class HorizontalPageViewController: UIPageViewController {
// /// Weak reference to owning detail view controller.
// weak var detailViewController: DetailViewController?
//
// /// The currently displayed vertical page view controller. Call `setCurrentController(_:direction:animated:completion:)` instead to animate to the page. Shouldn't be `nil`, but could be if not set up yet.
// var currentController: VerticalPageViewController? {
// get {
// return viewControllers?.first as? VerticalPageViewController
// }
// set {
// if let viewController = newValue {
// setCurrentController(viewController)
// }
// }
// }
//
// /// The previous vertical page view controller, if it has been requested, otherwise `nil`.
// var previousController: VerticalPageViewController?
//
// /// The next vertical page view controller, if it has been requested, otherwise `nil`.
// var nextController: VerticalPageViewController?
//
// /// Clear the previous and next vertical page view controllers.
// func reset() {
// previousController = nil
// nextController = nil
// }
//
// /// Sets the currently displayed vertical page view controller.
// ///
// /// - Parameter controller: The vertical page view controller to display.
// /// - Parameter direction: The navigation direction. Defaults to `.forward`.
// /// - Parameter animated: Whether or not to animate it. Defaults to `false`.
// /// - Parameter completion: A closure to call when the animation completes. Defaults to `nil`.
// func setCurrentController(_ controller: VerticalPageViewController, direction: UIPageViewController.NavigationDirection = .forward, animated: Bool = false, completion: ((Bool) -> Void)? = nil) {
// setViewControllers([controller], direction: direction, animated: animated, completion: completion)
// }
//
// override func setViewControllers(_ viewControllers: [UIViewController]?, direction: UIPageViewController.NavigationDirection, animated: Bool, completion: ((Bool) -> Void)? = nil) {
// guard self.viewControllers != viewControllers else {
// print("HorizontalPageViewController setViewControllers: \(String(describing: viewControllers)), ignoring as already set")
// return
// }
//
// reset()
//
// print("HorizontalPageViewController setViewControllers: \(String(describing: viewControllers)), current: \(String(describing: self.viewControllers))")
//
// super.setViewControllers(viewControllers, direction: direction, animated: animated, completion: completion)
// }
//}

View file

@ -42,7 +42,7 @@
@property (nonatomic, strong) DashboardViewController *dashboardViewController;
@property (nonatomic, strong) StoryDetailViewController *storyDetailViewController;
@property (nonatomic, strong) OriginalStoryViewController *originalViewController;
@property (nonatomic, strong) DetailViewController *detailViewController;
@property (nonatomic, strong) StoryPagesViewController *storyPagesViewController;
@property (nonatomic, strong) ShareViewController *shareViewController;
@property (nonatomic, strong) UIView *storyTitlesStub;
@property (readwrite) BOOL storyTitlesOnLeft;
@ -66,7 +66,7 @@
@synthesize dashboardViewController;
@synthesize storyDetailViewController;
@synthesize originalViewController;
@synthesize detailViewController;
@synthesize storyPagesViewController;
@synthesize shareViewController;
@synthesize feedDetailIsVisible;
@synthesize originalViewIsVisible;
@ -112,7 +112,7 @@
self.feedDetailViewController = appDelegate.feedDetailViewController;
self.storyDetailViewController = appDelegate.storyDetailViewController;
self.originalViewController = appDelegate.originalStoryViewController;
self.detailViewController = appDelegate.detailViewController;
self.storyPagesViewController = appDelegate.storyPagesViewController;
self.shareViewController = appDelegate.shareViewController;
// adding dashboardViewController
@ -125,7 +125,7 @@
[self.view addSubview:self.masterNavigationController.view];
[self.masterNavigationController didMoveToParentViewController:self];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.detailViewController];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.storyPagesViewController];
self.storyNavigationController = nav;
self.storyNavigationController.navigationBar.translucent = NO;
self.storyNavigationController.view.layer.masksToBounds = NO;
@ -225,7 +225,7 @@
[self performSelector:@selector(delayedReorientPages:) withObject:networkOperationIdentifier afterDelay:0.5];
} else {
[self.detailViewController reorientPages];
[self.storyPagesViewController reorientPages];
}
}
}];
@ -254,7 +254,7 @@
}
- (void)delayedReorientPages:(NSString *)identifier {
[self.detailViewController reorientPages];
[self.storyPagesViewController reorientPages];
[appDelegate endNetworkOperation:identifier];
}
@ -271,16 +271,16 @@
self.masterNavigationController.view.frame = CGRectMake(0, 0, self.masterWidth, self.view.bounds.size.height);
if (!isCompact) {
if (self.masterNavigationController.topViewController == self.detailViewController) {
if (self.masterNavigationController.topViewController == self.storyPagesViewController) {
[self.masterNavigationController popToViewController:self.feedDetailViewController animated:NO];
}
if (self.storyNavigationController.topViewController != self.detailViewController) {
[self.storyNavigationController pushViewController:self.detailViewController animated:NO];
self.detailViewController.isAnimatedIntoPlace = NO;
if (self.storyNavigationController.topViewController != self.storyPagesViewController) {
[self.storyNavigationController pushViewController:self.storyPagesViewController animated:NO];
self.storyPagesViewController.isAnimatedIntoPlace = NO;
}
[self.detailViewController hidePages];
[self.storyPagesViewController hidePages];
}
}
@ -320,7 +320,7 @@
self.originalNavigationController.navigationBar.barTintColor = [UINavigationBar appearance].barTintColor;
UIView *titleLabel = [appDelegate makeFeedTitle:appDelegate.storiesCollection.activeFeed];
self.detailViewController.navigationItem.titleView = titleLabel;
self.storyPagesViewController.navigationItem.titleView = titleLabel;
}
#pragma mark -
@ -334,7 +334,7 @@
if (self.feedDetailIsVisible) {
[self.feedDetailViewController encodeRestorableStateWithCoder:coder];
[self.detailViewController encodeRestorableStateWithCoder:coder];
[self.storyPagesViewController encodeRestorableStateWithCoder:coder];
}
}
@ -350,7 +350,7 @@
[self transitionToFeedDetail:YES animated:NO];
[self.feedDetailViewController decodeRestorableStateWithCoder:coder];
[self.detailViewController decodeRestorableStateWithCoder:coder];
[self.storyPagesViewController decodeRestorableStateWithCoder:coder];
}
}
@ -371,7 +371,7 @@
[self.appDelegate showPopoverWithViewController:self.appDelegate.userProfileNavigationController contentSize:CGSizeMake(320, 454) barButtonItem:sender];
} else {
CGRect frame = [sender CGRectValue];
[self.appDelegate showPopoverWithViewController:self.appDelegate.userProfileNavigationController contentSize:CGSizeMake(320, 454) sourceView:self.detailViewController.view sourceRect:frame];
[self.appDelegate showPopoverWithViewController:self.appDelegate.userProfileNavigationController contentSize:CGSizeMake(320, 454) sourceView:self.storyPagesViewController.view sourceRect:frame];
}
}
@ -386,7 +386,7 @@
[self.appDelegate showPopoverWithViewController:self.appDelegate.trainerViewController contentSize:CGSizeMake(420, 382) sourceView:cell sourceRect:cell.bounds];
} else {
CGRect frame = [sender CGRectValue];
[self.appDelegate showPopoverWithViewController:self.appDelegate.trainerViewController contentSize:CGSizeMake(420, 382) sourceView:self.detailViewController.view sourceRect:frame];
[self.appDelegate showPopoverWithViewController:self.appDelegate.trainerViewController contentSize:CGSizeMake(420, 382) sourceView:self.storyPagesViewController.view sourceRect:frame];
}
}
@ -407,7 +407,7 @@
}
- (void)syncNextPreviousButtons {
[self.detailViewController setNextPreviousButtons];
[self.storyPagesViewController setNextPreviousButtons];
}
#pragma mark - UIPopoverPresentationControllerDelegate
@ -441,7 +441,7 @@
self.masterNavigationController.view.frame = CGRectMake(0, 0, self.masterWidth, vb.size.height);
self.dashboardViewController.view.frame = CGRectMake(self.masterWidth, 0, vb.size.width - self.masterWidth, vb.size.height);
rightBorder.frame = CGRectMake(self.masterWidth-1, 0, 1, CGRectGetHeight(self.view.bounds));
self.detailViewController.navigationItem.leftBarButtonItem = self.detailViewController.buttonBack;
self.storyPagesViewController.navigationItem.leftBarButtonItem = self.storyPagesViewController.buttonBack;
}
- (void)layoutFeedDetailScreen {
@ -451,11 +451,11 @@
UIInterfaceOrientation orientation = self.appDelegate.window.windowScene.interfaceOrientation;
if (UIInterfaceOrientationIsPortrait(orientation) && !self.storyTitlesOnLeft) {
// add the back button
self.detailViewController.navigationItem.leftBarButtonItem = self.detailViewController.buttonBack;
self.storyPagesViewController.navigationItem.leftBarButtonItem = self.storyPagesViewController.buttonBack;
// set center title
UIView *titleLabel = [appDelegate makeFeedTitle:appDelegate.storiesCollection.activeFeed];
self.detailViewController.navigationItem.titleView = titleLabel;
self.storyPagesViewController.navigationItem.titleView = titleLabel;
if ([[self.masterNavigationController viewControllers] containsObject:self.feedDetailViewController]) {
[self.masterNavigationController popViewControllerAnimated:NO];
@ -475,7 +475,7 @@
vb.size.width, vb.size.height);
} else {
// remove the back button
self.detailViewController.navigationItem.leftBarButtonItem = nil;
self.storyPagesViewController.navigationItem.leftBarButtonItem = nil;
if (![[self.masterNavigationController viewControllers] containsObject:self.feedDetailViewController]) {
[self.masterNavigationController pushViewController:self.feedDetailViewController animated:NO];
@ -508,10 +508,10 @@
self.leftBorder.hidden = NO;
// remove the back button
self.detailViewController.navigationItem.leftBarButtonItem = nil;
self.storyPagesViewController.navigationItem.leftBarButtonItem = nil;
// remove center title
self.detailViewController.navigationItem.titleView = nil;
self.storyPagesViewController.navigationItem.titleView = nil;
[self.masterNavigationController popToRootViewControllerAnimated:NO];
if (![[self.masterNavigationController viewControllers] containsObject:self.feedDetailViewController]) {
@ -525,7 +525,7 @@
self.storyNavigationController.view.frame = CGRectMake(self.masterWidth-1, 0, vb.size.width - self.masterWidth + 1, vb.size.height);
} completion:^(BOOL finished) {
[self.feedDetailViewController checkScroll];
[self.appDelegate.detailViewController refreshPages];
[self.appDelegate.storyPagesViewController refreshPages];
[self.appDelegate adjustStoryDetailWebView];
[self.feedDetailViewController.storyTitlesTable reloadData];
}];
@ -549,11 +549,11 @@
self.leftBorder.hidden = YES;
// add the back button
self.detailViewController.navigationItem.leftBarButtonItem = self.detailViewController.buttonBack;
self.storyPagesViewController.navigationItem.leftBarButtonItem = self.storyPagesViewController.buttonBack;
// set center title
UIView *titleLabel = [appDelegate makeFeedTitle:appDelegate.storiesCollection.activeFeed];
self.detailViewController.navigationItem.titleView = titleLabel;
self.storyPagesViewController.navigationItem.titleView = titleLabel;
[UIView animateWithDuration:NB_DEFAULT_SLIDER_INTERVAL delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.masterNavigationController.view.frame = CGRectMake(-1 * self.masterWidth, 0, self.masterWidth, vb.size.height);
@ -567,7 +567,7 @@
self.feedDetailViewController.view.frame = CGRectMake(0, self.storyTitlesYCoordinate, vb.size.width, vb.size.height - self.storyTitlesYCoordinate);
self.storyTitlesStub.hidden = YES;
[self.feedDetailViewController checkScroll];
[self.appDelegate.detailViewController refreshPages];
[self.appDelegate.storyPagesViewController refreshPages];
[self.appDelegate adjustStoryDetailWebView];
[self.feedDetailViewController.storyTitlesTable reloadData];
}];
@ -605,17 +605,17 @@
// reset the storyDetailViewController components
// self.detailViewController.currentStoryController.webView.hidden = YES;
// self.detailViewController.nextPage.webView.hidden = YES;
self.detailViewController.navigationItem.rightBarButtonItems = nil;
[self.detailViewController hidePages];
self.storyPagesViewController.navigationItem.rightBarButtonItems = nil;
[self.storyPagesViewController hidePages];
NSInteger unreadCount = appDelegate.unreadCount;
if (unreadCount == 0) {
self.detailViewController.circularProgressView.percentage = 1;
self.storyPagesViewController.circularProgressView.percentage = 1;
} else {
self.detailViewController.circularProgressView.percentage = 0;
self.storyPagesViewController.circularProgressView.percentage = 0;
}
UIView *titleLabel = [appDelegate makeFeedTitle:appDelegate.storiesCollection.activeFeed];
self.detailViewController.navigationItem.titleView = titleLabel;
self.storyPagesViewController.navigationItem.titleView = titleLabel;
[self setupStoryTitlesPosition];
}
@ -624,11 +624,11 @@
UIInterfaceOrientation orientation = self.appDelegate.window.windowScene.interfaceOrientation;
if (UIInterfaceOrientationIsPortrait(orientation) && !self.storyTitlesOnLeft) {
// Force the story page control to load.
[detailViewController view];
[storyPagesViewController view];
// CASE: story titles on bottom
if (resetLayout) {
self.detailViewController.navigationItem.leftBarButtonItem = self.detailViewController.buttonBack;
self.detailViewController.navigationItem.rightBarButtonItems = self.feedDetailViewController.navigationItem.rightBarButtonItems;
self.storyPagesViewController.navigationItem.leftBarButtonItem = self.storyPagesViewController.buttonBack;
self.storyPagesViewController.navigationItem.rightBarButtonItems = self.feedDetailViewController.navigationItem.rightBarButtonItems;
[self.view insertSubview:self.feedDetailViewController.view
aboveSubview:self.storyNavigationController.view];
@ -673,7 +673,7 @@
[self interactiveTransitionFromFeedDetail:1];
UIView *titleLabel = [appDelegate makeFeedTitle:appDelegate.storiesCollection.activeFeed];
self.detailViewController.navigationItem.titleView = titleLabel;
self.storyPagesViewController.navigationItem.titleView = titleLabel;
}
self.leftBorder.hidden = NO;
@ -785,7 +785,7 @@
[self.originalViewController viewWillDisappear:YES];
self.originalViewIsVisible = NO;
[self.detailViewController becomeFirstResponder];
[self.storyPagesViewController becomeFirstResponder];
[UIView animateWithDuration:0.35 delay:0
options:UIViewAnimationOptionCurveEaseOut
@ -940,7 +940,7 @@
[self.appDelegate hidePopover];
CGRect vb = [self.view bounds];
self.isSharingStory = YES;
self.detailViewController.traverseView.hidden = YES;
self.storyPagesViewController.traverseView.hidden = YES;
// adding shareViewController
[self.shareNavigationController removeFromParentViewController];
@ -951,9 +951,9 @@
self.shareNavigationController.view.frame = CGRectMake(self.storyNavigationController.view.frame.origin.x,
vb.size.height,
self.detailViewController.view.frame.size.width,
self.storyPagesViewController.view.frame.size.width,
NB_DEFAULT_SHARE_HEIGHT);
[self.detailViewController resizeScrollView];
[self.storyPagesViewController resizeScrollView];
self.shareViewController.view.frame = CGRectMake(0,
0,
@ -974,7 +974,7 @@
[self.appDelegate hidePopover];
CGRect vb = [self.view bounds];
self.isSharingStory = NO;
self.detailViewController.traverseView.hidden = NO;
self.storyPagesViewController.traverseView.hidden = NO;
if ([self.shareViewController.commentField isFirstResponder] && self.keyboardIsShown) {
self.isHidingStory = YES; // the flag allows the keyboard animation to also slide down the share view
@ -1182,8 +1182,8 @@
} completion:^(BOOL finished) {
if (self.keyboardIsShown) {
self.storyNavigationController.view.frame = storyNavigationFrame;
[self.detailViewController.currentStoryController scrolltoComment];
[self.detailViewController resizeScrollView];
[self.storyPagesViewController.currentPage scrolltoComment];
[self.storyPagesViewController resizeScrollView];
} else {
// remove the shareNavigationController after keyboard slides down
if (self.isHidingStory) {

View file

@ -34,6 +34,7 @@
@class FriendsListViewController;
@class FontSettingsViewController;
@class DetailViewController;
@class StoryPagesViewController;
@class StoryDetailViewController;
@class ShareViewController;
@class LoginViewController;
@ -68,12 +69,13 @@ SFSafariViewControllerDelegate> {
UINavigationController *notificationsNavigationController;
UINavigationController *premiumNavigationController;
NBContainerViewController *masterContainerViewController;
DetailViewController *detailViewController;
FirstTimeUserViewController *firstTimeUserViewController;
FirstTimeUserAddSitesViewController *firstTimeUserAddSitesViewController;
FirstTimeUserAddFriendsViewController *firstTimeUserAddFriendsViewController;
FirstTimeUserAddNewsBlurViewController *firstTimeUserAddNewsBlurViewController;
DashboardViewController *dashboardViewController;
FeedsViewController *feedsViewController;
FeedsMenuViewController *feedsMenuViewController;
@ -81,8 +83,8 @@ SFSafariViewControllerDelegate> {
FriendsListViewController *friendsListViewController;
FontSettingsViewController *fontSettingsViewController;
StoryPagesViewController *storyPagesViewController;
StoryDetailViewController *storyDetailViewController;
DetailViewController *detailViewController;
ShareViewController *shareViewController;
LoginViewController *loginViewController;
AddSiteViewController *addSiteViewController;
@ -174,13 +176,14 @@ SFSafariViewControllerDelegate> {
@property (nonatomic) UINavigationController *userProfileNavigationController;
@property (nonatomic) UINavigationController *originalStoryViewNavController;
@property (nonatomic) IBOutlet NBContainerViewController *masterContainerViewController;
@property (nonatomic) IBOutlet DetailViewController *detailViewController;
@property (nonatomic) IBOutlet DashboardViewController *dashboardViewController;
@property (nonatomic) IBOutlet FeedsViewController *feedsViewController;
@property (nonatomic) IBOutlet FeedsMenuViewController *feedsMenuViewController;
@property (nonatomic) IBOutlet FeedDetailViewController *feedDetailViewController;
@property (nonatomic, strong) UINavigationController *feedDetailMenuNavigationController;
@property (nonatomic) IBOutlet FriendsListViewController *friendsListViewController;
@property (nonatomic) IBOutlet DetailViewController *detailViewController;
@property (nonatomic) IBOutlet StoryPagesViewController *storyPagesViewController;
@property (nonatomic) IBOutlet StoryDetailViewController *storyDetailViewController;
@property (nonatomic) IBOutlet LoginViewController *loginViewController;
@property (nonatomic, strong) UINavigationController *addSiteNavigationController;

View file

@ -93,14 +93,15 @@
@synthesize premiumNavigationController;
@synthesize userProfileNavigationController;
@synthesize masterContainerViewController;
@synthesize detailViewController;
@synthesize dashboardViewController;
@synthesize feedsViewController;
@synthesize feedsMenuViewController;
@synthesize feedDetailViewController;
@synthesize friendsListViewController;
@synthesize fontSettingsViewController;
@synthesize storyPagesViewController;
@synthesize storyDetailViewController;
@synthesize detailViewController;
@synthesize shareViewController;
@synthesize loginViewController;
@synthesize addSiteViewController;
@ -270,13 +271,13 @@
self.launchedShortcutItem = nil;
}
if (detailViewController.temporarilyMarkedUnread && [storiesCollection isStoryUnread:activeStory]) {
if (storyPagesViewController.temporarilyMarkedUnread && [storiesCollection isStoryUnread:activeStory]) {
[storiesCollection markStoryRead:activeStory];
[storiesCollection syncStoryAsRead:activeStory];
detailViewController.temporarilyMarkedUnread = NO;
storyPagesViewController.temporarilyMarkedUnread = NO;
[self.feedDetailViewController reloadData];
[self.detailViewController refreshHeaders];
[self.storyPagesViewController refreshHeaders];
}
}
@ -338,8 +339,10 @@
return self.feedsViewController;
} else if ([identifier isEqualToString:@"FeedDetailViewController"]) {
return self.feedDetailViewController;
// } else if ([identifier isEqualToString:@"DetailViewController"]) {
// return self.detailViewController;
} else if ([identifier isEqualToString:@"DetailViewController"]) {
return self.detailViewController;
} else if ([identifier isEqualToString:@"StoryPagesViewController"]) {
return self.storyPagesViewController;
} else if ([identifier isEqualToString:@"SplitViewController"]) {
return self.splitViewController;
} else {
@ -991,12 +994,12 @@
// // that on finger up the link will open.
CGPoint pt = [(NSValue *)sender CGPointValue];
CGRect rect = CGRectMake(pt.x, pt.y, 1, 1);
//// [[OSKPresentationManager sharedInstance] presentActivitySheetForContent:content presentingViewController:vc popoverFromRect:rect inView:self.detailViewController.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES options:options];
//// [[OSKPresentationManager sharedInstance] presentActivitySheetForContent:content presentingViewController:vc popoverFromRect:rect inView:self.storyPagesViewController.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES options:options];
// [[OSKPresentationManager sharedInstance] presentActivitySheetForContent:content
// presentingViewController:vc options:options];
popPC.sourceRect = rect;
popPC.sourceView = self.detailViewController.view;
popPC.sourceView = self.storyPagesViewController.view;
} else {
popPC.sourceRect = [sender frame];
popPC.sourceView = [sender superview];
@ -1039,7 +1042,7 @@
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
[self.masterContainerViewController transitionFromShareView];
[self.detailViewController becomeFirstResponder];
[self.storyPagesViewController becomeFirstResponder];
} else if (!self.showingSafariViewController) {
[self.feedsNavigationController dismissViewControllerAnimated:YES completion:nil];
[self.shareViewController.commentField resignFirstResponder];
@ -1075,6 +1078,7 @@
self.dashboardViewController = [DashboardViewController new];
self.feedsMenuViewController = [FeedsMenuViewController new];
self.friendsListViewController = [FriendsListViewController new];
self.storyPagesViewController = [StoryPagesViewController new];
self.storyDetailViewController = [StoryDetailViewController new];
self.loginViewController = [LoginViewController new];
self.addSiteViewController = [AddSiteViewController new];
@ -1294,7 +1298,7 @@
[self.userTagsViewController view]; // Force viewDidLoad
CGRect frame = [sender CGRectValue];
[self showPopoverWithViewController:self.userTagsViewController contentSize:CGSizeMake(220, 382) sourceView:self.detailViewController.view sourceRect:frame];
[self showPopoverWithViewController:self.userTagsViewController contentSize:CGSizeMake(220, 382) sourceView:self.storyPagesViewController.view sourceRect:frame];
}
#pragma mark - UIPopoverPresentationControllerDelegate
@ -1514,7 +1518,7 @@
detailViewController.navigationItem.titleView = [self makeFeedTitle:storiesCollection.activeFeed];
[self.feedDetailViewController checkScroll];
[self.detailViewController refreshPages];
[self.storyPagesViewController refreshPages];
[self adjustStoryDetailWebView];
[self.feedDetailViewController.storyTitlesTable reloadData];
@ -1644,7 +1648,7 @@
if (showHUD) {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
[self.detailViewController showShareHUD:@"Finding story..."];
[self.storyPagesViewController showShareHUD:@"Finding story..."];
} else {
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.feedDetailViewController.view animated:YES];
HUD.labelText = @"Finding story...";
@ -1918,7 +1922,7 @@
if (showHUD) {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
[self.detailViewController showShareHUD:@"Finding story..."];
[self.storyPagesViewController showShareHUD:@"Finding story..."];
} else {
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.feedDetailViewController.view animated:YES];
HUD.labelText = @"Finding story...";
@ -1927,9 +1931,10 @@
}
- (void)adjustStoryDetailWebView {
[detailViewController updateStoryControllers:^(StoryDetailViewController * _Nonnull storyController) {
[storyController changeWebViewWidth];
}];
// change the web view
[storyPagesViewController.currentPage changeWebViewWidth];
[storyPagesViewController.nextPage changeWebViewWidth];
[storyPagesViewController.previousPage changeWebViewWidth];
}
- (void)calibrateStoryTitles {
@ -2022,9 +2027,9 @@
if (activeStoryLocation >= 0) {
BOOL animated = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad &&
!self.tryFeedCategory);
[self.detailViewController view];
[self.detailViewController.view setNeedsLayout];
[self.detailViewController.view layoutIfNeeded];
[self.storyPagesViewController view];
[self.storyPagesViewController.view setNeedsLayout];
[self.storyPagesViewController.view layoutIfNeeded];
NSDictionary *params = @{@"location" : @(activeStoryLocation), @"animated" : @(animated)};
@ -2035,12 +2040,12 @@
}
}
[MBProgressHUD hideHUDForView:self.detailViewController.view animated:YES];
[MBProgressHUD hideHUDForView:self.storyPagesViewController.view animated:YES];
}
- (void)deferredChangePage:(NSDictionary *)params {
[self.detailViewController changePage:[params[@"location"] integerValue] animated:[params[@"animated"] boolValue]];
[self.detailViewController animateIntoPlace:YES];
[self.storyPagesViewController changePage:[params[@"location"] integerValue] animated:[params[@"animated"] boolValue]];
[self.storyPagesViewController animateIntoPlace:YES];
[self.splitViewController showColumn:UISplitViewControllerColumnSecondary];
[self showDetailViewController:self.detailViewController sender:self];
}
@ -2173,7 +2178,7 @@
config.entersReaderIfAvailable = useReader;
self.safariViewController = [[SFSafariViewController alloc] initWithURL:url configuration:config];
self.safariViewController.delegate = self;
[self.detailViewController setNavigationBarHidden:NO];
[self.storyPagesViewController setNavigationBarHidden:NO];
[feedsNavigationController presentViewController:self.safariViewController animated:YES completion:nil];
}
@ -2193,7 +2198,7 @@
// self.navigationController.view.frame = CGRectMake(self.navigationController.view.frame.origin.x, self.navigationController.view.frame.origin.y, self.isPortrait ? 270.0 : 370.0, self.navigationController.view.frame.size.height);
// }
[self.detailViewController reorientPages];
[self.storyPagesViewController reorientPages];
}
- (void)navigationController:(UINavigationController *)_navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
@ -2227,7 +2232,7 @@
[self.masterContainerViewController transitionFromOriginalView];
} else {
if ([[feedsNavigationController viewControllers] containsObject:originalStoryViewController]) {
[feedsNavigationController popToViewController:detailViewController animated:YES];
[feedsNavigationController popToViewController:storyPagesViewController animated:YES];
}
}
}
@ -2807,57 +2812,63 @@
}
- (void)finishMarkAsRead:(NSDictionary *)story {
for (StoryDetailViewController *page in detailViewController.storyControllers) {
if (!storyPagesViewController.previousPage || !storyPagesViewController.currentPage || !storyPagesViewController.nextPage) return;
for (StoryDetailViewController *page in @[storyPagesViewController.previousPage,
storyPagesViewController.currentPage,
storyPagesViewController.nextPage]) {
if ([[page.activeStory objectForKey:@"story_hash"]
isEqualToString:[story objectForKey:@"story_hash"]] && page.isRecentlyUnread) {
page.isRecentlyUnread = NO;
[detailViewController refreshHeaders];
[storyPagesViewController refreshHeaders];
}
}
}
- (void)finishMarkAsUnread:(NSDictionary *)story {
for (StoryDetailViewController *page in detailViewController.storyControllers) {
if (!storyPagesViewController.previousPage || !storyPagesViewController.currentPage || !storyPagesViewController.nextPage) return;
for (StoryDetailViewController *page in @[storyPagesViewController.previousPage,
storyPagesViewController.currentPage,
storyPagesViewController.nextPage]) {
if ([[page.activeStory objectForKey:@"story_hash"]
isEqualToString:[story objectForKey:@"story_hash"]]) {
page.isRecentlyUnread = YES;
[detailViewController refreshHeaders];
[storyPagesViewController refreshHeaders];
}
}
[detailViewController setNextPreviousButtons];
[storyPagesViewController setNextPreviousButtons];
originalStoryCount += 1;
}
- (void)failedMarkAsUnread:(NSDictionary *)params {
if (![detailViewController failedMarkAsUnread:params]) {
if (![storyPagesViewController failedMarkAsUnread:params]) {
[feedDetailViewController failedMarkAsUnread:params];
[detailViewController failedMarkAsUnread:params];
[storyPagesViewController failedMarkAsUnread:params];
}
[feedDetailViewController reloadData];
}
- (void)finishMarkAsSaved:(NSDictionary *)params {
[detailViewController finishMarkAsSaved:params];
[storyPagesViewController finishMarkAsSaved:params];
[feedDetailViewController finishMarkAsSaved:params];
}
- (void)failedMarkAsSaved:(NSDictionary *)params {
if (![detailViewController failedMarkAsSaved:params]) {
if (![storyPagesViewController failedMarkAsSaved:params]) {
[feedDetailViewController failedMarkAsSaved:params];
[detailViewController failedMarkAsSaved:params];
[storyPagesViewController failedMarkAsSaved:params];
}
[feedDetailViewController reloadData];
}
- (void)finishMarkAsUnsaved:(NSDictionary *)params {
[detailViewController finishMarkAsUnsaved:params];
[storyPagesViewController finishMarkAsUnsaved:params];
[feedDetailViewController finishMarkAsUnsaved:params];
}
- (void)failedMarkAsUnsaved:(NSDictionary *)params {
if (![detailViewController failedMarkAsUnsaved:params]) {
if (![storyPagesViewController failedMarkAsUnsaved:params]) {
[feedDetailViewController failedMarkAsUnsaved:params];
[detailViewController failedMarkAsUnsaved:params];
[storyPagesViewController failedMarkAsUnsaved:params];
}
[feedDetailViewController reloadData];
}
@ -3021,7 +3032,7 @@
} else {
CGRect frame = [sender CGRectValue];
[self showPopoverWithViewController:viewController contentSize:contentSize sourceView:self.detailViewController.view sourceRect:frame];
[self showPopoverWithViewController:viewController contentSize:contentSize sourceView:self.storyPagesViewController.view sourceRect:frame];
}
}
@ -3553,7 +3564,7 @@
if (self.trainerViewController.isViewLoaded && self.trainerViewController.view.window) {
view = self.trainerViewController;
} else {
view = self.detailViewController.currentStoryController;
view = self.storyPagesViewController.currentPage;
}
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
@ -3583,7 +3594,7 @@
[authors setObject:[NSNumber numberWithInt:authorScore] forKey:author];
[feedClassifiers setObject:authors forKey:@"authors"];
[storiesCollection.activeClassifiers setObject:feedClassifiers forKey:feedId];
[self.detailViewController refreshHeaders];
[self.storyPagesViewController refreshHeaders];
[self.trainerViewController refresh];
NSString *urlString = [NSString stringWithFormat:@"%@/classifier/save",
@ -3627,7 +3638,7 @@
[tags setObject:[NSNumber numberWithInt:tagScore] forKey:tag];
[feedClassifiers setObject:tags forKey:@"tags"];
[storiesCollection.activeClassifiers setObject:feedClassifiers forKey:feedId];
[self.detailViewController refreshHeaders];
[self.storyPagesViewController refreshHeaders];
[self.trainerViewController refresh];
NSString *urlString = [NSString stringWithFormat:@"%@/classifier/save",
@ -3675,7 +3686,7 @@
[titles setObject:[NSNumber numberWithInteger:titleScore] forKey:title];
[feedClassifiers setObject:titles forKey:@"titles"];
[storiesCollection.activeClassifiers setObject:feedClassifiers forKey:feedId];
[self.detailViewController refreshHeaders];
[self.storyPagesViewController refreshHeaders];
[self.trainerViewController refresh];
NSString *urlString = [NSString stringWithFormat:@"%@/classifier/save",
@ -3717,7 +3728,7 @@
[feeds setObject:[NSNumber numberWithInt:feedScore] forKey:feedId];
[feedClassifiers setObject:feeds forKey:@"feeds"];
[storiesCollection.activeClassifiers setObject:feedClassifiers forKey:feedId];
[self.detailViewController refreshHeaders];
[self.storyPagesViewController refreshHeaders];
[self.trainerViewController refresh];
NSString *urlString = [NSString stringWithFormat:@"%@/classifier/save",
@ -3745,7 +3756,7 @@
if (self.trainerViewController.isViewLoaded && self.trainerViewController.view.window) {
view = self.trainerViewController;
} else {
view = self.detailViewController.currentStoryController;
view = self.storyPagesViewController.currentPage;
}
if (httpResponse.statusCode == 503) {
return [view informError:@"In maintenance mode"];

View file

@ -336,7 +336,7 @@
# pragma mark Share Story
- (IBAction)doShareThisStory:(id)sender {
[appDelegate.detailViewController showShareHUD:@"Sharing"];
[appDelegate.storyPagesViewController showShareHUD:@"Sharing"];
NSString *urlString = [NSString stringWithFormat:@"%@/social/share_story",
self.appDelegate.url];
NSMutableDictionary *params = [NSMutableDictionary dictionary];
@ -392,15 +392,15 @@
[self replaceStory:[results objectForKey:@"story"] withReplyId:nil];
[appDelegate.feedDetailViewController redrawUnreadStory];
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.currentStoryController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.currentPage.view animated:NO];
}
# pragma mark
# pragma mark Reply to Story
- (IBAction)doReplyToComment:(id)sender {
[appDelegate.detailViewController showShareHUD:@"Replying"];
[appDelegate.storyPagesViewController showShareHUD:@"Replying"];
NSString *comments = commentField.text;
if ([comments length] == 0) {
return;
@ -442,11 +442,11 @@
}
- (void)requestFailed:(NSError *)error statusCode:(NSInteger)statusCode {
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.currentStoryController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.currentPage.view animated:NO];
NSLog(@"Error: %@", error);
[appDelegate.detailViewController.currentStoryController informError:error statusCode:statusCode];
[appDelegate.storyPagesViewController.currentPage informError:error statusCode:statusCode];
}
- (void)replaceStory:(NSDictionary *)newStory withReplyId:(NSString *)replyId {
@ -455,7 +455,7 @@
// update the current story and the activeFeedStories
appDelegate.activeStory = newStoryParsed;
[appDelegate.detailViewController.currentStoryController setActiveStoryAtIndex:-1];
[appDelegate.storyPagesViewController.currentPage setActiveStoryAtIndex:-1];
NSMutableArray *newActiveFeedStories = [[NSMutableArray alloc] init];
@ -473,7 +473,7 @@
appDelegate.storiesCollection.activeFeedStories = [NSArray arrayWithArray:newActiveFeedStories];
self.commentField.text = nil;
[appDelegate.detailViewController.currentStoryController refreshComments:replyId];
[appDelegate.storyPagesViewController.currentPage refreshComments:replyId];
[appDelegate changeActiveFeedDetailRow];
}

View file

@ -65,7 +65,8 @@
}
- (NSString *)description {
return [NSString stringWithFormat:@"%@: page %@, '%@'", [super description], @(pageIndex), activeStory[@"story_title"]];
NSString *page = appDelegate.storyPagesViewController.currentPage == self ? @"currentPage" : appDelegate.storyPagesViewController.previousPage == self ? @"previousPage" : appDelegate.storyPagesViewController.nextPage == self ? @"nextPage" : @"unattached page";
return [NSString stringWithFormat:@"%@", page];
}
- (void)viewDidLoad {
@ -95,7 +96,7 @@
self.webView.allowsLinkPreview = YES;
// self.webView.multipleTouchEnabled = NO;
[self.webView.scrollView setAlwaysBounceVertical:appDelegate.detailViewController.isHorizontal];
[self.webView.scrollView setAlwaysBounceVertical:appDelegate.storyPagesViewController.isHorizontal];
[self.webView.scrollView setDelaysContentTouches:NO];
[self.webView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal];
[self.webView.scrollView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth |
@ -197,7 +198,7 @@
[self.webView evaluateJavaScript:[NSString stringWithFormat:@"linkAt(%li, %li, 'id');", (long)pt.x,(long)pt.y] completionHandler:^(NSString *identifier, NSError *error) {
[self.webView evaluateJavaScript:[NSString stringWithFormat:@"linkAt(%li, %li, 'outerHTML');", (long)pt.x,(long)pt.y] completionHandler:^(NSString *outerHTML, NSError *error) {
if ([identifier isEqualToString:@"NB-story"] || ![outerHTML containsString:@"NB-"]) {
[self.appDelegate.detailViewController tappedStory];
[self.appDelegate.storyPagesViewController tappedStory];
}
}];
}];
@ -207,7 +208,7 @@
// Ignore links, videos, and iframes (e.g. embedded YouTube videos).
if (![@[@"A", @"VIDEO", @"IFRAME"] containsObject:tagName]) {
[self.appDelegate.detailViewController tappedStory];
[self.appDelegate.storyPagesViewController tappedStory];
}
}];
}
@ -257,7 +258,7 @@
}
inDoubleTap = NO;
[self performSelector:@selector(deferredEnableScrolling) withObject:nil afterDelay:0.0];
appDelegate.detailViewController.autoscrollActive = NO;
appDelegate.storyPagesViewController.autoscrollActive = NO;
}
}
@ -266,8 +267,8 @@
return;
}
appDelegate.detailViewController.forceNavigationBarShown = gestureRecognizer.scale < 1;
[appDelegate.detailViewController changedFullscreen];
appDelegate.storyPagesViewController.forceNavigationBarShown = gestureRecognizer.scale < 1;
[appDelegate.storyPagesViewController changedFullscreen];
}
- (void)screenEdgeSwipe:(UITapGestureRecognizer *)gestureRecognizer {
@ -276,7 +277,7 @@
isEqualToString:@"pop_to_story_list"];
// if (swipeEnabled && gestureRecognizer.state == UIGestureRecognizerStateBegan) {
// [appDelegate.detailViewController setNavigationBarHidden:NO];
// [appDelegate.storyPagesViewController setNavigationBarHidden:NO];
// }
if (swipeEnabled && gestureRecognizer.state == UIGestureRecognizerStateEnded) {
@ -358,7 +359,7 @@
UIInterfaceOrientation orientation = self.view.window.windowScene.interfaceOrientation;
[super viewWillLayoutSubviews];
dispatch_async(dispatch_get_main_queue(), ^{
[self.appDelegate.detailViewController layoutForInterfaceOrientation:orientation];
[self.appDelegate.storyPagesViewController layoutForInterfaceOrientation:orientation];
[self changeWebViewWidth];
[self drawFeedGradient];
});
@ -612,7 +613,7 @@
dispatch_async(dispatch_get_main_queue(), ^{
// NSLog(@"Drawing Story: %@", [self.activeStory objectForKey:@"story_title"]);
[self loadHTMLString:htmlTopAndBottom];
[self.appDelegate.detailViewController setTextButton:(StoryDetailViewController *)self];
[self.appDelegate.storyPagesViewController setTextButton:(StoryDetailViewController *)self];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
@ -623,14 +624,14 @@
}
- (void)drawFeedGradient {
BOOL shouldHideStatusBar = appDelegate.detailViewController.shouldHideStatusBar;
BOOL shouldHideStatusBar = appDelegate.storyPagesViewController.shouldHideStatusBar;
CGFloat yOffset = -1;
NSString *feedIdStr = [NSString stringWithFormat:@"%@",
[self.activeStory
objectForKey:@"story_feed_id"]];
NSDictionary *feed = [appDelegate getFeed:feedIdStr];
if (appDelegate.detailViewController.currentlyTogglingNavigationBar && !appDelegate.detailViewController.isNavigationBarHidden) {
if (appDelegate.storyPagesViewController.currentlyTogglingNavigationBar && !appDelegate.storyPagesViewController.isNavigationBarHidden) {
yOffset -= 25;
}
@ -661,11 +662,11 @@
}
[self.webView insertSubview:feedTitleGradient aboveSubview:self.webView.scrollView];
if (appDelegate.detailViewController.view.safeAreaInsets.top > 0.0 && [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && shouldHideStatusBar) {
feedTitleGradient.alpha = appDelegate.detailViewController.isNavigationBarHidden ? 1 : 0;
if (appDelegate.storyPagesViewController.view.safeAreaInsets.top > 0.0 && [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && shouldHideStatusBar) {
feedTitleGradient.alpha = appDelegate.storyPagesViewController.isNavigationBarHidden ? 1 : 0;
[UIView animateWithDuration:0.3 animations:^{
self.feedTitleGradient.alpha = self.appDelegate.detailViewController.isNavigationBarHidden ? 0 : 1;
self.feedTitleGradient.alpha = self.appDelegate.storyPagesViewController.isNavigationBarHidden ? 0 : 1;
}];
}
}
@ -1326,8 +1327,8 @@
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqual:@"contentOffset"]) {
BOOL isHorizontal = appDelegate.detailViewController.isHorizontal;
BOOL isNavBarHidden = appDelegate.detailViewController.isNavigationBarHidden;
BOOL isHorizontal = appDelegate.storyPagesViewController.isHorizontal;
BOOL isNavBarHidden = appDelegate.storyPagesViewController.isNavigationBarHidden;
if (self.webView.scrollView.contentOffset.y < (-1 * self.feedTitleGradient.frame.size.height + 1 + self.webView.scrollView.verticalScrollIndicatorInsets.top)) {
// Pulling
@ -1370,15 +1371,15 @@
}
}
if (appDelegate.detailViewController.currentStoryController != self) return;
if (appDelegate.storyPagesViewController.currentPage != self) return;
int webpageHeight = self.webView.scrollView.contentSize.height;
int viewportHeight = self.view.frame.size.height;
int topPosition = self.webView.scrollView.contentOffset.y;
CGFloat bottomInset = appDelegate.detailViewController.view.safeAreaInsets.bottom;
CGFloat bottomInset = appDelegate.storyPagesViewController.view.safeAreaInsets.bottom;
int safeBottomMargin = (-1 * bottomInset / 2) + 20;
int safeBottomMargin = -1 * bottomInset / 2;
int bottomPosition = webpageHeight - topPosition - viewportHeight;
BOOL singlePage = webpageHeight - 200 <= viewportHeight;
BOOL atBottom = bottomPosition < 150;
@ -1389,75 +1390,73 @@
hasScrolled = YES;
}
if (!isNavBarHidden && self.canHideNavigationBar && !nearTop && appDelegate.detailViewController.autoscrollActive) {
[appDelegate.detailViewController setNavigationBarHidden:YES];
if (!isNavBarHidden && self.canHideNavigationBar && !nearTop && appDelegate.storyPagesViewController.autoscrollActive) {
[appDelegate.storyPagesViewController setNavigationBarHidden:YES];
}
if (!atTop && !atBottom && !singlePage) {
BOOL traversalVisible = appDelegate.detailViewController.traverseView.alpha > 0;
BOOL traversalVisible = appDelegate.storyPagesViewController.traverseView.alpha > 0;
// Hide
[UIView animateWithDuration:.3 delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
self.appDelegate.detailViewController.traverseView.alpha = 0;
self.appDelegate.storyPagesViewController.traverseView.alpha = 0;
if (traversalVisible) {
[self.appDelegate.detailViewController hideAutoscrollImmediately];
[self.appDelegate.storyPagesViewController hideAutoscrollImmediately];
}
} completion:^(BOOL finished) {
}];
} else if (singlePage || !isHorizontal) {
appDelegate.detailViewController.traverseView.alpha = 1;
appDelegate.storyPagesViewController.traverseView.alpha = 1;
// NSLog(@" ---> Bottom position: %d", bottomPosition);
if (bottomPosition >= 0 || !isHorizontal) {
[appDelegate.detailViewController adjustTraversePosition:safeBottomMargin];
appDelegate.storyPagesViewController.traverseBottomConstraint.constant = safeBottomMargin;
} else {
if (webpageHeight > 0) {
[appDelegate.detailViewController adjustTraversePosition:viewportHeight - (webpageHeight - topPosition) + safeBottomMargin];
appDelegate.storyPagesViewController.traverseBottomConstraint.constant = viewportHeight - (webpageHeight - topPosition) + safeBottomMargin;
} else {
[appDelegate.detailViewController adjustTraversePosition:safeBottomMargin];
appDelegate.storyPagesViewController.traverseBottomConstraint.constant = safeBottomMargin;
}
}
} else if (!singlePage && (atTop && !atBottom)) {
// Pin to bottom of viewport, regardless of scrollview
appDelegate.detailViewController.traversePinned = YES;
appDelegate.detailViewController.traverseFloating = NO;
[appDelegate.detailViewController.view layoutIfNeeded];
appDelegate.storyPagesViewController.traversePinned = YES;
appDelegate.storyPagesViewController.traverseFloating = NO;
[appDelegate.storyPagesViewController.view layoutIfNeeded];
[appDelegate.detailViewController adjustTraversePosition:safeBottomMargin];
appDelegate.storyPagesViewController.traverseBottomConstraint.constant = safeBottomMargin;
[UIView animateWithDuration:.3 delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[self.appDelegate.detailViewController.view layoutIfNeeded];
self.appDelegate.detailViewController.traverseView.alpha = 1;
[self.appDelegate.storyPagesViewController.view layoutIfNeeded];
self.appDelegate.storyPagesViewController.traverseView.alpha = 1;
} completion:nil];
} else if (appDelegate.detailViewController.traverseView.alpha == 1 &&
appDelegate.detailViewController.traversePinned) {
} else if (appDelegate.storyPagesViewController.traverseView.alpha == 1 &&
appDelegate.storyPagesViewController.traversePinned) {
// Scroll with bottom of scrollview, but smoothly
appDelegate.detailViewController.traverseFloating = YES;
[appDelegate.detailViewController.view layoutIfNeeded];
appDelegate.storyPagesViewController.traverseFloating = YES;
[appDelegate.storyPagesViewController.view layoutIfNeeded];
[appDelegate.detailViewController adjustTraversePosition:safeBottomMargin];
appDelegate.storyPagesViewController.traverseBottomConstraint.constant = safeBottomMargin;
[UIView animateWithDuration:.3 delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[self.appDelegate.detailViewController.view layoutIfNeeded];
[self.appDelegate.storyPagesViewController.view layoutIfNeeded];
} completion:^(BOOL finished) {
self.appDelegate.detailViewController.traversePinned = NO;
self.appDelegate.storyPagesViewController.traversePinned = NO;
}];
} else {
// Scroll with bottom of scrollview
appDelegate.detailViewController.traversePinned = NO;
appDelegate.detailViewController.traverseFloating = YES;
appDelegate.detailViewController.traverseView.alpha = 1;
[appDelegate.detailViewController adjustTraversePosition:viewportHeight - (webpageHeight - topPosition) + safeBottomMargin];
appDelegate.storyPagesViewController.traversePinned = NO;
appDelegate.storyPagesViewController.traverseFloating = YES;
appDelegate.storyPagesViewController.traverseView.alpha = 1;
appDelegate.storyPagesViewController.traverseBottomConstraint.constant = viewportHeight - (webpageHeight - topPosition) + safeBottomMargin;
}
[self storeScrollPosition:YES];
[appDelegate.detailViewController allowPagingUp:atTop down:atBottom];
}
}
@ -1832,7 +1831,7 @@
appDelegate.tryFeedCategory &&
([[self.activeStory objectForKey:@"id"] isEqualToString:appDelegate.tryFeedStoryId] ||
[[self.activeStory objectForKey:@"story_hash"] isEqualToString:appDelegate.tryFeedStoryId])) {
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.view animated:YES];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.view animated:YES];
if ([appDelegate.tryFeedCategory isEqualToString:@"comment_like"] ||
[appDelegate.tryFeedCategory isEqualToString:@"comment_reply"]) {
@ -1905,7 +1904,7 @@
}
- (BOOL)canHideNavigationBar {
if (!appDelegate.detailViewController.allowFullscreen) {
if (!appDelegate.storyPagesViewController.allowFullscreen) {
NSLog(@"canHideNavigationBar: no, toggle is off"); // log
return NO;
}
@ -1924,7 +1923,7 @@
#pragma mark Actions
- (void)toggleLikeComment:(BOOL)likeComment {
[appDelegate.detailViewController showShareHUD:@"Favoriting"];
[appDelegate.storyPagesViewController showShareHUD:@"Favoriting"];
NSString *urlString;
if (likeComment) {
urlString = [NSString stringWithFormat:@"%@/social/like_comment",
@ -1970,8 +1969,8 @@
appDelegate.storiesCollection.activeFeedStories = [NSArray arrayWithArray:newActiveFeedStories];
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.currentStoryController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.currentPage.view animated:NO];
[self refreshComments:@"like"];
}
@ -1979,8 +1978,8 @@
- (void)requestFailed:(NSError *)error statusCode:(NSInteger)statusCode {
NSLog(@"Error in story detail: %@", error);
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.currentStoryController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.currentPage.view animated:NO];
[self informError:error statusCode:statusCode];
}
@ -2114,7 +2113,7 @@
UIPopoverPresentationController *popover = [alert popoverPresentationController];
popover.sourceRect = CGRectMake(pt.x, pt.y, 1, 1);
popover.sourceView = self.appDelegate.detailViewController.view;
popover.sourceView = self.appDelegate.storyPagesViewController.view;
[self presentViewController:alert animated:YES completion:nil];
}];
}];
@ -2129,7 +2128,7 @@
if (!href || ![href length]) return;
NSValue *ptValue = [NSValue valueWithCGPoint:pt];
[self.appDelegate showSendTo:self.appDelegate.detailViewController
[self.appDelegate showSendTo:self.appDelegate.storyPagesViewController
sender:ptValue
withUrl:url
authorName:nil
@ -2142,7 +2141,7 @@
}
- (CGPoint)pointForEvent:(NSNotification*)notification {
if (self != appDelegate.detailViewController.currentStoryController) return CGPointZero;
if (self != appDelegate.storyPagesViewController.currentPage) return CGPointZero;
if (!self.view.window) return CGPointZero;
CGPoint pt;
@ -2168,10 +2167,10 @@
}
- (CGPoint)pointForGesture:(UIGestureRecognizer *)gestureRecognizer {
if (self != appDelegate.detailViewController.currentStoryController) return CGPointZero;
if (self != appDelegate.storyPagesViewController.currentPage) return CGPointZero;
if (!self.view.window) return CGPointZero;
CGPoint pt = [gestureRecognizer locationInView:appDelegate.detailViewController.currentStoryController.webView];
CGPoint pt = [gestureRecognizer locationInView:appDelegate.storyPagesViewController.currentPage.webView];
// convert point from view to HTML coordinate system
// CGPoint offset = [self.webView scrollOffset];
@ -2188,7 +2187,7 @@
- (void)fetchImage:(NSURL *)url copy:(BOOL)copy save:(BOOL)save {
[MBProgressHUD hideHUDForView:self.webView animated:YES];
[appDelegate.detailViewController showShareHUD:copy ?
[appDelegate.storyPagesViewController showShareHUD:copy ?
@"Copying..." : @"Saving..."];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
@ -2229,7 +2228,7 @@
# pragma mark Subscribing to blurblog
- (void)subscribeToBlurblog {
[appDelegate.detailViewController showShareHUD:@"Following"];
[appDelegate.storyPagesViewController showShareHUD:@"Following"];
NSString *urlString = [NSString stringWithFormat:@"%@/social/follow",
self.appDelegate.url];
NSMutableDictionary *params = [NSMutableDictionary dictionary];
@ -2246,14 +2245,14 @@
}
- (void)finishSubscribeToBlurblog:(NSDictionary *)results {
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.view animated:NO];
self.storyHUD = [MBProgressHUD showHUDAddedTo:self.webView animated:YES];
self.storyHUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]];
self.storyHUD.mode = MBProgressHUDModeCustomView;
self.storyHUD.removeFromSuperViewOnHide = YES;
self.storyHUD.labelText = @"Followed";
[self.storyHUD hide:YES afterDelay:1];
appDelegate.detailViewController.navigationItem.leftBarButtonItem = nil;
appDelegate.storyPagesViewController.navigationItem.leftBarButtonItem = nil;
[appDelegate reloadFeedsView:NO];
}
@ -2298,7 +2297,7 @@
- (void)flashCheckmarkHud:(NSString *)messageType {
[MBProgressHUD hideHUDForView:self.webView animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.detailViewController.currentStoryController.view animated:NO];
[MBProgressHUD hideHUDForView:appDelegate.storyPagesViewController.currentPage.view animated:NO];
self.storyHUD = [MBProgressHUD showHUDAddedTo:self.webView animated:YES];
self.storyHUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]];
self.storyHUD.mode = MBProgressHUDModeCustomView;
@ -2495,7 +2494,7 @@
- (void)showStoryView {
self.inTextView = NO;
[MBProgressHUD hideHUDForView:self.webView animated:YES];
[appDelegate.detailViewController setTextButton:(StoryDetailViewController *)self];
[appDelegate.storyPagesViewController setTextButton:(StoryDetailViewController *)self];
[self drawStory];
}
@ -2503,8 +2502,8 @@
if (!self.activeStoryId || !self.activeStory) return;
self.inTextView = YES;
// NSLog(@"Fetching Text: %@", [self.activeStory objectForKey:@"story_title"]);
if (self.activeStory == appDelegate.detailViewController.currentStoryController.activeStory) {
[self.appDelegate.detailViewController showFetchingTextNotifier];
if (self.activeStory == appDelegate.storyPagesViewController.currentPage.activeStory) {
[self.appDelegate.storyPagesViewController showFetchingTextNotifier];
}
NSString *storyId = [self.activeStory objectForKey:@"id"];
@ -2518,21 +2517,21 @@
}
- (void)failedFetchText {
[self.appDelegate.detailViewController hideNotifier];
[self.appDelegate.storyPagesViewController hideNotifier];
[MBProgressHUD hideHUDForView:self.webView animated:YES];
if (self.activeStory == appDelegate.detailViewController.currentStoryController.activeStory) {
if (self.activeStory == appDelegate.storyPagesViewController.currentPage.activeStory) {
[self informError:@"Could not fetch text"];
}
self.inTextView = NO;
[appDelegate.detailViewController setTextButton:(StoryDetailViewController *)self];
[appDelegate.storyPagesViewController setTextButton:(StoryDetailViewController *)self];
}
- (void)finishFetchText:(NSString *)text storyId:(NSString *)storyId {
if (![storyId isEqualToString:[self.activeStory objectForKey:@"id"]]) {
[self.appDelegate.detailViewController hideNotifier];
[self.appDelegate.storyPagesViewController hideNotifier];
[MBProgressHUD hideHUDForView:self.webView animated:YES];
self.inTextView = NO;
[appDelegate.detailViewController setTextButton:(StoryDetailViewController *)self];
[appDelegate.storyPagesViewController setTextButton:(StoryDetailViewController *)self];
return;
}
@ -2543,7 +2542,7 @@
}
self.activeStory = newActiveStory;
[self.appDelegate.detailViewController hideNotifier];
[self.appDelegate.storyPagesViewController hideNotifier];
[MBProgressHUD hideHUDForView:self.webView animated:YES];
self.inTextView = YES;
@ -2557,9 +2556,9 @@
if (!self.activeStoryId || !self.activeStory) return;
self.inTextView = YES;
// NSLog(@"Fetching Changes: %@", [self.activeStory objectForKey:@"story_title"]);
if (self.activeStory == appDelegate.detailViewController.currentStoryController.activeStory) {
if (self.activeStory == appDelegate.storyPagesViewController.currentPage.activeStory) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.appDelegate.detailViewController showFetchingTextNotifier];
[self.appDelegate.storyPagesViewController showFetchingTextNotifier];
});
}
@ -2577,13 +2576,13 @@
}
- (void)failedFetchStoryChanges:(NSError *)error {
[self.appDelegate.detailViewController hideNotifier];
[self.appDelegate.storyPagesViewController hideNotifier];
[MBProgressHUD hideHUDForView:self.webView animated:YES];
if (self.activeStory == appDelegate.detailViewController.currentStoryController.activeStory) {
if (self.activeStory == appDelegate.storyPagesViewController.currentPage.activeStory) {
[self informError:@"Could not fetch changes"];
}
self.inTextView = NO;
[appDelegate.detailViewController setTextButton:(StoryDetailViewController *)self];
[appDelegate.storyPagesViewController setTextButton:(StoryDetailViewController *)self];
}
- (void)finishFetchStoryChanges:(NSDictionary *)results storyId:(NSString *)storyId {
@ -2593,10 +2592,10 @@
}
if (![storyId isEqualToString:self.activeStory[@"id"]]) {
[self.appDelegate.detailViewController hideNotifier];
[self.appDelegate.storyPagesViewController hideNotifier];
[MBProgressHUD hideHUDForView:self.webView animated:YES];
self.inTextView = NO;
[appDelegate.detailViewController setTextButton:(StoryDetailViewController *)self];
[appDelegate.storyPagesViewController setTextButton:(StoryDetailViewController *)self];
return;
}
@ -2608,7 +2607,7 @@
}
self.activeStory = newActiveStory;
[self.appDelegate.detailViewController hideNotifier];
[self.appDelegate.storyPagesViewController hideNotifier];
[MBProgressHUD hideHUDForView:self.webView animated:YES];
self.inTextView = YES;

View file

@ -1,5 +1,5 @@
//
// DetailObjCViewController.h
// StoryPagesObjCViewController.h
// NewsBlur
//
// Created by Samuel Clay on 11/2/12.
@ -14,7 +14,7 @@
@class StoryDetailViewController;
@interface DetailObjCViewController : BaseViewController
@interface StoryPagesObjCViewController : BaseViewController
<UIScrollViewDelegate, UIPopoverControllerDelegate, UIPopoverPresentationControllerDelegate, UIGestureRecognizerDelegate> {
NewsBlurAppDelegate *appDelegate;
THCircularProgressView *circularProgressView;
@ -38,11 +38,12 @@
}
@property (nonatomic, strong) NewsBlurAppDelegate *appDelegate;
//@property (nonatomic) StoryDetailViewController *currentPage;
//@property (nonatomic) StoryDetailViewController *nextPage;
//@property (nonatomic) StoryDetailViewController *previousPage;
@property (nonatomic) StoryDetailViewController *currentPage;
@property (nonatomic) StoryDetailViewController *nextPage;
@property (nonatomic) StoryDetailViewController *previousPage;
@property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
@property (nonatomic, strong) IBOutlet UIPageControl *pageControl;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *scrollViewTopConstraint;
@property (weak, nonatomic) IBOutlet UIView *autoscrollView;
@property (weak, nonatomic) IBOutlet UIImageView *autoscrollBackgroundImageView;
@ -50,8 +51,7 @@
@property (weak, nonatomic) IBOutlet UIButton *autoscrollPauseResumeButton;
@property (weak, nonatomic) IBOutlet UIButton *autoscrollSlowerButton;
@property (weak, nonatomic) IBOutlet UIButton *autoscrollFasterButton;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *autoscrollTopContainerBottomConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *autoscrollBottomContainerBottomConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *autoscrollBottomConstraint;
@property (nonatomic, strong) IBOutlet UIActivityIndicatorView *loadingIndicator;
@property (nonatomic) IBOutlet UIImageView *textStorySendBackgroundImageView;
@ -63,8 +63,8 @@
@property (nonatomic) IBOutlet UIButton *buttonSend;
@property (nonatomic) UIBarButtonItem *buttonBack;
@property (nonatomic) IBOutlet UIBarButtonItem *buttonAction;
@property (nonatomic) IBOutlet UIView *dividerView;
//@property (nonatomic) IBOutlet NSLayoutConstraint *dividerViewBottomConstraint;
@property (nonatomic) IBOutlet UIView *bottomSize;
@property (nonatomic) IBOutlet NSLayoutConstraint *bottomSizeHeightConstraint;
@property (nonatomic) IBOutlet UIBarButtonItem * spacerBarButton;
@property (nonatomic) IBOutlet UIBarButtonItem * spacer2BarButton;
@property (nonatomic) IBOutlet UIBarButtonItem * spacer3BarButton;
@ -76,15 +76,15 @@
@property (nonatomic) IBOutlet UIBarButtonItem *originalStoryButton;
@property (nonatomic, strong) IBOutlet UIBarButtonItem *subscribeButton;
@property (nonatomic) IBOutlet UIImageView *dragBarImageView;
@property (nonatomic) IBOutlet NSLayoutConstraint *traverseTopContainerBottomConstraint;
@property (nonatomic) IBOutlet NSLayoutConstraint *traverseBottomContainerBottomConstraint;
@property (nonatomic) IBOutlet NSLayoutConstraint *traverseBottomConstraint;
@property (nonatomic) IBOutlet NSLayoutConstraint *scrollBottomConstraint;
@property (nonatomic) IBOutlet UIView *statusBarBackgroundView;
@property (nonatomic) BOOL autoscrollAvailable;
@property (nonatomic) BOOL autoscrollActive;
@property (nonatomic) NSTimeInterval autoscrollSpeed;
@property (readwrite) BOOL traversePinned;
@property (readwrite) BOOL traverseFloating;
//@property (readwrite) CGFloat inTouchMove;
@property (readwrite) CGFloat inTouchMove;
@property (assign) BOOL isDraggingScrollview;
@property (assign) BOOL isAnimatedIntoPlace;
@property (assign) BOOL waitingForNextUnreadFromServer;
@ -97,21 +97,19 @@
@property (nonatomic, readonly) BOOL allowFullscreen;
@property (nonatomic) BOOL forceNavigationBarShown;
@property (nonatomic) BOOL currentlyTogglingNavigationBar;
@property (nonatomic, readonly) BOOL isPortraitOrientation;
@property (nonatomic, readonly) BOOL isHorizontal;
@property (nonatomic) BOOL temporarilyMarkedUnread;
@property (nonatomic, readonly) NSInteger storiesCount;
- (void)resizeScrollView;
- (BOOL)pageIndexIsValid:(NSInteger)pageIndex;
- (void)applyNewIndex:(NSInteger)newIndex pageController:(StoryDetailViewController *)pageController;
- (void)layoutForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
- (void)updateStatusBarState;
- (void)setNavigationBarHidden:(BOOL)hide;
- (void)setNavigationBarHidden:(BOOL)hide alsoTraverse:(BOOL)alsoTraverse;
//- (void)adjustDragBar:(UIInterfaceOrientation)orientation;
- (void)adjustDragBar:(UIInterfaceOrientation)orientation;
- (void)transitionFromFeedDetail;
- (void)resetPages;
- (void)hidePages;
- (void)refreshPages;
- (void)reorientPages;
@ -145,9 +143,6 @@
- (void)flashCheckmarkHud:(NSString *)messageType;
- (void)adjustTraversePosition:(CGFloat)position;
- (void)adjustAutoscrollPosition:(CGFloat)position;
- (void)tappedStory;
- (void)showAutoscrollBriefly:(BOOL)briefly;
- (void)hideAutoscrollAfterDelay;

View file

@ -0,0 +1,19 @@
//
// StoryPagesViewController.swift
// NewsBlur
//
// Created by David Sinclair on 2020-08-27.
// Copyright © 2020 NewsBlur. All rights reserved.
//
import UIKit
/// Manages story pages, containing the previous, current, and next stories.
class StoryPagesViewController: StoryPagesObjCViewController {
/// Convenience initializer to load a new instance of this class from the XIB.
convenience init() {
self.init(nibName: "StoryPagesViewController", bundle: nil)
self.appDelegate = NewsBlurAppDelegate.shared()
}
}

View file

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="StoryPageDelegate">
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="StoryPagesViewController">
<connections>
<outlet property="autoscrollBackgroundImageView" destination="Hm0-aD-uc2" id="iGQ-3d-kdN"/>
<outlet property="autoscrollBottomConstraint" destination="E9T-hc-jPk" id="2sE-74-XyW"/>
@ -19,9 +20,6 @@
<outlet property="buttonPrevious" destination="64" id="67"/>
<outlet property="buttonSend" destination="85" id="88"/>
<outlet property="buttonText" destination="81" id="84"/>
<outlet property="dividerView" destination="YKz-PZ-s0t" id="P3I-Wx-dLN"/>
<outlet property="dividerViewBottomConstraint" destination="Ugq-XC-pFz" id="A98-YF-eby"/>
<outlet property="dragBarImageView" destination="kYw-ba-fFD" id="3C2-Je-cht"/>
<outlet property="loadingIndicator" destination="73" id="74"/>
<outlet property="prevNextBackgroundImageView" destination="71" id="S3e-tC-Pbu"/>
<outlet property="scrollBottomConstraint" destination="AOS-qV-fjZ" id="JD4-zE-OTv"/>
@ -35,21 +33,21 @@
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view multipleTouchEnabled="YES" contentMode="scaleToFill" id="3">
<rect key="frame" x="0.0" y="0.0" width="375" height="724"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="808"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" verticalHuggingPriority="750" alwaysBounceHorizontal="YES" pagingEnabled="YES" delaysContentTouches="NO" bouncesZoom="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5">
<rect key="frame" x="0.0" y="0.0" width="375" height="724"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="808"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<outlet property="delegate" destination="-1" id="27"/>
</connections>
</scrollView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="75">
<rect key="frame" x="0.0" y="661" width="375" height="51"/>
<rect key="frame" x="0.0" y="711" width="414" height="51"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="traverse_background.png" translatesAutoresizingMaskIntoConstraints="NO" id="71">
<rect key="frame" x="209" y="4" width="160" height="44"/>
<rect key="frame" x="248" y="4" width="160" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="IFH-LS-Jje"/>
<constraint firstAttribute="width" constant="160" id="kwh-gV-kd6"/>
@ -63,7 +61,7 @@
</constraints>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="64">
<rect key="frame" x="215" y="9" width="43" height="34"/>
<rect key="frame" x="254" y="9" width="43" height="34"/>
<constraints>
<constraint firstAttribute="height" constant="34" id="FnC-xb-r8x"/>
<constraint firstAttribute="width" constant="43" id="Z6I-Ot-2Bv"/>
@ -83,7 +81,7 @@
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="62">
<rect key="frame" x="259" y="9" width="104" height="34"/>
<rect key="frame" x="298" y="9" width="104" height="34"/>
<constraints>
<constraint firstAttribute="width" constant="104" id="HmV-1Q-KBz"/>
<constraint firstAttribute="height" constant="34" id="aS7-gc-RoE"/>
@ -152,7 +150,7 @@
</connections>
</button>
<activityIndicatorView opaque="NO" contentMode="scaleToFill" hidesWhenStopped="YES" animating="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="73">
<rect key="frame" x="265" y="16" width="20" height="20"/>
<rect key="frame" x="304" y="16" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="20" id="GOD-rV-vW8"/>
<constraint firstAttribute="height" constant="20" id="Ksw-lV-QhR"/>
@ -189,7 +187,7 @@
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LNI-9u-7l4">
<rect key="frame" x="107.5" y="590" width="160" height="44"/>
<rect key="frame" x="127" y="640" width="160" height="44"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="traverse_background.png" translatesAutoresizingMaskIntoConstraints="NO" id="Hm0-aD-uc2">
<rect key="frame" x="0.0" y="0.0" width="160" height="44"/>
@ -292,24 +290,24 @@
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YKz-PZ-s0t">
<rect key="frame" x="0.0" y="712" width="375" height="12"/>
<rect key="frame" x="0.0" y="762" width="414" height="12"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MK4-IV-OSa">
<rect key="frame" x="0.0" y="-1" width="375" height="1"/>
<rect key="frame" x="0.0" y="-1" width="414" height="1"/>
<color key="backgroundColor" red="0.75644385814666748" green="0.75644385814666748" blue="0.75644385814666748" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="TSL-hY-u15"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="62E-7z-9mB">
<rect key="frame" x="0.0" y="12" width="375" height="1"/>
<rect key="frame" x="0.0" y="12" width="414" height="1"/>
<color key="backgroundColor" red="0.75644385814666748" green="0.75644385814666748" blue="0.75644385814666748" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="eNC-Bd-hu0"/>
</constraints>
</view>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="drag_icon.png" translatesAutoresizingMaskIntoConstraints="NO" id="kYw-ba-fFD">
<rect key="frame" x="170.5" y="2" width="34" height="9"/>
<rect key="frame" x="190" y="2" width="34" height="9"/>
<constraints>
<constraint firstAttribute="height" constant="9" id="Pta-oX-r3A"/>
<constraint firstAttribute="width" constant="34" id="oVQ-MZ-nUk"/>

View file

@ -1,58 +0,0 @@
//
// VerticalPageDelegate.swift
// NewsBlur
//
// Created by David Sinclair on 2020-09-24.
// Copyright © 2020 NewsBlur. All rights reserved.
//
import UIKit
/// Delegate and data source of the story vertical page view controller.
class VerticalPageDelegate: NSObject {
}
extension VerticalPageDelegate: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let pageViewController = pageViewController as? VerticalPageViewController, let currentViewController = viewController as? StoryDetailViewController, let detailViewController = pageViewController.detailViewController else {
return nil
}
let pageIndex = currentViewController.pageIndex - 1
let storyController = detailViewController.pageIndexIsValid(pageIndex) ? detailViewController.makeStoryController(for: pageIndex) : nil
pageViewController.previousController = storyController
return storyController
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let pageViewController = pageViewController as? VerticalPageViewController, let currentViewController = viewController as? StoryDetailViewController, let detailViewController = pageViewController.detailViewController else {
return nil
}
var pageIndex = currentViewController.pageIndex + 1
if pageIndex == -1 {
pageIndex = 0
}
let storyController = detailViewController.pageIndexIsValid(pageIndex) ? detailViewController.makeStoryController(for: pageIndex) : nil
pageViewController.nextController = storyController
return storyController
}
}
extension VerticalPageDelegate: UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
guard let pageViewController = pageViewController as? VerticalPageViewController, let detailViewController = pageViewController.detailViewController, let horizontalPageViewController = detailViewController.horizontalPageViewController else {
return
}
horizontalPageViewController.setCurrentController(pageViewController)
horizontalPageViewController.reset()
detailViewController.setStoryFromScroll(false)
}
}

View file

@ -1,132 +0,0 @@
//
// VerticalPageViewController.swift
// NewsBlur
//
// Created by David Sinclair on 2020-09-24.
// Copyright © 2020 NewsBlur. All rights reserved.
//
import UIKit
/// Manages vertical story pages. Instances of this are contained within `HorizontalPageViewController`.
class VerticalPageViewController: UIPageViewController {
/// Weak reference to owning horizontal page view controller.
weak var horizontalPageViewController: HorizontalPageViewController?
/// Weak computed reference to owning detail view controller.
weak var detailViewController: DetailViewController? {
return horizontalPageViewController?.detailViewController
}
/// Returns the story page index of the currently displayed page.
var pageIndex: Int? {
guard let current = currentController else {
return nil
}
return current.pageIndex
}
/// The currently displayed story view controller. Call `setCurrentController(_:direction:animated:completion:)` instead to animate to the page. Shouldn't be `nil`, but could be if not set up yet.
var currentController: StoryDetailViewController? {
get {
return viewControllers?.first as? StoryDetailViewController
}
set {
if let viewController = newValue {
setCurrentController(viewController)
}
}
}
/// The previous story view controller, if it has been requested, otherwise `nil`.
var previousController: StoryDetailViewController?
/// The next story view controller, if it has been requested, otherwise `nil`.
var nextController: StoryDetailViewController?
/// The internal scroll view that drives the page controller.
var scrollView: UIScrollView? {
return view.subviews.filter { $0 is UIScrollView }.first as? UIScrollView
}
private var isPageUpEnabled = true
private var isPageDownEnabled = true
override func viewDidLoad() {
super.viewDidLoad()
self.scrollView?.delegate = self
}
/// Updates whether paging up and/or down is enabled.
func allowPaging(up: Bool, down: Bool) {
isPageUpEnabled = up
isPageDownEnabled = down
if !isPageUpEnabled {
print("Page Up Disabled")
}
if !isPageDownEnabled {
print("Page Down Disabled")
}
}
/// Clear the previous and next story view controllers.
func reset() {
previousController = nil
nextController = nil
}
/// Sets the currently displayed story view controller.
///
/// - Parameter controller: The story view controller to display.
/// - Parameter direction: The navigation direction. Defaults to `.forward`.
/// - Parameter animated: Whether or not to animate it. Defaults to `false`.
/// - Parameter completion: A closure to call when the animation completes. Defaults to `nil`.
func setCurrentController(_ controller: StoryDetailViewController, direction: UIPageViewController.NavigationDirection = .forward, animated: Bool = false, completion: ((Bool) -> Void)? = nil) {
setViewControllers([controller], direction: direction, animated: animated, completion: completion)
}
override func setViewControllers(_ viewControllers: [UIViewController]?, direction: UIPageViewController.NavigationDirection, animated: Bool, completion: ((Bool) -> Void)? = nil) {
guard self.viewControllers != viewControllers else {
print("VerticalPageViewController setViewControllers: \(String(describing: viewControllers)), ignoring as already set")
return
}
reset()
print("VerticalPageViewController setViewControllers: \(String(describing: viewControllers)), current: \(String(describing: self.viewControllers))")
super.setViewControllers(viewControllers, direction: direction, animated: animated, completion: completion)
}
}
extension VerticalPageViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("contentOffset = \(scrollView.contentOffset.y)")
if !self.isPageUpEnabled {
disableUpScroll(scrollView)
}
if !self.isPageDownEnabled {
disableDownScroll(scrollView)
}
}
private func disableUpScroll(_ scrollView: UIScrollView) {
let viewHeight = view.bounds.height
if scrollView.contentOffset.y < viewHeight {
scrollView.setContentOffset(CGPoint(x: 0, y: viewHeight), animated: false)
}
}
private func disableDownScroll(_ scrollView: UIScrollView) {
let viewHeight = view.bounds.height
if scrollView.contentOffset.y > viewHeight {
scrollView.setContentOffset(CGPoint(x: 0, y: viewHeight), animated: false)
}
}
}

View file

@ -18,10 +18,9 @@
170E3CD324F8A89B009CE819 /* HorizontalPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 170E3CD224F8A89B009CE819 /* HorizontalPageViewController.swift */; };
170E3CD724F8AB0D009CE819 /* FeedDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 170E3CD624F8AB0D009CE819 /* FeedDetailViewController.swift */; };
1715D02B2166B3F900227731 /* PremiumManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1715D02A2166B3F900227731 /* PremiumManager.m */; };
171B6FFD25C4C7C8008638A9 /* StoryPagesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171B6FFC25C4C7C8008638A9 /* StoryPagesViewController.swift */; };
1721C9D12497F91A00B0EDC4 /* mute_gray.png in Resources */ = {isa = PBXBuildFile; fileRef = 1721C9D02497F91900B0EDC4 /* mute_gray.png */; };
172AD25E251D9011000BB264 /* VerticalPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172AD25D251D9011000BB264 /* VerticalPageViewController.swift */; };
172AD264251D901D000BB264 /* HorizontalPageDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172AD263251D901D000BB264 /* HorizontalPageDelegate.swift */; };
172AD26A251D9028000BB264 /* VerticalPageDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172AD269251D9028000BB264 /* VerticalPageDelegate.swift */; };
172AD274251D9F40000BB264 /* Storyboards.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172AD273251D9F40000BB264 /* Storyboards.swift */; };
17362ADD23639B4E00A0FCCC /* OfflineFetchText.m in Sources */ = {isa = PBXBuildFile; fileRef = 17362ADC23639B4E00A0FCCC /* OfflineFetchText.m */; };
1740C6881C10FD75005EA453 /* theme_color_dark.png in Resources */ = {isa = PBXBuildFile; fileRef = 1740C6841C10FD75005EA453 /* theme_color_dark.png */; };
@ -429,8 +428,8 @@
FF688E4F16E6B3E1003B7B42 /* traverse_done@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FF688E4D16E6B3E1003B7B42 /* traverse_done@2x.png */; };
FF688E5216E6B8D0003B7B42 /* traverse_background.png in Resources */ = {isa = PBXBuildFile; fileRef = FF688E5016E6B8D0003B7B42 /* traverse_background.png */; };
FF688E5316E6B8D0003B7B42 /* traverse_background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FF688E5116E6B8D0003B7B42 /* traverse_background@2x.png */; };
FF6A233216448E0700E15989 /* DetailObjCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FF6A233116448E0700E15989 /* DetailObjCViewController.m */; };
FF6A23391644957800E15989 /* StoryPageControl.xib in Resources */ = {isa = PBXBuildFile; fileRef = FF6A23361644903900E15989 /* StoryPageControl.xib */; };
FF6A233216448E0700E15989 /* StoryPagesObjCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FF6A233116448E0700E15989 /* StoryPagesObjCViewController.m */; };
FF6A23391644957800E15989 /* StoryPagesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = FF6A23361644903900E15989 /* StoryPagesViewController.xib */; };
FF6DD31E1AEDF9F300F1F53A /* menu_icn_rename.png in Resources */ = {isa = PBXBuildFile; fileRef = FF6DD31C1AEDF9F300F1F53A /* menu_icn_rename.png */; };
FF6DD31F1AEDF9F300F1F53A /* menu_icn_rename@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FF6DD31D1AEDF9F300F1F53A /* menu_icn_rename@2x.png */; };
FF753CCE175858FC00344EC9 /* FMDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = FF753CC4175858FC00344EC9 /* FMDatabase.m */; };
@ -684,10 +683,9 @@
170E3CD624F8AB0D009CE819 /* FeedDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedDetailViewController.swift; sourceTree = "<group>"; };
1715D0292166B3F900227731 /* PremiumManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PremiumManager.h; sourceTree = "<group>"; };
1715D02A2166B3F900227731 /* PremiumManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PremiumManager.m; sourceTree = "<group>"; };
171B6FFC25C4C7C8008638A9 /* StoryPagesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryPagesViewController.swift; sourceTree = "<group>"; };
1721C9D02497F91900B0EDC4 /* mute_gray.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mute_gray.png; sourceTree = "<group>"; };
172AD25D251D9011000BB264 /* VerticalPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalPageViewController.swift; sourceTree = "<group>"; };
172AD263251D901D000BB264 /* HorizontalPageDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalPageDelegate.swift; sourceTree = "<group>"; };
172AD269251D9028000BB264 /* VerticalPageDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalPageDelegate.swift; sourceTree = "<group>"; };
172AD273251D9F40000BB264 /* Storyboards.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storyboards.swift; sourceTree = "<group>"; };
17362ADB23639B4E00A0FCCC /* OfflineFetchText.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OfflineFetchText.h; path = offline/OfflineFetchText.h; sourceTree = "<group>"; };
17362ADC23639B4E00A0FCCC /* OfflineFetchText.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OfflineFetchText.m; path = offline/OfflineFetchText.m; sourceTree = "<group>"; };
@ -1233,9 +1231,9 @@
FF688E4D16E6B3E1003B7B42 /* traverse_done@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "traverse_done@2x.png"; sourceTree = "<group>"; };
FF688E5016E6B8D0003B7B42 /* traverse_background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = traverse_background.png; sourceTree = "<group>"; };
FF688E5116E6B8D0003B7B42 /* traverse_background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "traverse_background@2x.png"; sourceTree = "<group>"; };
FF6A233016448E0700E15989 /* DetailObjCViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailObjCViewController.h; sourceTree = "<group>"; };
FF6A233116448E0700E15989 /* DetailObjCViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailObjCViewController.m; sourceTree = "<group>"; };
FF6A23361644903900E15989 /* StoryPageControl.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = StoryPageControl.xib; path = ../Classes/StoryPageControl.xib; sourceTree = "<group>"; };
FF6A233016448E0700E15989 /* StoryPagesObjCViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StoryPagesObjCViewController.h; sourceTree = "<group>"; };
FF6A233116448E0700E15989 /* StoryPagesObjCViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StoryPagesObjCViewController.m; sourceTree = "<group>"; };
FF6A23361644903900E15989 /* StoryPagesViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = StoryPagesViewController.xib; path = ../Classes/StoryPagesViewController.xib; sourceTree = "<group>"; };
FF6DD31C1AEDF9F300F1F53A /* menu_icn_rename.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_icn_rename.png; sourceTree = "<group>"; };
FF6DD31D1AEDF9F300F1F53A /* menu_icn_rename@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "menu_icn_rename@2x.png"; sourceTree = "<group>"; };
FF753CC3175858FC00344EC9 /* FMDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabase.h; sourceTree = "<group>"; };
@ -1896,13 +1894,11 @@
431B857415A1324200DCE497 /* Story */ = {
isa = PBXGroup;
children = (
176A5C7924F8BD1B009E8DF9 /* DetailViewController.swift */,
FF6A233016448E0700E15989 /* DetailObjCViewController.h */,
FF6A233116448E0700E15989 /* DetailObjCViewController.m */,
171B6FFC25C4C7C8008638A9 /* StoryPagesViewController.swift */,
FF6A233016448E0700E15989 /* StoryPagesObjCViewController.h */,
FF6A233116448E0700E15989 /* StoryPagesObjCViewController.m */,
170E3CD224F8A89B009CE819 /* HorizontalPageViewController.swift */,
172AD263251D901D000BB264 /* HorizontalPageDelegate.swift */,
172AD25D251D9011000BB264 /* VerticalPageViewController.swift */,
172AD269251D9028000BB264 /* VerticalPageDelegate.swift */,
1787082F24F8B3A50000C82B /* StoryDetailViewController.swift */,
7842ECF511D44A530066CF9D /* StoryDetailObjCViewController.h */,
7842ECF611D44A530066CF9D /* StoryDetailObjCViewController.m */,
@ -2309,7 +2305,7 @@
43B8F01F156603170008733D /* NewsBlurViewController.xib */,
43081E2115AFE84200B24D7A /* ShareViewController.xib */,
43B8F021156603170008733D /* StoryDetailViewController.xib */,
FF6A23361644903900E15989 /* StoryPageControl.xib */,
FF6A23361644903900E15989 /* StoryPagesViewController.xib */,
FF67D3B6168977690057A7DA /* TrainerViewController.xib */,
43A4BAEA15C893E300F3B8D4 /* FriendsListViewController.xib */,
);
@ -2385,6 +2381,7 @@
172AD273251D9F40000BB264 /* Storyboards.swift */,
170E3CCE24F8A5D8009CE819 /* SplitViewController.swift */,
170E3CD024F8A664009CE819 /* SplitViewDelegate.swift */,
176A5C7924F8BD1B009E8DF9 /* DetailViewController.swift */,
436ACA8B15BF1088004E01CC /* NBContainerViewController.h */,
436ACA8C15BF1088004E01CC /* NBContainerViewController.m */,
17432C7D1C533FBC003F8FD6 /* MenuViewController.h */,
@ -2837,7 +2834,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1120;
LastUpgradeCheck = 1230;
LastUpgradeCheck = 1240;
ORGANIZATIONNAME = NewsBlur;
TargetAttributes = {
1749390F1C251BFE003D98AA = {
@ -3126,7 +3123,7 @@
FF5F3A8B162B8390008DBE3E /* car.png in Resources */,
FF41309D162CEC7100DDB6A7 /* time.png in Resources */,
FF4130A0162CECAE00DDB6A7 /* email.png in Resources */,
FF6A23391644957800E15989 /* StoryPageControl.xib in Resources */,
FF6A23391644957800E15989 /* StoryPagesViewController.xib in Resources */,
FF67D3B7168977690057A7DA /* TrainerViewController.xib in Resources */,
FF67D3BB168A70630057A7DA /* trainer.css in Resources */,
FF3FA8951BB26B6A001F7C32 /* copy_link@2x.png in Resources */,
@ -3401,7 +3398,6 @@
FFC0E5AC1F7AC00A0023B9D9 /* AFImageDownloader.m in Sources */,
FFC0E5AE1F7AC00A0023B9D9 /* AFNetworkActivityIndicatorManager.m in Sources */,
FFC0E5B11F7AC00A0023B9D9 /* AFNetworkReachabilityManager.m in Sources */,
172AD26A251D9028000BB264 /* VerticalPageDelegate.swift in Sources */,
FFC0E5B31F7AC00A0023B9D9 /* AFSecurityPolicy.m in Sources */,
FFC0E5B51F7AC00A0023B9D9 /* AFURLRequestSerialization.m in Sources */,
FFC0E5B71F7AC00A0023B9D9 /* AFURLResponseSerialization.m in Sources */,
@ -3415,6 +3411,7 @@
17EB50601BE46A900021358B /* FontListViewController.m in Sources */,
FF0FAEB117B084D2008651F9 /* OfflineCleanImages.m in Sources */,
43F44B1C159D8DBC00F48F8A /* FeedTableCell.m in Sources */,
171B6FFD25C4C7C8008638A9 /* StoryPagesViewController.swift in Sources */,
1D3623260D0F684500981E51 /* NewsBlurAppDelegate.m in Sources */,
17432C861C5343C0003F8FD6 /* FeedChooserTitleView.m in Sources */,
28D7ACF80DDB3853001CB0EB /* FeedsObjCViewController.m in Sources */,
@ -3439,7 +3436,6 @@
17731A9D23DFAD3D00759A7D /* ImportExportPreferences.swift in Sources */,
FFD1D7311459B63500E46F89 /* BaseViewController.m in Sources */,
FF34FD6D1E9D93CB0062F8ED /* IASKSwitch.m in Sources */,
172AD25E251D9011000BB264 /* VerticalPageViewController.swift in Sources */,
FF9B8BB217F2351A0036A41C /* NBBarButtonItem.m in Sources */,
FF2D8CE514893BC000057B80 /* MoveSiteViewController.m in Sources */,
433323CD158968ED0025064D /* FirstTimeUserViewController.m in Sources */,
@ -3515,7 +3511,7 @@
17432C7F1C533FBC003F8FD6 /* MenuViewController.m in Sources */,
FFF8B3AF1F847505001AB95E /* NBDashboardNavigationBar.m in Sources */,
17E635AF1C548C580075338E /* FeedChooserItem.m in Sources */,
FF6A233216448E0700E15989 /* DetailObjCViewController.m in Sources */,
FF6A233216448E0700E15989 /* StoryPagesObjCViewController.m in Sources */,
FF67D3B2168924C40057A7DA /* TrainerViewController.m in Sources */,
FF1660CD16D6FD8A00AF8541 /* SmallInteractionCell.m in Sources */,
FF34FD6E1E9D93CB0062F8ED /* IASKTextField.m in Sources */,

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1230"
LastUpgradeVersion = "1240"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1230"
LastUpgradeVersion = "1240"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1230"
LastUpgradeVersion = "1240"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1230"
LastUpgradeVersion = "1240"
wasCreatedForAppExtension = "YES"
version = "1.3">
<BuildAction

View file

@ -12,6 +12,6 @@
#import "FeedsObjCViewController.h"
#import "FeedDetailObjCViewController.h"
#import "DetailObjCViewController.h"
#import "StoryPagesObjCViewController.h"
#import "StoryDetailObjCViewController.h"
#import "OriginalStoryViewController.h"

View file

@ -1,9 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="17503.1" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
<device id="ipad9_7" orientation="portrait" layout="fullscreen" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17502"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -34,6 +33,7 @@
<outlet property="premiumViewController" destination="Nno-Ma-6TQ" id="0Ex-VU-Hek"/>
<outlet property="shareViewController" destination="168" id="272"/>
<outlet property="storyDetailViewController" destination="92" id="93"/>
<outlet property="storyPagesViewController" destination="290" id="lNi-vY-38g"/>
<outlet property="trainerViewController" destination="287" id="289"/>
<outlet property="userProfileViewController" destination="235" id="236"/>
<outlet property="userTagsViewController" destination="v2Q-Hh-f3K" id="5CE-5l-aoS"/>
@ -45,6 +45,7 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="blackOpaque"/>
<point key="canvasLocation" x="50" y="154"/>
</window>
<viewController nibName="AddSiteViewController" id="121" userLabel="Add Site View Controller" customClass="AddSiteViewController">
<extendedEdge key="edgesForExtendedLayout"/>
@ -153,6 +154,12 @@
<connections>
<outlet property="appDelegate" destination="3" id="271"/>
</connections>
<point key="canvasLocation" x="-63" y="-1123"/>
</viewController>
<viewController restorationIdentifier="StoryPagesViewController" id="290" customClass="StoryPagesViewController" customModule="NewsBlur" customModuleProvider="target">
<extendedEdge key="edgesForExtendedLayout"/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="blackOpaque"/>
<point key="canvasLocation" x="50" y="-485"/>
</viewController>
<viewController restorationIdentifier="StoryDetailView" nibName="StoryDetailViewController" id="92" customClass="StoryDetailViewController">
<extendedEdge key="edgesForExtendedLayout"/>
@ -160,6 +167,7 @@
<connections>
<outlet property="appDelegate" destination="3" id="105"/>
</connections>
<point key="canvasLocation" x="702" y="-514"/>
</viewController>
<viewController id="235" customClass="UserProfileViewController">
<extendedEdge key="edgesForExtendedLayout"/>
@ -174,6 +182,7 @@
<connections>
<outlet property="appDelegate" destination="3" id="267"/>
</connections>
<point key="canvasLocation" x="-716" y="-525"/>
</viewController>
<navigationController restorationIdentifier="MainNavigation" title="Main" id="173">
<extendedEdge key="edgesForExtendedLayout"/>

View file

@ -33,6 +33,7 @@
<outlet property="premiumViewController" destination="GXC-Ze-HBm" id="wZ1-Qy-e0X"/>
<outlet property="shareViewController" destination="131" id="132"/>
<outlet property="storyDetailViewController" destination="92" id="173"/>
<outlet property="storyPagesViewController" destination="170" id="172"/>
<outlet property="trainerViewController" destination="174" id="176"/>
<outlet property="userProfileViewController" destination="141" id="142"/>
<outlet property="window" destination="12" id="78"/>
@ -67,6 +68,14 @@
</connections>
<point key="canvasLocation" x="-677" y="-1136"/>
</viewController>
<viewController restorationIdentifier="StoryPagesViewController" nibName="StoryPagesViewController" automaticallyAdjustsScrollViewInsets="NO" id="170" customClass="StoryPagesViewController">
<extendedEdge key="edgesForExtendedLayout"/>
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
<connections>
<outlet property="appDelegate" destination="3" id="171"/>
</connections>
<point key="canvasLocation" x="-1564" y="-1165"/>
</viewController>
<viewController nibName="LoginViewController" id="102" userLabel="Login View Controller" customClass="LoginViewController">
<extendedEdge key="edgesForExtendedLayout"/>
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>

View file

@ -13,7 +13,7 @@
<objects>
<viewController storyboardIdentifier="DetailViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="djW-7k-haK" customClass="DetailViewController" customModule="NewsBlur" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jTZ-4O-xyT">
<rect key="frame" x="0.0" y="0.0" width="1194" height="834"/>
<rect key="frame" x="0.0" y="0.0" width="818.5" height="834"/>
<subviews>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bPa-u1-Aml">
<rect key="frame" x="0.0" y="50" width="1194" height="604"/>
@ -73,304 +73,30 @@
</mask>
</variation>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4vK-W4-ayS">
<rect key="frame" x="0.0" y="583" width="1194" height="51"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="traverse_background.png" translatesAutoresizingMaskIntoConstraints="NO" id="PLd-RZ-773">
<rect key="frame" x="1028" y="4" width="160" height="44"/>
<constraints>
<constraint firstAttribute="width" constant="160" id="SOi-6Y-1cH"/>
<constraint firstAttribute="height" constant="44" id="yra-hO-9Gh"/>
</constraints>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="traverse_background.png" translatesAutoresizingMaskIntoConstraints="NO" id="zfl-mN-y0T">
<rect key="frame" x="4" y="4" width="143" height="44"/>
<constraints>
<constraint firstAttribute="width" constant="143" id="v9X-2X-Bgb"/>
<constraint firstAttribute="height" constant="44" id="vg2-XI-Vnl"/>
</constraints>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="oct-Cn-9L0">
<rect key="frame" x="1034" y="9" width="43" height="34"/>
<constraints>
<constraint firstAttribute="height" constant="34" id="8OI-gJ-c5x"/>
<constraint firstAttribute="width" constant="43" id="kNF-2d-gY1"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="13"/>
<inset key="contentEdgeInsets" minX="0.0" minY="0.0" maxX="20" maxY="0.0"/>
<state key="normal" backgroundImage="traverse_previous.png">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" backgroundImage="traverse_previous_off.png"/>
<state key="highlighted">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="doPreviousStory:" destination="djW-7k-haK" eventType="touchUpInside" id="pgb-NN-Zmi"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZoU-af-wjh">
<rect key="frame" x="1078" y="9" width="104" height="34"/>
<constraints>
<constraint firstAttribute="width" constant="104" id="Esh-zh-12I"/>
<constraint firstAttribute="height" constant="34" id="LWH-y8-6oO"/>
</constraints>
<fontDescription key="fontDescription" name="Helvetica-Bold" family="Helvetica" pointSize="13"/>
<inset key="titleEdgeInsets" minX="2" minY="0.0" maxX="0.0" maxY="0.0"/>
<state key="normal" title="NEXT" backgroundImage="traverse_next.png">
<color key="titleColor" red="0.51764705879999995" green="0.52549019610000003" blue="0.50196078430000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="titleShadowColor" red="0.49803921569999998" green="0.49803921569999998" blue="0.49803921569999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="selected">
<color key="titleColor" red="0.1969947517" green="0.1969947517" blue="0.1969947517" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="highlighted">
<color key="titleColor" red="0.33333334329999997" green="0.33333334329999997" blue="0.33333334329999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="doNextUnreadStory:" destination="djW-7k-haK" eventType="touchUpInside" id="7Ye-5J-1dI"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Mhr-a8-MQd">
<rect key="frame" x="9" y="9" width="87" height="34"/>
<constraints>
<constraint firstAttribute="height" constant="34" id="8lr-m8-D43"/>
<constraint firstAttribute="width" constant="87" id="fH9-Ji-sL9"/>
</constraints>
<fontDescription key="fontDescription" name="Helvetica-Bold" family="Helvetica" pointSize="13"/>
<inset key="titleEdgeInsets" minX="16" minY="0.0" maxX="0.0" maxY="0.0"/>
<state key="normal" title="TEXT" backgroundImage="traverse_text.png">
<color key="titleColor" red="0.51726847890000005" green="0.52641934160000003" blue="0.5003217459" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="selected">
<color key="titleColor" red="0.1969947517" green="0.1969947517" blue="0.1969947517" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="highlighted">
<color key="titleColor" red="0.33333334329999997" green="0.33333334329999997" blue="0.33333334329999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="toggleTextView:" destination="djW-7k-haK" eventType="touchUpInside" id="BcX-EA-coX"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Teu-p1-Gy0">
<rect key="frame" x="97" y="9" width="44" height="34"/>
<constraints>
<constraint firstAttribute="width" constant="44" id="GHI-MI-CDD"/>
<constraint firstAttribute="height" constant="34" id="UIz-s9-jVY"/>
</constraints>
<fontDescription key="fontDescription" name="Helvetica-Bold" family="Helvetica" pointSize="13"/>
<inset key="contentEdgeInsets" minX="0.0" minY="0.0" maxX="20" maxY="0.0"/>
<state key="normal" backgroundImage="traverse_send.png">
<color key="titleColor" red="0.51726847890000005" green="0.52641934160000003" blue="0.5003217459" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="selected">
<color key="titleColor" red="0.1969947517" green="0.1969947517" blue="0.1969947517" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="highlighted">
<color key="titleColor" red="0.33333334329999997" green="0.33333334329999997" blue="0.33333334329999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="openSendToDialog:" destination="djW-7k-haK" eventType="touchUpInside" id="9U3-UM-kcf"/>
</connections>
</button>
<activityIndicatorView opaque="NO" contentMode="scaleToFill" hidesWhenStopped="YES" animating="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="wpt-1g-x7w">
<rect key="frame" x="1084" y="16" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="20" id="GBn-Oz-urx"/>
<constraint firstAttribute="height" constant="20" id="wo2-Qz-ku4"/>
</constraints>
<color key="color" red="0.5383990407" green="0.54777079819999996" blue="0.51707810160000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</activityIndicatorView>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="wpt-1g-x7w" secondAttribute="bottom" constant="15" id="03o-Tx-Ngx"/>
<constraint firstAttribute="trailing" secondItem="ZoU-af-wjh" secondAttribute="trailing" constant="12" id="9oi-95-ua5"/>
<constraint firstAttribute="bottom" secondItem="Teu-p1-Gy0" secondAttribute="bottom" constant="8" id="DhJ-Vd-Zos"/>
<constraint firstAttribute="bottom" secondItem="ZoU-af-wjh" secondAttribute="bottom" constant="8" id="F4M-Gs-4Q8"/>
<constraint firstAttribute="trailing" secondItem="PLd-RZ-773" secondAttribute="trailing" constant="6" id="KIb-u5-yKl"/>
<constraint firstItem="Mhr-a8-MQd" firstAttribute="top" secondItem="4vK-W4-ayS" secondAttribute="top" constant="9" id="Lm9-bw-Gae"/>
<constraint firstItem="wpt-1g-x7w" firstAttribute="top" secondItem="4vK-W4-ayS" secondAttribute="top" constant="16" id="Onq-vt-9IB"/>
<constraint firstItem="oct-Cn-9L0" firstAttribute="top" secondItem="4vK-W4-ayS" secondAttribute="top" constant="9" id="Sb8-ah-WTX"/>
<constraint firstAttribute="bottom" secondItem="PLd-RZ-773" secondAttribute="bottom" constant="3" id="XVE-t8-vex"/>
<constraint firstItem="Mhr-a8-MQd" firstAttribute="leading" secondItem="4vK-W4-ayS" secondAttribute="leading" constant="9" id="cUF-Cc-QxF"/>
<constraint firstAttribute="height" constant="51" id="eDx-IM-t3r"/>
<constraint firstAttribute="bottom" secondItem="Mhr-a8-MQd" secondAttribute="bottom" constant="8" id="elN-qs-zPt"/>
<constraint firstItem="Teu-p1-Gy0" firstAttribute="leading" secondItem="Mhr-a8-MQd" secondAttribute="trailing" constant="1" id="fVb-wU-tzk"/>
<constraint firstItem="ZoU-af-wjh" firstAttribute="top" secondItem="4vK-W4-ayS" secondAttribute="top" constant="9" id="fng-rP-yJD"/>
<constraint firstItem="ZoU-af-wjh" firstAttribute="leading" secondItem="oct-Cn-9L0" secondAttribute="trailing" constant="1" id="g6D-iX-NZ0"/>
<constraint firstAttribute="bottom" secondItem="oct-Cn-9L0" secondAttribute="bottom" constant="8" id="iUr-Cf-Q16"/>
<constraint firstItem="PLd-RZ-773" firstAttribute="top" secondItem="4vK-W4-ayS" secondAttribute="top" constant="4" id="kPd-Dz-5Mp"/>
<constraint firstItem="zfl-mN-y0T" firstAttribute="leading" secondItem="4vK-W4-ayS" secondAttribute="leading" constant="4" id="p37-nQ-da5"/>
<constraint firstItem="wpt-1g-x7w" firstAttribute="leading" secondItem="oct-Cn-9L0" secondAttribute="trailing" constant="7" id="pie-9C-6lc"/>
<constraint firstItem="Teu-p1-Gy0" firstAttribute="top" secondItem="4vK-W4-ayS" secondAttribute="top" constant="9" id="r6J-NM-Wih"/>
<constraint firstItem="ZoU-af-wjh" firstAttribute="leading" secondItem="oct-Cn-9L0" secondAttribute="trailing" constant="1" id="sAq-ce-nf3"/>
<constraint firstItem="zfl-mN-y0T" firstAttribute="top" secondItem="4vK-W4-ayS" secondAttribute="top" constant="4" id="u2K-Za-5uE"/>
<constraint firstItem="Teu-p1-Gy0" firstAttribute="leading" secondItem="Mhr-a8-MQd" secondAttribute="trailing" constant="1" id="vqy-97-fJY"/>
<constraint firstAttribute="bottom" secondItem="zfl-mN-y0T" secondAttribute="bottom" constant="3" id="zAW-8Q-Srb"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hfm-Pf-oeW">
<rect key="frame" x="517" y="532" width="160" height="44"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="traverse_background.png" translatesAutoresizingMaskIntoConstraints="NO" id="DhZ-K9-Ohx">
<rect key="frame" x="0.0" y="0.0" width="160" height="44"/>
<constraints>
<constraint firstAttribute="width" constant="160" id="pgM-aj-MFu"/>
<constraint firstAttribute="height" constant="44" id="whT-PJ-xOd"/>
</constraints>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Xtc-sh-knL">
<rect key="frame" x="6" y="5" width="36" height="34"/>
<constraints>
<constraint firstAttribute="height" constant="34" id="2pi-Ji-rYh"/>
<constraint firstAttribute="width" constant="36" id="GUg-uM-GcI"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="13"/>
<inset key="contentEdgeInsets" minX="0.0" minY="0.0" maxX="20" maxY="0.0"/>
<state key="normal" backgroundImage="autoscroll_off.png">
<color key="titleColor" red="0.51764705879999995" green="0.52549019610000003" blue="0.50196078430000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" backgroundImage="traverse_previous_off.png"/>
<state key="highlighted">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="autoscrollDisable:" destination="djW-7k-haK" eventType="touchUpInside" id="xy6-pJ-Zar"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="WoA-Tv-FTT">
<rect key="frame" x="43" y="5" width="36" height="34"/>
<constraints>
<constraint firstAttribute="width" constant="36" id="DLV-4U-iIU"/>
<constraint firstAttribute="height" constant="34" id="hGu-E7-dg7"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="13"/>
<inset key="contentEdgeInsets" minX="0.0" minY="0.0" maxX="20" maxY="0.0"/>
<state key="normal" backgroundImage="autoscroll_resume.png">
<color key="titleColor" red="0.51764705879999995" green="0.52549019610000003" blue="0.50196078430000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" backgroundImage="traverse_previous_off.png"/>
<state key="highlighted">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="autoscrollPauseResume:" destination="djW-7k-haK" eventType="touchUpInside" id="nkL-6Z-mrc"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="x4P-S0-dR7">
<rect key="frame" x="80" y="5" width="36" height="34"/>
<constraints>
<constraint firstAttribute="width" constant="36" id="kGz-Tf-Nfz"/>
<constraint firstAttribute="height" constant="34" id="wsh-s4-baM"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="13"/>
<inset key="contentEdgeInsets" minX="0.0" minY="0.0" maxX="20" maxY="0.0"/>
<state key="normal" backgroundImage="autoscroll_slower.png">
<color key="titleColor" red="0.51764705879999995" green="0.52549019610000003" blue="0.50196078430000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" backgroundImage="traverse_previous_off.png"/>
<state key="highlighted">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="autoscrollSlower:" destination="djW-7k-haK" eventType="touchUpInside" id="JIU-Gg-Lt9"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xZB-Qu-u2n">
<rect key="frame" x="117" y="5" width="37" height="34"/>
<constraints>
<constraint firstAttribute="width" constant="37" id="Uc8-iE-dwS"/>
<constraint firstAttribute="height" constant="34" id="eBL-Sp-Fbq"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="13"/>
<inset key="contentEdgeInsets" minX="0.0" minY="0.0" maxX="20" maxY="0.0"/>
<state key="normal" backgroundImage="autoscroll_faster.png">
<color key="titleColor" red="0.51764705879999995" green="0.52549019610000003" blue="0.50196078430000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" backgroundImage="traverse_previous_off.png"/>
<state key="highlighted">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="autoscrollFaster:" destination="djW-7k-haK" eventType="touchUpInside" id="8aA-ma-ybu"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="160" id="8JN-0x-Wxg"/>
<constraint firstItem="x4P-S0-dR7" firstAttribute="leading" secondItem="WoA-Tv-FTT" secondAttribute="trailing" constant="1" id="9d0-El-qfS"/>
<constraint firstItem="xZB-Qu-u2n" firstAttribute="centerY" secondItem="hfm-Pf-oeW" secondAttribute="centerY" id="Fum-wZ-lMO"/>
<constraint firstItem="Xtc-sh-knL" firstAttribute="leading" secondItem="DhZ-K9-Ohx" secondAttribute="leading" constant="6" id="LGD-tR-0md"/>
<constraint firstAttribute="height" constant="44" id="McX-ZT-Oa5"/>
<constraint firstItem="xZB-Qu-u2n" firstAttribute="leading" secondItem="x4P-S0-dR7" secondAttribute="trailing" constant="1" id="S9q-9z-hqL"/>
<constraint firstItem="WoA-Tv-FTT" firstAttribute="centerY" secondItem="hfm-Pf-oeW" secondAttribute="centerY" id="Uxl-g3-HeW"/>
<constraint firstItem="WoA-Tv-FTT" firstAttribute="leading" secondItem="Xtc-sh-knL" secondAttribute="trailing" constant="1" id="b8m-Mq-cvm"/>
<constraint firstItem="DhZ-K9-Ohx" firstAttribute="centerY" secondItem="hfm-Pf-oeW" secondAttribute="centerY" id="mrl-fB-AqE"/>
<constraint firstItem="DhZ-K9-Ohx" firstAttribute="centerX" secondItem="hfm-Pf-oeW" secondAttribute="centerX" id="nU9-HN-T6z"/>
<constraint firstItem="x4P-S0-dR7" firstAttribute="centerY" secondItem="hfm-Pf-oeW" secondAttribute="centerY" id="ngp-qt-zlU"/>
<constraint firstItem="Xtc-sh-knL" firstAttribute="centerY" secondItem="hfm-Pf-oeW" secondAttribute="centerY" id="yw5-gp-mD8"/>
</constraints>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="rKh-Md-Ci2"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="4vK-W4-ayS" firstAttribute="leading" secondItem="jTZ-4O-xyT" secondAttribute="leading" id="AFV-14-jnc"/>
<constraint firstAttribute="trailing" secondItem="5M7-bO-MVK" secondAttribute="trailing" id="Bge-if-1kj"/>
<constraint firstItem="5M7-bO-MVK" firstAttribute="bottom" secondItem="hfm-Pf-oeW" secondAttribute="bottom" constant="90" id="DIG-xz-1US"/>
<constraint firstItem="hfm-Pf-oeW" firstAttribute="centerX" secondItem="jTZ-4O-xyT" secondAttribute="centerX" id="Grz-1P-qjc"/>
<constraint firstItem="rKh-Md-Ci2" firstAttribute="top" secondItem="bPa-u1-Aml" secondAttribute="top" id="JN4-aj-xiN"/>
<constraint firstAttribute="trailing" secondItem="4vK-W4-ayS" secondAttribute="trailing" id="JVw-MX-f4R"/>
<constraint firstItem="bPa-u1-Aml" firstAttribute="leading" secondItem="jTZ-4O-xyT" secondAttribute="leading" id="Px6-tP-Snv"/>
<constraint firstItem="tFd-Uv-aMP" firstAttribute="top" secondItem="bPa-u1-Aml" secondAttribute="bottom" id="SGz-wm-mAv"/>
<constraint firstItem="5M7-bO-MVK" firstAttribute="leading" secondItem="jTZ-4O-xyT" secondAttribute="leading" id="Tg9-DU-zcP"/>
<constraint firstItem="tFd-Uv-aMP" firstAttribute="top" secondItem="4vK-W4-ayS" secondAttribute="bottom" constant="20" id="YVh-UJ-d3j"/>
<constraint firstAttribute="bottom" secondItem="tFd-Uv-aMP" secondAttribute="bottom" constant="168" id="c9d-f5-wud"/>
<constraint firstItem="5M7-bO-MVK" firstAttribute="bottom" secondItem="4vK-W4-ayS" secondAttribute="bottom" constant="32" id="efm-qO-UF1"/>
<constraint firstAttribute="trailing" secondItem="tFd-Uv-aMP" secondAttribute="trailing" id="h2I-ng-gxc"/>
<constraint firstAttribute="bottom" secondItem="5M7-bO-MVK" secondAttribute="bottom" id="nSX-TU-ART"/>
<constraint firstItem="tFd-Uv-aMP" firstAttribute="top" secondItem="hfm-Pf-oeW" secondAttribute="bottom" constant="78" id="phm-3P-lxo"/>
<constraint firstItem="5M7-bO-MVK" firstAttribute="top" secondItem="tFd-Uv-aMP" secondAttribute="bottom" id="v7j-Eh-lGD"/>
<constraint firstItem="tFd-Uv-aMP" firstAttribute="leading" secondItem="jTZ-4O-xyT" secondAttribute="leading" id="wzt-O8-Ild"/>
<constraint firstAttribute="trailing" secondItem="bPa-u1-Aml" secondAttribute="trailing" id="xth-oH-VTF"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="DIG-xz-1US"/>
<exclude reference="efm-qO-UF1"/>
</mask>
</variation>
</view>
<navigationItem key="navigationItem" id="OyA-BF-OGR"/>
<connections>
<outlet property="autoscrollBackgroundImageView" destination="DhZ-K9-Ohx" id="JlX-4q-aYI"/>
<outlet property="autoscrollBottomContainerBottomConstraint" destination="DIG-xz-1US" id="SRV-nP-Wrx"/>
<outlet property="autoscrollDisableButton" destination="Xtc-sh-knL" id="HH8-tu-4lg"/>
<outlet property="autoscrollFasterButton" destination="xZB-Qu-u2n" id="ora-na-Jht"/>
<outlet property="autoscrollPauseResumeButton" destination="WoA-Tv-FTT" id="G89-JX-DAM"/>
<outlet property="autoscrollSlowerButton" destination="x4P-S0-dR7" id="5r5-Ix-oSv"/>
<outlet property="autoscrollTopContainerBottomConstraint" destination="phm-3P-lxo" id="1se-rX-o1p"/>
<outlet property="autoscrollView" destination="hfm-Pf-oeW" id="uLO-sQ-E0v"/>
<outlet property="bottomContainerView" destination="5M7-bO-MVK" id="Tqo-s5-kGB"/>
<outlet property="buttonNext" destination="ZoU-af-wjh" id="Bg3-Bc-32l"/>
<outlet property="buttonPrevious" destination="oct-Cn-9L0" id="GQY-2J-pfy"/>
<outlet property="buttonSend" destination="Teu-p1-Gy0" id="cLM-Zi-gs0"/>
<outlet property="buttonText" destination="Mhr-a8-MQd" id="bXI-fg-Y5m"/>
<outlet property="dividerView" destination="tFd-Uv-aMP" id="d0U-lI-Ukb"/>
<outlet property="dividerViewBottomConstraint" destination="c9d-f5-wud" id="0kK-IS-Yql"/>
<outlet property="dragBarImageView" destination="xeQ-Iz-FR0" id="JfY-AN-erg"/>
<outlet property="loadingIndicator" destination="wpt-1g-x7w" id="6Re-nf-bHo"/>
<outlet property="prevNextBackgroundImageView" destination="PLd-RZ-773" id="adi-Gt-uX1"/>
<outlet property="textStorySendBackgroundImageView" destination="zfl-mN-y0T" id="lD1-7s-izZ"/>
<outlet property="topContainerTopConstraint" destination="JN4-aj-xiN" id="BFs-GY-GpX"/>
<outlet property="topContainerView" destination="bPa-u1-Aml" id="nUk-aR-0ix"/>
<outlet property="traverseBottomContainerBottomConstraint" destination="efm-qO-UF1" id="cEE-UD-KiD"/>
<outlet property="traverseTopContainerBottomConstraint" destination="YVh-UJ-d3j" id="d4B-Vw-6hb"/>
<outlet property="traverseView" destination="4vK-W4-ayS" id="yvU-Yp-1YP"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="AQD-wG-11i" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
@ -704,20 +430,10 @@
</scenes>
<resources>
<image name="all.png" width="19.5" height="12.5"/>
<image name="autoscroll_faster.png" width="37" height="34"/>
<image name="autoscroll_off.png" width="36" height="34"/>
<image name="autoscroll_resume.png" width="36" height="34"/>
<image name="autoscroll_slower.png" width="36" height="34"/>
<image name="big_world.png" width="30.719999313354492" height="30.719999313354492"/>
<image name="drag_icon.png" width="96" height="24"/>
<image name="nav_icn_add.png" width="49.454544067382812" height="64"/>
<image name="nav_icn_settings.png" width="15.359999656677246" height="12.239999771118164"/>
<image name="traverse_background.png" width="113" height="46"/>
<image name="traverse_next.png" width="104" height="34"/>
<image name="traverse_previous.png" width="43" height="34"/>
<image name="traverse_previous_off.png" width="43" height="34"/>
<image name="traverse_send.png" width="44" height="34"/>
<image name="traverse_text.png" width="94" height="34"/>
<image name="unread_blue.png" width="49.5" height="12.5"/>
<image name="unread_green.png" width="49" height="12.5"/>
<image name="unread_yellow.png" width="58" height="12.5"/>