2012-11-05 15:12:42 -08:00
//
2021-01-29 20:10:53 -08:00
// StoryPagesObjCViewController . m
2012-11-05 15:12:42 -08:00
// NewsBlur
//
// Created by Samuel Clay on 11 / 2 / 12.
// Copyright ( c ) 2012 NewsBlur . All rights reserved .
//
2021-01-29 20:10:53 -08:00
# import "StoryPagesObjCViewController.h"
2012-11-05 17:16:10 -08:00
# import "NewsBlurAppDelegate.h"
# import "FontSettingsViewController.h"
# import "UserProfileViewController.h"
# import "ShareViewController.h"
# import "Utilities.h"
# import "NSString+HTML.h"
# import "DataUtilities.h"
2015-09-16 16:53:07 -07:00
# import "SBJson4.h"
2013-02-27 18:04:03 -08:00
# import "UIBarButtonItem+Image.h"
2013-04-10 21:06:17 -07:00
# import "THCircularProgressView.h"
2013-06-16 08:15:40 -07:00
# import "FMDatabase.h"
2014-02-12 20:09:37 -08:00
# import "StoriesCollection.h"
2020-08-27 21:26:12 -07:00
# import "NewsBlur-Swift.h"
2020-02-23 15:21:32 -08:00
@ import WebKit ;
2012-11-05 15:12:42 -08:00
2021-01-29 20:10:53 -08:00
@ interface StoryPagesObjCViewController ( )
2019-02-28 15:29:31 -08:00
2020-04-24 20:58:20 -07:00
@ property ( nonatomic ) CGFloat statusBarHeight ;
2020-07-31 16:10:09 -07:00
@ property ( nonatomic ) BOOL wasNavigationBarHidden ;
2019-02-28 15:29:31 -08:00
@ property ( nonatomic , strong ) NSTimer * autoscrollTimer ;
@ property ( nonatomic , strong ) NSTimer * autoscrollViewTimer ;
2019-03-22 20:55:22 -07:00
@ property ( nonatomic , strong ) NSString * restoringStoryId ;
2019-02-28 15:29:31 -08:00
@ end
2021-01-29 20:10:53 -08:00
@ implementation StoryPagesObjCViewController
2012-11-05 15:12:42 -08:00
2020-09-23 21:30:31 -07:00
@ synthesize appDelegate ;
2021-01-29 20:10:53 -08:00
@ synthesize currentPage , nextPage , previousPage ;
2013-04-10 21:06:17 -07:00
@ synthesize circularProgressView ;
2013-02-27 18:04:03 -08:00
@ synthesize separatorBarButton ;
@ synthesize spacerBarButton , spacer2BarButton , spacer3BarButton ;
2012-11-05 17:16:10 -08:00
@ synthesize buttonPrevious ;
@ synthesize buttonNext ;
@ synthesize buttonAction ;
2013-05-29 13:36:39 -07:00
@ synthesize buttonText ;
2013-07-19 18:19:30 -07:00
@ synthesize buttonSend ;
2012-11-05 17:16:10 -08:00
@ synthesize fontSettingsButton ;
@ synthesize originalStoryButton ;
@ synthesize subscribeButton ;
@ synthesize buttonBack ;
2021-01-29 20:10:53 -08:00
@ synthesize bottomSize ;
@ synthesize bottomSizeHeightConstraint ;
2012-11-05 17:16:10 -08:00
@ synthesize loadingIndicator ;
2021-01-29 20:10:53 -08:00
@ synthesize inTouchMove ;
2012-11-08 18:30:45 -08:00
@ synthesize isDraggingScrollview ;
2012-12-13 16:41:52 -08:00
@ synthesize waitingForNextUnreadFromServer ;
2012-11-09 14:13:44 -08:00
@ synthesize storyHUD ;
2012-11-14 17:31:52 -08:00
@ synthesize scrollingToPage ;
2013-03-06 14:29:40 -08:00
@ synthesize traverseView ;
2014-01-30 20:28:08 -08:00
@ synthesize isAnimatedIntoPlace ;
2013-04-26 13:51:03 -07:00
@ synthesize progressView , progressViewContainer ;
2013-03-07 10:55:23 -05:00
@ synthesize traversePinned , traverseFloating ;
2021-01-29 20:10:53 -08:00
@ synthesize traverseBottomConstraint ;
@ synthesize scrollBottomConstraint ;
2012-11-05 15:12:42 -08:00
- ( id ) initWithNibName : ( NSString * ) nibNameOrNil bundle : ( NSBundle * ) nibBundleOrNil {
self = [ super initWithNibName : nibNameOrNil bundle : nibBundleOrNil ] ;
if ( self ) {
// Custom initialization
}
return self ;
}
2012-11-05 18:23:45 -08:00
- ( void ) viewDidLoad {
2014-09-18 11:25:51 -07:00
[ super viewDidLoad ] ;
2017-04-03 16:07:01 -07:00
appDelegate = [ NewsBlurAppDelegate sharedAppDelegate ] ;
2021-01-29 20:10:53 -08:00
currentPage = [ [ StoryDetailViewController alloc ]
initWithNibName : @ "StoryDetailViewController"
bundle : nil ] ;
nextPage = [ [ StoryDetailViewController alloc ]
initWithNibName : @ "StoryDetailViewController"
bundle : nil ] ;
previousPage = [ [ StoryDetailViewController alloc ]
initWithNibName : @ "StoryDetailViewController"
bundle : nil ] ;
currentPage . appDelegate = appDelegate ;
nextPage . appDelegate = appDelegate ;
previousPage . appDelegate = appDelegate ;
currentPage . view . frame = self . scrollView . frame ;
nextPage . view . frame = self . scrollView . frame ;
previousPage . view . frame = self . scrollView . frame ;
2012-11-14 17:31:52 -08:00
2015-12-01 16:51:18 -08:00
// NSLog ( @ "Scroll view content inset: %@" , NSStringFromCGRect ( self . scrollView . bounds ) ) ;
// NSLog ( @ "Scroll view frame pre: %@" , NSStringFromCGRect ( self . scrollView . frame ) ) ;
2021-01-29 20:10:53 -08:00
[ self . scrollView addSubview : currentPage . view ] ;
[ self . scrollView addSubview : nextPage . view ] ;
[ self . scrollView addSubview : previousPage . view ] ;
[ self addChildViewController : currentPage ] ;
[ self addChildViewController : nextPage ] ;
[ self addChildViewController : previousPage ] ;
2012-11-05 15:12:42 -08:00
[ self . scrollView setPagingEnabled : YES ] ;
[ self . scrollView setScrollEnabled : YES ] ;
[ self . scrollView setShowsHorizontalScrollIndicator : NO ] ;
[ self . scrollView setShowsVerticalScrollIndicator : NO ] ;
2018-08-30 16:33:42 -07:00
[ self . scrollView setAlwaysBounceHorizontal : self . isHorizontal ] ;
[ self . scrollView setAlwaysBounceVertical : ! self . isHorizontal ] ;
2018-11-29 13:35:44 -08:00
2020-09-25 20:31:01 -07:00
if ( [ [ UIDevice currentDevice ] userInterfaceIdiom ] = = UIUserInterfaceIdiomPad ) {
self . scrollView . contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever ;
2018-11-29 13:35:44 -08:00
}
2015-12-01 16:51:18 -08:00
// NSLog ( @ "Scroll view frame post: %@" , NSStringFromCGRect ( self . scrollView . frame ) ) ;
// NSLog ( @ "Scroll view parent: %@" , NSStringFromCGRect ( currentPage . view . frame ) ) ;
2015-03-12 19:43:39 -07:00
[ self . scrollView sizeToFit ] ;
2015-12-01 16:51:18 -08:00
// NSLog ( @ "Scroll view frame post 2: %@" , NSStringFromCGRect ( self . scrollView . frame ) ) ;
2012-11-05 17:16:10 -08:00
2020-09-25 20:31:01 -07:00
self . statusBarHeight = self . view . window . windowScene . statusBarManager . statusBarFrame . size . height ;
2020-04-24 20:58:20 -07:00
2015-12-15 12:37:18 -08:00
// adding HUD for progress bar
2013-04-12 13:06:47 -07:00
CGFloat radius = 8 ;
2013-04-10 21:06:17 -07:00
circularProgressView = [ [ THCircularProgressView alloc ]
2013-05-30 16:31:57 -07:00
initWithCenter : CGPointMake ( self . buttonNext . frame . origin . x + 2 * radius ,
2013-04-10 21:06:17 -07:00
self . traverseView . frame . size . height / 2 )
radius : radius
lineWidth : radius / 4.0 f
progressMode : THProgressModeFill
2013-04-12 13:06:47 -07:00
progressColor : [ UIColor colorWithRed : 0.612 f green : 0.62 f blue : 0.596 f alpha : 0.4 f ]
2013-04-10 21:06:17 -07:00
progressBackgroundMode : THProgressBackgroundModeCircumference
2013-07-19 17:53:52 -07:00
progressBackgroundColor : [ UIColor colorWithRed : 0.312 f green : 0.32 f blue : 0.296 f alpha : .04 f ]
2013-04-10 21:06:17 -07:00
percentage : 20 ] ;
2013-05-30 16:31:57 -07:00
circularProgressView . autoresizingMask = UIViewAutoresizingFlexibleLeftMargin ;
2013-04-10 21:06:17 -07:00
[ self . traverseView addSubview : circularProgressView ] ;
2013-10-03 13:54:15 -07:00
UIView * tapIndicator = [ [ UIView alloc ]
initWithFrame : CGRectMake ( circularProgressView . frame . origin . x -
circularProgressView . frame . size . width / 2 ,
circularProgressView . frame . origin . y -
circularProgressView . frame . size . height / 2 ,
circularProgressView . frame . size . width * 2 ,
circularProgressView . frame . size . height * 2 ) ] ;
UITapGestureRecognizer * tap = [ [ UITapGestureRecognizer alloc ]
initWithTarget : self
action : @ selector ( tapProgressBar : ) ] ;
2013-05-28 18:07:19 -07:00
[ tapIndicator addGestureRecognizer : tap ] ;
2013-05-30 16:31:57 -07:00
tapIndicator . autoresizingMask = UIViewAutoresizingFlexibleLeftMargin ;
2013-05-28 18:07:19 -07:00
[ self . traverseView insertSubview : tapIndicator aboveSubview : circularProgressView ] ;
2013-04-23 11:52:34 -07:00
self . loadingIndicator . frame = self . circularProgressView . frame ;
2013-04-10 21:06:17 -07:00
2013-02-27 18:04:03 -08:00
spacerBarButton = [ [ UIBarButtonItem alloc ]
2013-10-03 13:54:15 -07:00
initWithBarButtonSystemItem : UIBarButtonSystemItemFixedSpace
target : nil action : nil ] ;
2013-02-27 18:04:03 -08:00
spacerBarButton . width = -12 ;
spacer2BarButton = [ [ UIBarButtonItem alloc ]
2013-10-03 13:54:15 -07:00
initWithBarButtonSystemItem : UIBarButtonSystemItemFixedSpace
target : nil action : nil ] ;
spacer2BarButton . width = -6 ;
2013-02-27 18:04:03 -08:00
spacer3BarButton = [ [ UIBarButtonItem alloc ]
2013-10-03 13:54:15 -07:00
initWithBarButtonSystemItem : UIBarButtonSystemItemFixedSpace
target : nil action : nil ] ;
spacer3BarButton . width = -6 ;
2012-11-05 17:16:10 -08:00
2013-02-27 18:04:03 -08:00
UIImage * separatorImage = [ UIImage imageNamed : @ "bar-separator.png" ] ;
2016-03-01 12:31:22 -05:00
if ( [ ThemeManager themeManager ] . isDarkTheme ) {
separatorImage = [ UIImage imageNamed : @ "bar_separator_dark" ] ;
}
2013-10-03 13:54:15 -07:00
separatorBarButton = [ UIBarButtonItem barItemWithImage : separatorImage
target : nil
action : nil ] ;
2013-02-27 18:04:03 -08:00
[ separatorBarButton setEnabled : NO ] ;
2015-11-03 22:21:18 -08:00
separatorBarButton . isAccessibilityElement = NO ;
2012-11-05 17:16:10 -08:00
2022-08-17 21:48:20 -07:00
UIImage * settingsImage = [ Utilities imageNamed : @ "settings" sized : 30 ] ;
2013-10-03 13:54:15 -07:00
fontSettingsButton = [ UIBarButtonItem barItemWithImage : settingsImage
target : self
action : @ selector ( toggleFontSize : ) ] ;
2015-11-03 22:21:18 -08:00
fontSettingsButton . accessibilityLabel = @ "Story settings" ;
2012-11-05 17:16:10 -08:00
2013-02-27 18:04:03 -08:00
UIImage * markreadImage = [ UIImage imageNamed : @ "original_button.png" ] ;
2013-10-03 13:54:15 -07:00
originalStoryButton = [ UIBarButtonItem barItemWithImage : markreadImage
target : self
action : @ selector ( showOriginalSubview : ) ] ;
2015-11-03 22:21:18 -08:00
originalStoryButton . accessibilityLabel = @ "Show original story" ;
2017-11-01 22:19:26 -07:00
separatorBarButton2 = [ UIBarButtonItem barItemWithImage : separatorImage
target : nil
action : nil ] ;
[ separatorBarButton2 setEnabled : NO ] ;
separatorBarButton2 . isAccessibilityElement = NO ;
2012-11-05 17:16:10 -08:00
2017-11-01 22:19:26 -07:00
UIImage * markReadImage = [ UIImage imageNamed : @ "markread.png" ] ;
markReadBarButton = [ UIBarButtonItem barItemWithImage : markReadImage
target : self
action : @ selector ( markAllRead : ) ] ;
markReadBarButton . accessibilityLabel = @ "Mark all as read" ;
2012-11-05 17:16:10 -08:00
UIBarButtonItem * subscribeBtn = [ [ UIBarButtonItem alloc ]
initWithTitle : @ "Follow User"
2016-10-05 21:03:32 -07:00
style : UIBarButtonItemStylePlain
2012-11-05 17:16:10 -08:00
target : self
action : @ selector ( subscribeToBlurblog )
] ;
self . subscribeButton = subscribeBtn ;
2015-10-28 21:50:23 -07:00
self . notifier = [ [ NBNotifier alloc ] initWithTitle : @ "Fetching text..."
2021-01-29 20:10:53 -08:00
withOffset : CGPointMake ( 0.0 , 0.0 / * self . bottomSize . frame . size . height * / ) ] ;
2015-10-28 21:50:23 -07:00
[ self . view addSubview : self . notifier ] ;
2017-10-30 11:30:12 -07:00
[ self . view addConstraint : [ NSLayoutConstraint constraintWithItem : self . notifier attribute : NSLayoutAttributeWidth relatedBy : NSLayoutRelationEqual toItem : self . view attribute : NSLayoutAttributeWidth multiplier : 1.0 constant : 0 ] ] ;
[ self . view addConstraint : [ NSLayoutConstraint constraintWithItem : self . notifier attribute : NSLayoutAttributeLeading relatedBy : NSLayoutRelationEqual toItem : self . view attribute : NSLayoutAttributeLeading multiplier : 1.0 constant : 0 ] ] ;
[ self . view addConstraint : [ NSLayoutConstraint constraintWithItem : self . notifier attribute : NSLayoutAttributeHeight relatedBy : NSLayoutRelationEqual toItem : nil attribute : NSLayoutAttributeNotAnAttribute multiplier : 1.0 constant : NOTIFIER_HEIGHT ] ] ;
2017-10-30 18:32:59 -07:00
self . notifier . topOffsetConstraint = [ NSLayoutConstraint constraintWithItem : self . notifier attribute : NSLayoutAttributeTop relatedBy : NSLayoutRelationEqual toItem : self . view attribute : NSLayoutAttributeBottom multiplier : 1.0 constant : 0 ] ;
[ self . view addConstraint : self . notifier . topOffsetConstraint ] ;
2015-10-28 21:50:23 -07:00
[ self . notifier hideNow ] ;
2012-11-05 17:16:10 -08:00
2022-02-01 20:40:07 -08:00
self . traverseBottomConstraint . constant = 0 ;
2020-05-26 14:13:46 -07:00
2020-08-25 21:46:23 -07:00
if ( [ [ UIDevice currentDevice ] userInterfaceIdiom ] = = UIUserInterfaceIdiomPhone ) {
2021-01-30 12:49:07 -08:00
appDelegate . detailViewController . navigationItem . rightBarButtonItems = [ NSArray arrayWithObjects :
2013-10-11 17:46:09 -07:00
originalStoryButton ,
separatorBarButton ,
fontSettingsButton , nil ] ;
2013-03-04 18:21:10 -08:00
}
2012-11-08 18:30:45 -08:00
[ self . scrollView addObserver : self forKeyPath : @ "contentOffset"
options : NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context : nil ] ;
2013-03-04 17:15:50 -08:00
2020-09-25 20:31:01 -07:00
_orientation = self . view . window . windowScene . interfaceOrientation ;
2019-03-22 20:55:22 -07:00
2022-03-29 21:20:41 -07:00
[ self addKeyCommandWithInput : UIKeyInputDownArrow modifierFlags : 0 action : @ selector ( changeToNextPage : ) discoverabilityTitle : @ "Next Story" wantPriority : YES ] ;
2015-11-21 23:23:37 -05:00
[ self addKeyCommandWithInput : @ "j" modifierFlags : 0 action : @ selector ( changeToNextPage : ) discoverabilityTitle : @ "Next Story" ] ;
2022-03-29 21:20:41 -07:00
[ self addKeyCommandWithInput : UIKeyInputUpArrow modifierFlags : 0 action : @ selector ( changeToPreviousPage : ) discoverabilityTitle : @ "Previous Story" wantPriority : YES ] ;
2015-11-21 23:23:37 -05:00
[ self addKeyCommandWithInput : @ "k" modifierFlags : 0 action : @ selector ( changeToPreviousPage : ) discoverabilityTitle : @ "Previous Story" ] ;
[ self addKeyCommandWithInput : @ "\r" modifierFlags : UIKeyModifierShift action : @ selector ( toggleTextView : ) discoverabilityTitle : @ "Text View" ] ;
[ self addKeyCommandWithInput : @ " " modifierFlags : 0 action : @ selector ( scrollPageDown : ) discoverabilityTitle : @ "Page Down" ] ;
[ self addKeyCommandWithInput : @ " " modifierFlags : UIKeyModifierShift action : @ selector ( scrollPageUp : ) discoverabilityTitle : @ "Page Up" ] ;
[ self addKeyCommandWithInput : @ "n" modifierFlags : 0 action : @ selector ( doNextUnreadStory : ) discoverabilityTitle : @ "Next Unread Story" ] ;
[ self addKeyCommandWithInput : @ "u" modifierFlags : 0 action : @ selector ( toggleStoryUnread : ) discoverabilityTitle : @ "Toggle Read/Unread" ] ;
[ self addKeyCommandWithInput : @ "m" modifierFlags : 0 action : @ selector ( toggleStoryUnread : ) discoverabilityTitle : @ "Toggle Read/Unread" ] ;
[ self addKeyCommandWithInput : @ "s" modifierFlags : 0 action : @ selector ( toggleStorySaved : ) discoverabilityTitle : @ "Save/Unsave Story" ] ;
[ self addKeyCommandWithInput : @ "o" modifierFlags : 0 action : @ selector ( showOriginalSubview : ) discoverabilityTitle : @ "Open in Browser" ] ;
[ self addKeyCommandWithInput : @ "v" modifierFlags : 0 action : @ selector ( showOriginalSubview : ) discoverabilityTitle : @ "Open in Browser" ] ;
[ self addKeyCommandWithInput : @ "s" modifierFlags : UIKeyModifierShift action : @ selector ( openShareDialog ) discoverabilityTitle : @ "Share This Story" ] ;
[ self addKeyCommandWithInput : @ "c" modifierFlags : 0 action : @ selector ( scrolltoComment ) discoverabilityTitle : @ "Scroll to Comments" ] ;
2015-11-24 15:39:07 -05:00
[ self addKeyCommandWithInput : @ "t" modifierFlags : 0 action : @ selector ( openStoryTrainerFromKeyboard : ) discoverabilityTitle : @ "Open Story Trainer" ] ;
2012-11-05 15:12:42 -08:00
}
- ( void ) viewWillAppear : ( BOOL ) animated {
2014-09-18 11:25:51 -07:00
[ super viewWillAppear : animated ] ;
2020-05-26 14:13:46 -07:00
[ self updateTheme ] ;
2019-02-28 15:29:31 -08:00
[ self updateAutoscrollButtons ] ;
2015-12-07 16:09:49 -08:00
[ self updateTraverseBackground ] ;
2012-11-08 17:39:32 -08:00
[ self setNextPreviousButtons ] ;
2013-12-11 18:06:22 -08:00
[ self setTextButton ] ;
2020-04-22 19:53:17 -07:00
[ self updateStatusBarState ] ;
2019-02-27 13:33:38 -08:00
self . currentlyTogglingNavigationBar = NO ;
2013-12-06 16:19:27 -08:00
NSUserDefaults * userPreferences = [ NSUserDefaults standardUserDefaults ] ;
BOOL swipeEnabled = [ [ userPreferences stringForKey : @ "story_detail_swipe_left_edge" ]
isEqualToString : @ "pop_to_story_list" ] ;;
2020-07-31 16:10:09 -07:00
2021-02-27 20:29:58 -08:00
appDelegate . detailViewController . parentNavigationController . interactivePopGestureRecognizer . enabled = swipeEnabled ;
2020-06-20 21:31:21 -07:00
2015-11-28 22:07:38 -08:00
if ( self . isPhoneOrCompact ) {
2014-02-12 20:09:37 -08:00
if ( ! appDelegate . storiesCollection . isSocialView ) {
2012-11-13 13:07:36 -08:00
UIImage * titleImage ;
2014-02-12 20:09:37 -08:00
if ( appDelegate . storiesCollection . isSocialRiverView &&
[ appDelegate . storiesCollection . activeFolder isEqualToString : @ "river_global" ] ) {
#1693 (2022 Redesign)
- Laboriously updated the icons (finding the names in the web inspector, updating the code, inspecting the colors, setting those separately, dealing with scaling issues, etc etc).
- Let me know if you spot any icons that I missed, or unscaled icons (they have to be explicitly sized, otherwise appear huge).
- More space between story title and story content.
- More space when reading a folder.
- Added Compact/Comfortable to feed detail menu.
- Changing Compact/Comfortable also adjusts the feed detail list.
- Adjusted the color of the story content etc in the feed detail list.
- Removed top and bottom borders from feed title gradient in story detail.
- More space in story detail header.
- The feed detail is offset when selected.
- Updated the feeds social, search, and saved background colors.
- Unread counts no longer have a shadow, and have more space.
- Folders and feeds remain selected in the feeds list when returning from a story or refreshing.
- Folders in the feeds list no longer have a different background color.
- The folders and feeds highlight is now rounded and unbordered like on web.
2022-07-20 21:35:16 -07:00
titleImage = [ UIImage imageNamed : @ "global-shares" ] ;
2014-02-12 20:09:37 -08:00
} else if ( appDelegate . storiesCollection . isSocialRiverView &&
[ appDelegate . storiesCollection . activeFolder isEqualToString : @ "river_blurblogs" ] ) {
#1693 (2022 Redesign)
- Laboriously updated the icons (finding the names in the web inspector, updating the code, inspecting the colors, setting those separately, dealing with scaling issues, etc etc).
- Let me know if you spot any icons that I missed, or unscaled icons (they have to be explicitly sized, otherwise appear huge).
- More space between story title and story content.
- More space when reading a folder.
- Added Compact/Comfortable to feed detail menu.
- Changing Compact/Comfortable also adjusts the feed detail list.
- Adjusted the color of the story content etc in the feed detail list.
- Removed top and bottom borders from feed title gradient in story detail.
- More space in story detail header.
- The feed detail is offset when selected.
- Updated the feeds social, search, and saved background colors.
- Unread counts no longer have a shadow, and have more space.
- Folders and feeds remain selected in the feeds list when returning from a story or refreshing.
- Folders in the feeds list no longer have a different background color.
- The folders and feeds highlight is now rounded and unbordered like on web.
2022-07-20 21:35:16 -07:00
titleImage = [ UIImage imageNamed : @ "all-shares" ] ;
2014-02-12 20:09:37 -08:00
} else if ( appDelegate . storiesCollection . isRiverView &&
[ appDelegate . storiesCollection . activeFolder isEqualToString : @ "everything" ] ) {
#1693 (2022 Redesign)
- Laboriously updated the icons (finding the names in the web inspector, updating the code, inspecting the colors, setting those separately, dealing with scaling issues, etc etc).
- Let me know if you spot any icons that I missed, or unscaled icons (they have to be explicitly sized, otherwise appear huge).
- More space between story title and story content.
- More space when reading a folder.
- Added Compact/Comfortable to feed detail menu.
- Changing Compact/Comfortable also adjusts the feed detail list.
- Adjusted the color of the story content etc in the feed detail list.
- Removed top and bottom borders from feed title gradient in story detail.
- More space in story detail header.
- The feed detail is offset when selected.
- Updated the feeds social, search, and saved background colors.
- Unread counts no longer have a shadow, and have more space.
- Folders and feeds remain selected in the feeds list when returning from a story or refreshing.
- Folders in the feeds list no longer have a different background color.
- The folders and feeds highlight is now rounded and unbordered like on web.
2022-07-20 21:35:16 -07:00
titleImage = [ UIImage imageNamed : @ "all-stories" ] ;
2017-11-05 22:07:43 -08:00
} else if ( appDelegate . storiesCollection . isRiverView &&
[ appDelegate . storiesCollection . activeFolder isEqualToString : @ "infrequent" ] ) {
2021-03-26 21:51:02 -07:00
titleImage = [ UIImage imageNamed : @ "ak-icon-infrequent.png" ] ;
2014-05-20 15:29:16 -07:00
} else if ( appDelegate . storiesCollection . isSavedView &&
appDelegate . storiesCollection . activeSavedStoryTag ) {
titleImage = [ UIImage imageNamed : @ "tag.png" ] ;
2022-03-09 19:16:43 -07:00
} else if ( [ appDelegate . storiesCollection . activeFolder isEqualToString : @ "widget_stories" ] ) {
titleImage = [ UIImage imageNamed : @ "g_icn_folder_widget.png" ] ;
2014-10-22 16:39:37 -07:00
} else if ( [ appDelegate . storiesCollection . activeFolder isEqualToString : @ "read_stories" ] ) {
#1693 (2022 Redesign)
- Laboriously updated the icons (finding the names in the web inspector, updating the code, inspecting the colors, setting those separately, dealing with scaling issues, etc etc).
- Let me know if you spot any icons that I missed, or unscaled icons (they have to be explicitly sized, otherwise appear huge).
- More space between story title and story content.
- More space when reading a folder.
- Added Compact/Comfortable to feed detail menu.
- Changing Compact/Comfortable also adjusts the feed detail list.
- Adjusted the color of the story content etc in the feed detail list.
- Removed top and bottom borders from feed title gradient in story detail.
- More space in story detail header.
- The feed detail is offset when selected.
- Updated the feeds social, search, and saved background colors.
- Unread counts no longer have a shadow, and have more space.
- Folders and feeds remain selected in the feeds list when returning from a story or refreshing.
- Folders in the feeds list no longer have a different background color.
- The folders and feeds highlight is now rounded and unbordered like on web.
2022-07-20 21:35:16 -07:00
titleImage = [ UIImage imageNamed : @ "indicator-unread" ] ;
2020-05-27 21:26:44 -07:00
} else if ( [ appDelegate . storiesCollection . activeFolder isEqualToString : @ "saved_searches" ] ) {
#1693 (2022 Redesign)
- Laboriously updated the icons (finding the names in the web inspector, updating the code, inspecting the colors, setting those separately, dealing with scaling issues, etc etc).
- Let me know if you spot any icons that I missed, or unscaled icons (they have to be explicitly sized, otherwise appear huge).
- More space between story title and story content.
- More space when reading a folder.
- Added Compact/Comfortable to feed detail menu.
- Changing Compact/Comfortable also adjusts the feed detail list.
- Adjusted the color of the story content etc in the feed detail list.
- Removed top and bottom borders from feed title gradient in story detail.
- More space in story detail header.
- The feed detail is offset when selected.
- Updated the feeds social, search, and saved background colors.
- Unread counts no longer have a shadow, and have more space.
- Folders and feeds remain selected in the feeds list when returning from a story or refreshing.
- Folders in the feeds list no longer have a different background color.
- The folders and feeds highlight is now rounded and unbordered like on web.
2022-07-20 21:35:16 -07:00
titleImage = [ UIImage imageNamed : @ "search" ] ;
2014-05-20 15:29:16 -07:00
} else if ( [ appDelegate . storiesCollection . activeFolder isEqualToString : @ "saved_stories" ] ) {
#1693 (2022 Redesign)
- Laboriously updated the icons (finding the names in the web inspector, updating the code, inspecting the colors, setting those separately, dealing with scaling issues, etc etc).
- Let me know if you spot any icons that I missed, or unscaled icons (they have to be explicitly sized, otherwise appear huge).
- More space between story title and story content.
- More space when reading a folder.
- Added Compact/Comfortable to feed detail menu.
- Changing Compact/Comfortable also adjusts the feed detail list.
- Adjusted the color of the story content etc in the feed detail list.
- Removed top and bottom borders from feed title gradient in story detail.
- More space in story detail header.
- The feed detail is offset when selected.
- Updated the feeds social, search, and saved background colors.
- Unread counts no longer have a shadow, and have more space.
- Folders and feeds remain selected in the feeds list when returning from a story or refreshing.
- Folders in the feeds list no longer have a different background color.
- The folders and feeds highlight is now rounded and unbordered like on web.
2022-07-20 21:35:16 -07:00
titleImage = [ UIImage imageNamed : @ "saved-stories" ] ;
2014-02-12 20:09:37 -08:00
} else if ( appDelegate . storiesCollection . isRiverView ) {
#1693 (2022 Redesign)
- Laboriously updated the icons (finding the names in the web inspector, updating the code, inspecting the colors, setting those separately, dealing with scaling issues, etc etc).
- Let me know if you spot any icons that I missed, or unscaled icons (they have to be explicitly sized, otherwise appear huge).
- More space between story title and story content.
- More space when reading a folder.
- Added Compact/Comfortable to feed detail menu.
- Changing Compact/Comfortable also adjusts the feed detail list.
- Adjusted the color of the story content etc in the feed detail list.
- Removed top and bottom borders from feed title gradient in story detail.
- More space in story detail header.
- The feed detail is offset when selected.
- Updated the feeds social, search, and saved background colors.
- Unread counts no longer have a shadow, and have more space.
- Folders and feeds remain selected in the feeds list when returning from a story or refreshing.
- Folders in the feeds list no longer have a different background color.
- The folders and feeds highlight is now rounded and unbordered like on web.
2022-07-20 21:35:16 -07:00
titleImage = [ UIImage imageNamed : @ "folder-open" ] ;
2012-11-13 13:07:36 -08:00
} else {
NSString * feedIdStr = [ NSString stringWithFormat : @ "%@" ,
[ appDelegate . activeStory objectForKey : @ "story_feed_id" ] ] ;
2014-02-24 18:56:51 -08:00
titleImage = [ appDelegate getFavicon : feedIdStr ] ;
2012-11-13 13:07:36 -08:00
}
UIImageView * titleImageView = [ [ UIImageView alloc ] initWithImage : titleImage ] ;
2017-10-03 18:39:06 -07:00
UIImageView * titleImageViewWrapper = [ [ UIImageView alloc ] init ] ;
2014-02-12 20:09:37 -08:00
if ( appDelegate . storiesCollection . isRiverView ) {
2012-11-13 13:07:36 -08:00
titleImageView . frame = CGRectMake ( 0.0 , 2.0 , 22.0 , 22.0 ) ;
} else {
titleImageView . frame = CGRectMake ( 0.0 , 2.0 , 16.0 , 16.0 ) ;
}
titleImageView . hidden = YES ;
titleImageView . contentMode = UIViewContentModeScaleAspectFit ;
2017-10-03 18:39:06 -07:00
[ titleImageViewWrapper addSubview : titleImageView ] ;
[ titleImageViewWrapper setFrame : titleImageView . frame ] ;
2021-01-30 12:49:07 -08:00
if ( ! appDelegate . detailViewController . navigationItem . titleView ) {
appDelegate . detailViewController . navigationItem . titleView = titleImageViewWrapper ;
2014-01-07 18:26:17 -08:00
}
2012-11-13 13:07:36 -08:00
titleImageView . hidden = NO ;
} else {
NSString * feedIdStr = [ NSString stringWithFormat : @ "%@" ,
2014-02-12 20:09:37 -08:00
[ appDelegate . storiesCollection . activeFeed objectForKey : @ "id" ] ] ;
2014-02-24 18:56:51 -08:00
UIImage * titleImage = [ appDelegate getFavicon : feedIdStr ] ;
2012-11-13 13:07:36 -08:00
titleImage = [ Utilities roundCorneredImage : titleImage radius : 6 ] ;
2017-10-03 18:39:06 -07:00
UIImageView * titleImageView = [ [ UIImageView alloc ] initWithFrame : CGRectZero ] ;
UIImageView * titleImageViewWrapper = [ [ UIImageView alloc ] init ] ;
titleImageView . frame = CGRectMake ( 0.0 , 0.0 , 28.0 , 28.0 ) ;
titleImageView . contentMode = UIViewContentModeScaleAspectFit ;
[ titleImageView setImage : titleImage ] ;
[ titleImageViewWrapper addSubview : titleImageView ] ;
[ titleImageViewWrapper setFrame : titleImageView . frame ] ;
2021-01-30 12:49:07 -08:00
appDelegate . detailViewController . navigationItem . titleView = titleImageViewWrapper ;
2012-11-13 13:07:36 -08:00
}
}
2012-12-18 17:29:23 -08:00
2019-02-28 15:29:31 -08:00
self . autoscrollView . alpha = 0 ;
2021-01-29 20:10:53 -08:00
previousPage . view . hidden = YES ;
2013-09-05 16:34:39 -07:00
self . traverseView . alpha = 1 ;
2014-01-30 20:28:08 -08:00
self . isAnimatedIntoPlace = NO ;
2021-01-29 20:10:53 -08:00
currentPage . view . hidden = NO ;
2014-01-08 13:38:18 -08:00
2021-01-30 12:49:07 -08:00
self . navigationController . navigationItem . backBarButtonItem = [ [ UIBarButtonItem alloc ]
2014-01-08 13:38:18 -08:00
initWithTitle : @ " "
style : UIBarButtonItemStylePlain
target : nil action : nil ] ;
2015-09-22 18:20:48 -07:00
2020-09-25 20:31:01 -07:00
UIInterfaceOrientation orientation = self . view . window . windowScene . interfaceOrientation ;
2015-09-22 18:20:48 -07:00
[ self layoutForInterfaceOrientation : orientation ] ;
2015-12-01 15:17:46 -08:00
[ self reorientPages ] ;
2012-11-05 15:12:42 -08:00
}
2012-11-05 17:16:10 -08:00
- ( void ) viewDidAppear : ( BOOL ) animated {
2014-09-18 11:25:51 -07:00
[ super viewDidAppear : animated ] ;
2012-11-05 17:16:10 -08:00
// set the subscribeButton flag
2016-12-06 16:03:40 -08:00
if ( appDelegate . isTryFeedView && ! self . isPhoneOrCompact &&
! [ [ appDelegate . storiesCollection . activeFeed objectForKey : @ "username" ] isKindOfClass : [ NSNull class ] ] &&
[ appDelegate . storiesCollection . activeFeed objectForKey : @ "username" ] ) {
2013-10-03 13:54:15 -07:00
self . subscribeButton . title = [ NSString stringWithFormat : @ "Follow %@" ,
2014-02-12 20:09:37 -08:00
[ appDelegate . storiesCollection . activeFeed objectForKey : @ "username" ] ] ;
2021-01-30 12:49:07 -08:00
appDelegate . detailViewController . navigationItem . leftBarButtonItem = self . subscribeButton ;
2012-11-05 17:16:10 -08:00
}
appDelegate . isTryFeedView = NO ;
2015-11-30 18:12:10 -08:00
[ self reorientPages ] ;
2021-01-29 20:10:53 -08:00
previousPage . view . hidden = NO ;
2019-02-28 15:29:31 -08:00
2015-11-21 23:23:37 -05:00
[ self becomeFirstResponder ] ;
2013-09-25 10:47:35 -07:00
}
2015-09-23 13:02:25 -07:00
- ( void ) viewDidLayoutSubviews {
2021-05-22 16:13:25 -07:00
CGRect frame = self . scrollView . frame ;
if ( frame . size . width ! = floor ( frame . size . width ) ) {
self . scrollView . frame = CGRectMake ( frame . origin . x , frame . origin . y , floor ( frame . size . width ) , floor ( frame . size . height ) ) ;
}
2022-03-31 22:01:03 -07:00
[ self reorientPages ] ;
2015-09-23 13:02:25 -07:00
[ super viewDidLayoutSubviews ] ;
}
2014-02-21 16:06:49 -08:00
- ( void ) viewDidDisappear : ( BOOL ) animated {
2014-09-18 11:25:51 -07:00
[ super viewDidDisappear : animated ] ;
2022-10-27 15:19:31 -06:00
if ( ! appDelegate . detailViewController . storyTitlesInGrid ) {
appDelegate . detailViewController . navigationItem . leftBarButtonItem = nil ;
}
2014-02-21 16:06:49 -08:00
}
2013-09-25 10:47:35 -07:00
- ( void ) viewWillDisappear : ( BOOL ) animated {
2014-09-18 11:25:51 -07:00
[ super viewWillDisappear : animated ] ;
2021-01-29 20:10:53 -08:00
previousPage . view . hidden = YES ;
2021-02-27 20:29:58 -08:00
appDelegate . detailViewController . parentNavigationController . interactivePopGestureRecognizer . enabled = YES ;
[ appDelegate . detailViewController . parentNavigationController setNavigationBarHidden : NO animated : YES ] ;
2019-02-28 15:29:31 -08:00
self . autoscrollActive = NO ;
2012-11-05 17:16:10 -08:00
}
2015-11-22 21:11:23 -05:00
- ( BOOL ) becomeFirstResponder {
// delegate to current page
2021-01-29 20:10:53 -08:00
return [ currentPage becomeFirstResponder ] ;
2015-11-22 21:11:23 -05:00
}
2015-09-22 13:25:18 -07:00
- ( void ) viewWillTransitionToSize : ( CGSize ) size withTransitionCoordinator : ( id < UIViewControllerTransitionCoordinator > ) coordinator {
2015-09-22 16:34:24 -07:00
[ super viewWillTransitionToSize : size withTransitionCoordinator : coordinator ] ;
2017-11-06 21:13:07 -08:00
inRotation = YES ;
2015-09-22 13:25:18 -07:00
[ coordinator animateAlongsideTransition : ^ ( id < UIViewControllerTransitionCoordinatorContext > _Nonnull context ) {
2017-11-06 21:13:07 -08:00
// NSLog ( @ "---> Story page control is re-orienting: %@ / %@" , NSStringFromCGSize ( self . scrollView . bounds . size ) , NSStringFromCGSize ( size ) ) ;
2020-09-25 20:31:01 -07:00
UIInterfaceOrientation orientation = self . view . window . windowScene . interfaceOrientation ;
2020-09-22 17:28:14 -07:00
self -> _orientation = orientation ;
2015-09-22 13:25:18 -07:00
[ self layoutForInterfaceOrientation : orientation ] ;
[ self reorientPages ] ;
} completion : ^ ( id < UIViewControllerTransitionCoordinatorContext > _Nonnull context ) {
2017-11-06 21:13:07 -08:00
// NSLog ( @ "---> Story page control did re-orient: %@ / %@" , NSStringFromCGSize ( self . scrollView . bounds . size ) , NSStringFromCGSize ( size ) ) ;
2020-08-27 15:08:46 -07:00
self -> inRotation = NO ;
2020-04-22 19:31:08 -07:00
[ self updateStatusBarState ] ;
2017-11-06 21:13:07 -08:00
2016-06-16 17:10:04 -07:00
[ self . view setNeedsLayout ] ;
[ self . view layoutIfNeeded ] ;
2015-09-22 13:25:18 -07:00
} ] ;
}
2013-03-04 17:15:50 -08:00
- ( void ) layoutForInterfaceOrientation : ( UIInterfaceOrientation ) interfaceOrientation {
2014-09-22 12:35:38 -07:00
// NSLog ( @ "layout for stories: %@" , NSStringFromCGRect ( self . view . frame ) ) ;
2021-01-29 20:10:53 -08:00
if ( interfaceOrientation ! = _orientation ) {
_orientation = interfaceOrientation ;
if ( currentPage . pageIndex = = 0 ) {
previousPage . view . hidden = YES ;
}
}
2012-11-07 17:54:16 -08:00
}
2015-12-01 15:17:46 -08:00
- ( void ) viewWillLayoutSubviews {
[ super viewWillLayoutSubviews ] ;
2020-07-31 16:10:09 -07:00
2021-01-29 20:10:53 -08:00
if ( self . isNavigationBarHidden && ! self . shouldHideStatusBar ) {
self . scrollViewTopConstraint . constant = self . statusBarHeight ;
} else {
self . scrollViewTopConstraint . constant = 0 ;
}
2020-07-31 16:10:09 -07:00
2020-09-25 20:31:01 -07:00
UIInterfaceOrientation orientation = self . view . window . windowScene . interfaceOrientation ;
2015-12-01 15:17:46 -08:00
[ self layoutForInterfaceOrientation : orientation ] ;
}
2020-07-31 16:10:09 -07:00
- ( BOOL ) shouldHideStatusBar {
2021-02-12 19:50:35 -08:00
// Disabled for now , as not working currently .
return NO ;
2020-04-22 19:31:08 -07:00
2021-02-12 19:50:35 -08:00
// NSUserDefaults * preferences = [ NSUserDefaults standardUserDefaults ] ;
//
// return [ preferences boolForKey : @ "story_hide_status_bar" ] ;
2020-04-22 19:31:08 -07:00
}
2020-07-31 16:10:09 -07:00
- ( BOOL ) isNavigationBarHidden {
return self . navigationController . navigationBarHidden ;
}
- ( void ) updateStatusBarState {
BOOL isNavBarHidden = self . isNavigationBarHidden ;
2020-04-22 19:31:08 -07:00
2020-07-31 16:10:09 -07:00
self . statusBarBackgroundView . hidden = self . shouldHideStatusBar || ! isNavBarHidden || ! appDelegate . isPortrait ;
}
- ( BOOL ) prefersStatusBarHidden {
2020-04-22 19:31:08 -07:00
[ self updateStatusBarState ] ;
2020-07-31 16:10:09 -07:00
return self . shouldHideStatusBar && self . isNavigationBarHidden ;
iOS: #1137 (full screen reading)
Added a "Tap story" preference with "Toggle full screen" and "Do nothing" options; toggling is the default. This is only available on iPhone. When active, a single tap in a story, not on a link, image, movie, or button, will hide or show the status and navigation bars. On iPhones with a notch (iPhone X, XS, etc), the feed bar at the top is also hidden, so the story can scroll under the notch, using every bit of the screen.
2018-10-31 20:05:11 -07:00
}
2020-06-20 21:31:21 -07:00
- ( BOOL ) allowFullscreen {
2020-09-22 17:28:14 -07:00
if ( [ [ UIDevice currentDevice ] userInterfaceIdiom ] ! = UIUserInterfaceIdiomPhone || self . presentedViewController ! = nil ) {
2020-06-20 21:31:21 -07:00
return NO ;
}
2019-02-27 13:33:38 -08:00
NSUserDefaults * preferences = [ NSUserDefaults standardUserDefaults ] ;
2019-03-04 20:07:42 -08:00
return ( [ preferences boolForKey : @ "story_full_screen" ] || self . autoscrollAvailable ) && ! self . forceNavigationBarShown ;
2019-02-27 13:33:38 -08:00
}
2019-01-16 19:15:07 -08:00
- ( void ) setNavigationBarHidden : ( BOOL ) hide {
2019-01-24 20:04:00 -08:00
[ self setNavigationBarHidden : hide alsoTraverse : NO ] ;
}
- ( void ) setNavigationBarHidden : ( BOOL ) hide alsoTraverse : ( BOOL ) alsoTraverse {
2019-05-16 19:31:24 -07:00
if ( self . navigationController = = nil || self . navigationController . navigationBarHidden = = hide || self . currentlyTogglingNavigationBar ) {
2019-01-16 19:15:07 -08:00
return ;
}
self . currentlyTogglingNavigationBar = YES ;
2020-07-31 16:10:09 -07:00
self . wasNavigationBarHidden = hide ;
2019-01-16 19:15:07 -08:00
[ self . navigationController setNavigationBarHidden : hide animated : YES ] ;
2021-02-27 20:29:58 -08:00
NSUserDefaults * userPreferences = [ NSUserDefaults standardUserDefaults ] ;
BOOL swipeEnabled = [ [ userPreferences stringForKey : @ "story_detail_swipe_left_edge" ]
isEqualToString : @ "pop_to_story_list" ] ;;
appDelegate . detailViewController . parentNavigationController . interactivePopGestureRecognizer . enabled = swipeEnabled ;
if ( hide ) {
appDelegate . detailViewController . parentNavigationController . interactivePopGestureRecognizer . delegate = self ;
} else if ( appDelegate . feedDetailViewController . standardInteractivePopGestureDelegate ! = nil ) {
appDelegate . detailViewController . parentNavigationController . interactivePopGestureRecognizer . delegate = appDelegate . feedDetailViewController . standardInteractivePopGestureDelegate ;
}
2021-01-29 20:10:53 -08:00
CGPoint oldOffset = currentPage . webView . scrollView . contentOffset ;
2019-01-16 19:15:07 -08:00
CGFloat navHeight = self . navigationController . navigationBar . bounds . size . height ;
2021-02-12 19:50:35 -08:00
CGFloat statusAdjustment = 0.0 ;
2019-01-16 19:15:07 -08:00
2021-02-12 19:50:35 -08:00
// // The top inset is zero when the status bar is hidden , so using the bottom one to confirm .
// if ( self . view . safeAreaInsets . top > 0.0 || self . view . safeAreaInsets . bottom > 0.0 ) {
// statusAdjustment = 0.0 ;
// }
2019-01-16 19:15:07 -08:00
if ( oldOffset . y < 0.0 ) {
oldOffset . y = 0.0 ;
}
CGFloat sign = hide ? -1.0 : 1.0 ;
CGFloat absoluteAdjustment = navHeight + statusAdjustment ;
CGFloat totalAdjustment = sign * absoluteAdjustment ;
CGPoint newOffset = CGPointMake ( oldOffset . x , oldOffset . y + totalAdjustment ) ;
2019-01-24 20:04:00 -08:00
if ( alsoTraverse ) {
self . traversePinned = YES ;
self . traverseFloating = NO ;
if ( ! hide ) {
2022-02-01 20:40:07 -08:00
self . traverseBottomConstraint . constant = 0 ;
2019-01-24 20:04:00 -08:00
[ self . view layoutIfNeeded ] ;
}
}
2021-02-12 19:50:35 -08:00
self . currentPage . webView . scrollView . contentOffset = newOffset ;
[ self . appDelegate . detailViewController adjustForAutoscroll ] ;
if ( alsoTraverse ) {
[ self . view layoutIfNeeded ] ;
self . traverseView . alpha = hide ? 0 : 1 ;
2021-01-30 20:33:29 -08:00
2021-02-12 19:50:35 -08:00
if ( hide ) {
[ self hideAutoscrollImmediately ] ;
2019-01-24 20:04:00 -08:00
}
2021-02-12 19:50:35 -08:00
}
2019-01-16 19:15:07 -08:00
2021-02-12 19:50:35 -08:00
if ( ! self . isHorizontal ) {
dispatch_after ( dispatch_time ( DISPATCH_TIME _NOW , 0.5 * NSEC_PER _SEC ) ,
dispatch_get _main _queue ( ) , ^ {
[ self reorientPages ] ;
} ) ;
}
2021-08-24 21:01:28 -07:00
[ self . view layoutIfNeeded ] ;
2019-01-16 19:15:07 -08:00
[ UIView animateWithDuration : 0.2 animations : ^ {
[ self setNeedsStatusBarAppearanceUpdate ] ;
} completion : ^ ( BOOL finished ) {
self . currentlyTogglingNavigationBar = NO ;
2020-04-22 19:31:08 -07:00
[ self updateStatusBarState ] ;
2019-01-16 19:15:07 -08:00
} ] ;
}
2019-04-24 13:02:04 -07:00
- ( BOOL ) gestureRecognizerShouldBegin : ( UIGestureRecognizer * ) gestureRecognizer {
return YES ;
}
2019-05-28 19:40:15 -07:00
- ( BOOL ) gestureRecognizer : ( UIGestureRecognizer * ) gestureRecognizer shouldBeRequiredToFailByGestureRecognizer : ( UIGestureRecognizer * ) otherGestureRecognizer {
return ! [ otherGestureRecognizer isKindOfClass : [ UIScreenEdgePanGestureRecognizer class ] ] ;
}
2013-10-08 13:57:15 -07:00
- ( void ) highlightButton : ( UIButton * ) b {
2013-10-10 13:00:35 -07:00
if ( ! [ b isKindOfClass : [ UIButton class ] ] ) return ;
2013-10-08 13:57:15 -07:00
[ b setHighlighted : YES ] ;
}
- ( void ) unhighlightButton : ( UIButton * ) b {
2013-10-10 13:00:35 -07:00
if ( ! [ b isKindOfClass : [ UIButton class ] ] ) return ;
2013-10-08 13:57:15 -07:00
[ b setHighlighted : NO ] ;
}
- ( IBAction ) beginTouchDown : ( UIButton * ) sender {
[ self performSelector : @ selector ( highlightButton : ) withObject : sender afterDelay : 0.0 ] ;
}
- ( IBAction ) endTouchDown : ( UIButton * ) sender {
if ( ! sender ) return ;
[ self performSelector : @ selector ( unhighlightButton : ) withObject : sender afterDelay : 0.2 ] ;
}
2020-11-28 21:28:19 -08:00
- ( BOOL ) isPortraitOrientation {
return UIInterfaceOrientationIsPortrait ( self . view . window . windowScene . interfaceOrientation ) ;
}
2018-08-30 16:33:42 -07:00
- ( BOOL ) isHorizontal {
return [ [ [ NSUserDefaults standardUserDefaults ] objectForKey : @ "scroll_stories_horizontally" ] boolValue ] ;
}
2021-01-29 20:10:53 -08:00
- ( void ) resetPages {
2021-01-30 12:49:07 -08:00
appDelegate . detailViewController . navigationItem . titleView = nil ;
2014-01-07 18:26:17 -08:00
2021-01-29 20:10:53 -08:00
[ currentPage clearStory ] ;
[ nextPage clearStory ] ;
[ previousPage clearStory ] ;
2021-01-30 13:26:25 -08:00
[ currentPage hideStory ] ;
2012-12-11 12:01:49 -08:00
2021-01-29 20:10:53 -08:00
CGRect frame = self . scrollView . frame ;
self . scrollView . contentSize = frame . size ;
// NSLog ( @ "Pages are at: %f / %f / %f (%@)" , previousPage . view . frame . origin . x , currentPage . view . frame . origin . x , nextPage . view . frame . origin . x , NSStringFromCGRect ( frame ) ) ;
currentPage . view . frame = self . scrollView . frame ;
nextPage . view . frame = self . scrollView . frame ;
previousPage . view . frame = self . scrollView . frame ;
2013-10-11 17:46:09 -07:00
2021-01-29 20:10:53 -08:00
currentPage . pageIndex = -2 ;
nextPage . pageIndex = -2 ;
previousPage . pageIndex = -2 ;
2020-12-24 16:20:22 -08:00
}
2013-10-11 17:46:09 -07:00
- ( void ) hidePages {
2021-01-29 20:10:53 -08:00
[ currentPage hideStory ] ;
[ nextPage hideStory ] ;
[ previousPage hideStory ] ;
2012-11-07 17:54:16 -08:00
}
2012-11-13 12:28:16 -08:00
- ( void ) refreshPages {
2021-01-29 20:10:53 -08:00
NSInteger pageIndex = currentPage . pageIndex ;
2012-11-13 12:28:16 -08:00
[ self resizeScrollView ] ;
[ appDelegate adjustStoryDetailWebView ] ;
2021-01-29 20:10:53 -08:00
currentPage . pageIndex = -2 ;
nextPage . pageIndex = -2 ;
previousPage . pageIndex = -2 ;
2012-11-13 12:28:16 -08:00
[ self changePage : pageIndex animated : NO ] ;
[ MBProgressHUD hideHUDForView : self . view animated : YES ] ;
2015-10-28 21:50:23 -07:00
[ self . notifier hide ] ;
2012-11-13 12:28:16 -08:00
// self . scrollView . contentOffset = CGPointMake ( self . scrollView . frame . size . width * currentPage . pageIndex , 0 ) ;
}
2015-09-22 13:25:18 -07:00
- ( void ) reorientPages {
2022-04-01 21:18:54 -07:00
NSInteger currentIndex = currentPage . pageIndex ;
[ self resizeScrollView ] ; // Will change currentIndex , so preserve
2021-01-29 20:10:53 -08:00
[ self applyNewIndex : currentPage . pageIndex -1 pageController : previousPage supressRedraw : YES ] ;
[ self applyNewIndex : currentPage . pageIndex + 1 pageController : nextPage supressRedraw : YES ] ;
[ self applyNewIndex : currentPage . pageIndex pageController : currentPage supressRedraw : YES ] ;
2014-12-03 15:35:37 -08:00
2021-01-29 20:10:53 -08:00
// Scroll back to preserved index
CGRect frame = self . scrollView . bounds ;
if ( self . isHorizontal ) {
frame . origin . x = frame . size . width * currentIndex ;
frame . origin . y = 0 ;
} else {
frame . origin . x = 0 ;
frame . origin . y = ( frame . size . height * currentIndex ) - self . view . safeAreaInsets . bottom ;
}
[ self . scrollView scrollRectToVisible : frame animated : NO ] ;
2015-12-01 16:51:18 -08:00
// NSLog ( @ "---> Scrolling to story at: %@ %d-%d" , NSStringFromCGRect ( frame ) , currentPage . pageIndex , currentIndex ) ;
2014-11-30 21:24:42 -05:00
[ MBProgressHUD hideHUDForView : self . view animated : YES ] ;
2015-12-01 15:17:46 -08:00
[ self hideNotifier ] ;
2022-04-01 21:18:54 -07:00
2022-04-11 16:58:27 -07:00
if ( [ [ UIDevice currentDevice ] userInterfaceIdiom ] = = UIUserInterfaceIdiomPad ) {
[ currentPage realignScroll ] ;
}
2014-11-30 21:24:42 -05:00
}
2012-12-07 17:18:31 -08:00
- ( void ) refreshHeaders {
2021-01-29 20:10:53 -08:00
[ currentPage setActiveStoryAtIndex : [ appDelegate . storiesCollection
indexOfStoryId : currentPage . activeStoryId ] ] ;
[ nextPage setActiveStoryAtIndex : [ appDelegate . storiesCollection
indexOfStoryId : nextPage . activeStoryId ] ] ;
[ previousPage setActiveStoryAtIndex : [ appDelegate . storiesCollection
indexOfStoryId : previousPage . activeStoryId ] ] ;
[ currentPage refreshHeader ] ;
[ nextPage refreshHeader ] ;
[ previousPage refreshHeader ] ;
[ currentPage refreshSideOptions ] ;
[ nextPage refreshSideOptions ] ;
[ previousPage refreshSideOptions ] ;
2012-12-07 17:18:31 -08:00
}
2015-12-01 15:17:46 -08:00
2012-11-06 17:26:08 -08:00
- ( void ) resizeScrollView {
2021-01-29 20:10:53 -08:00
NSInteger storyCount = appDelegate . storiesCollection . storyLocationsCount ;
if ( storyCount = = 0 ) {
storyCount = 1 ;
}
if ( self . isHorizontal ) {
self . scrollView . contentSize = CGSizeMake ( self . scrollView . bounds . size . width
* storyCount ,
self . scrollView . bounds . size . height ) ;
} else {
self . scrollView . contentSize = CGSizeMake ( self . scrollView . bounds . size . width ,
self . scrollView . bounds . size . height
* storyCount ) ;
}
2012-11-06 17:26:08 -08:00
}
2021-01-29 20:10:53 -08:00
- ( BOOL ) isPhoneOrCompact {
return [ [ UIDevice currentDevice ] userInterfaceIdiom ] = = UIUserInterfaceIdiomPhone || appDelegate . isCompactWidth ;
2020-12-21 20:53:08 -08:00
}
2019-02-28 15:29:31 -08:00
- ( void ) updateAutoscrollButtons {
self . autoscrollBackgroundImageView . image = [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "traverse_background.png" ] ] ;
[ self . autoscrollDisableButton setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "autoscroll_off.png" ] ] forState : UIControlStateNormal ] ;
if ( self . autoscrollActive ) {
[ self . autoscrollPauseResumeButton setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "autoscroll_pause.png" ] ] forState : UIControlStateNormal ] ;
} else {
[ self . autoscrollPauseResumeButton setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "autoscroll_resume.png" ] ] forState : UIControlStateNormal ] ;
}
[ self . autoscrollSlowerButton setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "autoscroll_slower.png" ] ] forState : UIControlStateNormal ] ;
[ self . autoscrollFasterButton setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "autoscroll_faster.png" ] ] forState : UIControlStateNormal ] ;
}
2015-12-07 16:09:49 -08:00
- ( void ) updateTraverseBackground {
self . textStorySendBackgroundImageView . image = [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "traverse_background.png" ] ] ;
self . prevNextBackgroundImageView . image = [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "traverse_background.png" ] ] ;
2021-01-29 20:10:53 -08:00
self . bottomSize . backgroundColor = UIColorFromRGB ( NEWSBLUR_WHITE _COLOR ) ;
2015-12-07 16:09:49 -08:00
}
- ( void ) updateTheme {
[ super updateTheme ] ;
2019-10-22 21:14:15 -07:00
self . navigationController . navigationBar . tintColor = [ UINavigationBar appearance ] . tintColor ;
2020-02-20 20:32:49 -08:00
self . navigationController . navigationBar . barTintColor = UIColorFromLightSepiaMediumDarkRGB ( 0 xE3E6E0 , 0 xFFFFC5 , 0 x222222 , 0 x111111 ) ;
2019-10-22 21:14:15 -07:00
self . navigationController . navigationBar . backgroundColor = [ UINavigationBar appearance ] . backgroundColor ;
2020-02-20 20:32:49 -08:00
self . view . backgroundColor = UIColorFromLightDarkRGB ( 0 xe0e0e0 , 0 x111111 ) ;
2019-10-22 21:14:15 -07:00
2019-02-28 15:29:31 -08:00
[ self updateAutoscrollButtons ] ;
2015-12-07 16:09:49 -08:00
[ self updateTraverseBackground ] ;
[ self setNextPreviousButtons ] ;
[ self setTextButton ] ;
2018-10-22 15:14:12 -07:00
[ self updateStoriesTheme ] ;
2020-04-22 19:31:08 -07:00
[ self updateStatusBarTheme ] ;
2015-12-07 16:09:49 -08:00
}
2021-06-05 21:50:57 -07:00
// allow keyboard commands
2015-11-21 23:23:37 -05:00
- ( BOOL ) canBecomeFirstResponder {
return YES ;
}
2019-03-22 20:55:22 -07:00
# pragma mark -
# pragma mark State Restoration
- ( void ) encodeRestorableStateWithCoder : ( NSCoder * ) coder {
[ super encodeRestorableStateWithCoder : coder ] ;
2021-01-29 20:10:53 -08:00
[ coder encodeObject : currentPage . activeStoryId forKey : @ "current_story_id" ] ;
2019-03-22 20:55:22 -07:00
[ appDelegate . storiesCollection toggleStoryUnread ] ;
self . temporarilyMarkedUnread = YES ;
}
- ( void ) decodeRestorableStateWithCoder : ( NSCoder * ) coder {
[ super decodeRestorableStateWithCoder : coder ] ;
self . restoringStoryId = [ coder decodeObjectOfClass : [ NSString class ] forKey : @ "current_story_id" ] ;
}
- ( void ) restorePage {
if ( self . restoringStoryId . length > 0 ) {
NSInteger pageIndex = [ appDelegate . storiesCollection indexOfStoryId : self . restoringStoryId ] ;
2019-08-23 20:14:22 -07:00
if ( pageIndex >= 0 ) {
2019-03-22 20:55:22 -07:00
[ self changePage : pageIndex animated : NO ] ;
2020-03-29 16:21:00 -07:00
} else if ( [ [ UIDevice currentDevice ] userInterfaceIdiom ] = = UIUserInterfaceIdiomPad ) {
2020-03-24 17:05:22 -07:00
// If the story can ' t be found , don ' t show anything ; uncomment this to instead show the first unread story :
// [ self doNextUnreadStory : nil ] ;
2019-08-23 20:14:22 -07:00
} else {
[ appDelegate hideStoryDetailView ] ;
2019-03-22 20:55:22 -07:00
}
self . restoringStoryId = nil ;
}
}
2012-11-07 17:54:16 -08:00
# pragma mark -
# pragma mark Side scroll view
2013-10-03 13:54:15 -07:00
- ( void ) applyNewIndex : ( NSInteger ) newIndex
pageController : ( StoryDetailViewController * ) pageController {
2014-11-30 21:24:42 -05:00
[ self applyNewIndex : newIndex pageController : pageController supressRedraw : NO ] ;
}
- ( void ) applyNewIndex : ( NSInteger ) newIndex
pageController : ( StoryDetailViewController * ) pageController
supressRedraw : ( BOOL ) suppressRedraw {
2021-01-29 20:10:53 -08:00
NSInteger pageCount = [ [ appDelegate . storiesCollection activeFeedStoryLocations ] count ] ;
BOOL outOfBounds = newIndex >= pageCount || newIndex < 0 ;
if ( ! outOfBounds ) {
CGRect pageFrame = pageController . view . bounds ;
if ( self . isHorizontal ) {
pageFrame . origin . y = 0 ;
pageFrame . origin . x = CGRectGetWidth ( self . scrollView . bounds ) * newIndex ;
} else {
pageFrame . origin . y = CGRectGetHeight ( self . scrollView . bounds ) * newIndex ;
pageFrame . origin . x = 0 ;
}
pageFrame . size . height = CGRectGetHeight ( self . scrollView . bounds ) ;
pageFrame . size . width = CGRectGetWidth ( self . scrollView . bounds ) ;
if ( self . currentlyTogglingNavigationBar && ! self . isNavigationBarHidden ) {
pageFrame . size . height - = 20.0 ;
}
pageController . view . hidden = NO ;
pageController . view . frame = pageFrame ;
} else {
// NSLog ( @ "Out of bounds: was %@, now %@" , @ ( pageController . pageIndex ) , @ ( newIndex ) ) ;
CGRect pageFrame = pageController . view . bounds ;
if ( self . isHorizontal ) {
pageFrame . origin . x = CGRectGetWidth ( self . scrollView . bounds ) * newIndex ;
pageFrame . origin . y = CGRectGetHeight ( self . scrollView . bounds ) ;
} else {
pageFrame . origin . x = 0 ;
pageFrame . origin . y = CGRectGetHeight ( self . scrollView . bounds ) * newIndex ;
}
pageFrame . size . height = CGRectGetHeight ( self . scrollView . bounds ) ;
pageFrame . size . width = CGRectGetWidth ( self . scrollView . bounds ) ;
pageController . view . hidden = YES ;
pageController . view . frame = pageFrame ;
}
2018-08-30 16:33:42 -07:00
// NSLog ( @ "---> Story page control orient page: %@ (%@-%@)" , NSStringFromCGRect ( self . scrollView . bounds ) , @ ( pageController . pageIndex ) , suppressRedraw ? @ "supress" : @ "redraw" ) ;
2015-11-30 18:12:10 -08:00
2014-11-30 21:24:42 -05:00
if ( suppressRedraw ) return ;
2018-09-06 11:31:17 -07:00
// NSInteger wasIndex = pageController . pageIndex ;
2012-11-05 15:12:42 -08:00
pageController . pageIndex = newIndex ;
2021-01-29 20:10:53 -08:00
// NSLog ( @ "Applied Index to %@: Was %ld, now %ld (%ld/%ld/%ld) [%lu stories - %d] %@" , pageController , ( long ) wasIndex , ( long ) newIndex , ( long ) previousPage . pageIndex , ( long ) currentPage . pageIndex , ( long ) nextPage . pageIndex , ( unsigned long ) [ appDelegate . storiesCollection . activeFeedStoryLocations count ] , outOfBounds , NSStringFromCGRect ( self . scrollView . frame ) ) ;
2012-11-05 15:12:42 -08:00
2021-01-29 20:10:53 -08:00
if ( newIndex > 0 && newIndex >= [ appDelegate . storiesCollection . activeFeedStoryLocations count ] ) {
2012-12-06 15:30:16 -08:00
pageController . pageIndex = -2 ;
2017-04-03 16:07:01 -07:00
if ( appDelegate . storiesCollection . feedPage < 100 &&
! appDelegate . feedDetailViewController . pageFinished &&
! appDelegate . feedDetailViewController . pageFetching ) {
[ appDelegate . feedDetailViewController fetchNextPage : ^ ( ) {
2021-01-29 20:10:53 -08:00
// NSLog ( @ "Fetched next page, %@ stories" , @ ( [ appDelegate . storiesCollection . activeFeedStoryLocations count ] ) ) ;
2012-11-05 18:23:45 -08:00
[ self applyNewIndex : newIndex pageController : pageController ] ;
} ] ;
2017-04-03 16:07:01 -07:00
} else if ( ! appDelegate . feedDetailViewController . pageFinished &&
! appDelegate . feedDetailViewController . pageFetching ) {
2021-01-29 20:10:53 -08:00
[ appDelegate . feedsNavigationController
popToViewController : [ appDelegate . feedsNavigationController . viewControllers
objectAtIndex : 0 ]
animated : YES ] ;
2012-12-06 15:30:16 -08:00
[ appDelegate hideStoryDetailView ] ;
2012-11-05 18:23:45 -08:00
}
2012-11-14 17:31:52 -08:00
} else if ( ! outOfBounds ) {
2014-02-12 20:09:37 -08:00
NSInteger location = [ appDelegate . storiesCollection indexFromLocation : pageController . pageIndex ] ;
2012-11-06 13:45:15 -08:00
[ pageController setActiveStoryAtIndex : location ] ;
2012-11-14 17:31:52 -08:00
[ pageController clearStory ] ;
2012-11-19 19:15:05 -08:00
if ( self . isDraggingScrollview ||
2012-11-26 16:47:20 -08:00
self . scrollingToPage < 0 ||
2013-09-25 17:43:00 -07:00
ABS ( newIndex - self . scrollingToPage ) <= 1 ) {
2015-10-02 16:04:49 -07:00
[ pageController drawFeedGradient ] ;
2015-10-06 18:52:58 -07:00
NSString * originalStoryId = pageController . activeStoryId ;
__block StoryDetailViewController * blockPageController = pageController ;
2015-10-02 16:04:49 -07:00
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _HIGH , 0 ul ) , ^ {
2015-10-06 18:52:58 -07:00
if ( blockPageController . activeStoryId && ! [ blockPageController . activeStoryId isEqualToString : originalStoryId ] ) {
2018-08-30 16:33:42 -07:00
// NSLog ( @ "Stale story, already drawn. Was: %@, Now: %@" , originalStoryId , blockPageController . activeStoryId ) ;
2015-10-06 18:52:58 -07:00
return ;
}
2016-04-14 20:28:16 -07:00
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
[ blockPageController initStory ] ;
[ blockPageController drawStory ] ;
[ blockPageController showTextOrStoryView ] ;
} ) ;
2015-10-02 16:04:49 -07:00
} ) ;
2012-11-14 17:31:52 -08:00
} else {
2013-01-07 16:34:59 -08:00
// NSLog ( @ "Skipping drawing %d (waiting for %d)" , newIndex , self . scrollingToPage ) ;
2012-11-14 17:31:52 -08:00
}
2021-05-07 21:31:55 -07:00
} else if ( outOfBounds && pageController = = self . currentPage ) {
2021-01-29 20:10:53 -08:00
[ pageController clearStory ] ;
2020-11-24 21:34:45 -08:00
2021-06-04 21:49:08 -07:00
[ self . appDelegate showColumn : UISplitViewControllerColumnSupplementary debugInfo : @ "applyNewIndex" ] ;
2012-11-05 18:23:45 -08:00
}
2012-11-05 17:16:10 -08:00
2014-12-03 15:35:37 -08:00
if ( ! suppressRedraw ) {
[ self resizeScrollView ] ;
}
2013-05-29 13:36:39 -07:00
[ self setTextButton ] ;
2012-11-05 17:16:10 -08:00
[ self . loadingIndicator stopAnimating ] ;
2013-04-23 11:52:34 -07:00
self . circularProgressView . hidden = NO ;
2023-03-03 21:38:55 -07:00
// if ( self . currentPage ! = nil && pageController = = self . currentPage ) {
// [ self . appDelegate . feedDetailViewController changedStoryHeight : currentPage . webView . scrollView . contentSize . height ] ;
// }
2012-11-05 15:12:42 -08:00
}
2012-11-14 17:31:52 -08:00
- ( void ) scrollViewDidScroll : ( UIScrollView * ) sender {
2021-01-29 20:10:53 -08:00
if ( inRotation ) return ;
2021-02-12 20:29:58 -08:00
NSInteger currentPageIndex = currentPage . pageIndex ;
2021-01-29 20:10:53 -08:00
CGSize size = self . scrollView . frame . size ;
CGPoint offset = self . scrollView . contentOffset ;
CGFloat pageAmount = self . isHorizontal ? size . width : size . height ;
float fractionalPage = ( self . isHorizontal ? offset . x : offset . y ) / pageAmount ;
NSInteger lowerNumber = floor ( fractionalPage ) ;
NSInteger upperNumber = lowerNumber + 1 ;
NSInteger previousNumber = lowerNumber - 1 ;
NSInteger storyCount = [ appDelegate . storiesCollection . activeFeedStoryLocations count ] ;
if ( storyCount = = 0 || lowerNumber > storyCount ) return ;
// NSLog ( @ "Did Scroll: %@ = %@ (%@/%@/%@)" , @ ( fractionalPage ) , @ ( lowerNumber ) , @ ( previousPage . pageIndex ) , @ ( currentPage . pageIndex ) , @ ( nextPage . pageIndex ) ) ;
if ( lowerNumber = = currentPage . pageIndex ) {
if ( upperNumber ! = nextPage . pageIndex ) {
// NSLog ( @ "Next was %d, now %d (A)" , nextPage . pageIndex , upperNumber ) ;
[ self applyNewIndex : upperNumber pageController : nextPage ] ;
}
if ( previousNumber ! = previousPage . pageIndex ) {
// NSLog ( @ "Prev was %d, now %d (A)" , previousPage . pageIndex , previousNumber ) ;
[ self applyNewIndex : previousNumber pageController : previousPage ] ;
}
} else if ( upperNumber = = currentPage . pageIndex ) {
// Going backwards
if ( lowerNumber ! = previousPage . pageIndex ) {
// NSLog ( @ "Prev was %d, now %d (B)" , previousPage . pageIndex , previousNumber ) ;
[ self applyNewIndex : lowerNumber pageController : previousPage ] ;
}
} else {
// Going forwards
if ( lowerNumber = = nextPage . pageIndex ) {
// NSLog ( @ "Prev was %d, now %d (C1)" , previousPage . pageIndex , previousNumber ) ;
2012-11-14 17:31:52 -08:00
// [ self applyNewIndex : upperNumber pageController : nextPage ] ;
2020-10-30 20:58:27 -07:00
// [ self applyNewIndex : lowerNumber pageController : currentPage ] ;
2021-01-29 20:10:53 -08:00
[ self applyNewIndex : previousNumber pageController : previousPage ] ;
} else if ( upperNumber = = nextPage . pageIndex ) {
// NSLog ( @ "Prev was %d, now %d (C2)" , previousPage . pageIndex , previousNumber ) ;
[ self applyNewIndex : lowerNumber pageController : currentPage ] ;
[ self applyNewIndex : previousNumber pageController : previousPage ] ;
} else {
// NSLog ( @ "Next was %d, now %d (C3)" , nextPage . pageIndex , upperNumber ) ;
// NSLog ( @ "Current was %d, now %d (C3)" , currentPage . pageIndex , lowerNumber ) ;
// NSLog ( @ "Prev was %d, now %d (C3)" , previousPage . pageIndex , previousNumber ) ;
[ self applyNewIndex : lowerNumber pageController : currentPage ] ;
[ self applyNewIndex : upperNumber pageController : nextPage ] ;
[ self applyNewIndex : previousNumber pageController : previousPage ] ;
}
}
// if ( self . isDraggingScrollview ) {
[ self setStoryFromScroll ] ;
2012-11-26 09:54:20 -08:00
// }
2021-01-29 20:10:53 -08:00
2021-02-12 20:29:58 -08:00
if ( currentPage . pageIndex = = currentPageIndex ) {
return ;
}
2021-01-29 20:10:53 -08:00
[ self showAutoscrollBriefly : YES ] ;
// Stick to bottom
traversePinned = YES ;
2022-02-01 20:40:07 -08:00
self . traverseBottomConstraint . constant = 0 ;
2021-02-12 20:29:58 -08:00
2021-08-19 21:13:22 -07:00
if ( self . traverseView . alpha = = 0 ) {
[ UIView animateWithDuration : .24 delay : 0
options : UIViewAnimationOptionCurveEaseInOut
animations : ^ {
[ self . traverseView setNeedsLayout ] ;
self . traverseView . alpha = 1 ;
self . traversePinned = YES ;
[ self . view layoutIfNeeded ] ;
} completion : ^ ( BOOL finished ) {
} ] ;
}
2012-11-05 15:12:42 -08:00
}
2012-11-08 18:30:45 -08:00
- ( void ) scrollViewWillBeginDragging : ( UIScrollView * ) scrollView {
self . isDraggingScrollview = YES ;
}
2012-11-14 17:31:52 -08:00
- ( void ) scrollViewDidEndDecelerating : ( UIScrollView * ) newScrollView
{
[ self scrollViewDidEndScrollingAnimation : newScrollView ] ;
}
2012-11-05 15:12:42 -08:00
- ( void ) scrollViewDidEndScrollingAnimation : ( UIScrollView * ) newScrollView
{
2012-11-08 18:30:45 -08:00
self . isDraggingScrollview = NO ;
2018-08-30 16:33:42 -07:00
CGSize size = self . scrollView . frame . size ;
CGPoint offset = self . scrollView . contentOffset ;
CGFloat pageAmount = self . isHorizontal ? size . width : size . height ;
float fractionalPage = ( self . isHorizontal ? offset . x : offset . y ) / pageAmount ;
2012-11-14 17:31:52 -08:00
NSInteger nearestNumber = lround ( fractionalPage ) ;
self . scrollingToPage = nearestNumber ;
2012-11-08 17:39:32 -08:00
[ self setStoryFromScroll ] ;
2012-11-05 15:12:42 -08:00
}
2013-10-03 13:54:15 -07:00
- ( void ) observeValueForKeyPath : ( NSString * ) keyPath
ofObject : ( id ) object
change : ( NSDictionary * ) change
context : ( void * ) context {
2015-11-28 22:07:38 -08:00
if ( ! self . isPhoneOrCompact &&
2013-02-06 15:15:43 -08:00
[ keyPath isEqual : @ "contentOffset" ] &&
2012-11-19 19:15:05 -08:00
self . isDraggingScrollview ) {
2018-08-30 16:33:42 -07:00
CGSize size = self . scrollView . frame . size ;
CGPoint offset = self . scrollView . contentOffset ;
CGFloat pageAmount = self . isHorizontal ? size . width : size . height ;
float fractionalPage = ( self . isHorizontal ? offset . x : offset . y ) / pageAmount ;
2012-11-08 18:30:45 -08:00
NSInteger nearestNumber = lround ( fractionalPage ) ;
2014-02-12 20:09:37 -08:00
if ( ! [ appDelegate . storiesCollection . activeFeedStories count ] ) return ;
2012-11-28 15:21:44 -08:00
2018-08-30 16:33:42 -07:00
// NSLog ( @ "observe content offset: fractional page %@" , @ ( fractionalPage ) ) ; // log
2014-02-12 20:09:37 -08:00
NSInteger storyIndex = [ appDelegate . storiesCollection indexFromLocation : nearestNumber ] ;
2015-11-28 22:07:38 -08:00
if ( storyIndex ! = [ appDelegate . storiesCollection indexOfActiveStory ] && storyIndex ! = NSNotFound ) {
2014-02-12 20:09:37 -08:00
appDelegate . activeStory = [ appDelegate . storiesCollection . activeFeedStories
objectAtIndex : storyIndex ] ;
2012-11-19 19:15:05 -08:00
[ appDelegate changeActiveFeedDetailRow ] ;
}
2012-11-08 18:30:45 -08:00
}
}
2014-02-24 18:35:35 -08:00
- ( void ) animateIntoPlace : ( BOOL ) animated {
2014-01-30 20:28:08 -08:00
// Move view into position if no story is selected yet
2015-11-28 22:07:38 -08:00
if ( ! self . isPhoneOrCompact &&
2014-01-30 20:28:08 -08:00
! self . isAnimatedIntoPlace ) {
CGRect frame = self . scrollView . frame ;
2018-08-30 16:33:42 -07:00
if ( self . isHorizontal ) {
frame . origin . x = frame . size . width ;
} else {
frame . origin . y = frame . size . height ;
}
2014-01-30 20:28:08 -08:00
self . scrollView . frame = frame ;
2018-08-30 16:33:42 -07:00
2014-02-24 18:35:35 -08:00
[ UIView animateWithDuration : ( animated ? .22 : 0 ) delay : 0
options : UIViewAnimationOptionCurveEaseInOut
animations : ^
{
2014-01-30 20:28:08 -08:00
CGRect frame = self . scrollView . frame ;
2018-08-30 16:33:42 -07:00
if ( self . isHorizontal ) {
frame . origin . x = 0 ;
} else {
frame . origin . y = 0 ;
}
2014-01-30 20:28:08 -08:00
self . scrollView . frame = frame ;
} completion : ^ ( BOOL finished ) {
self . isAnimatedIntoPlace = YES ;
} ] ;
}
}
2012-11-05 18:23:45 -08:00
- ( void ) changePage : ( NSInteger ) pageIndex {
2012-11-09 11:39:36 -08:00
[ self changePage : pageIndex animated : YES ] ;
}
- ( void ) changePage : ( NSInteger ) pageIndex animated : ( BOOL ) animated {
2018-08-30 16:33:42 -07:00
// NSLog ( @ "changePage to %@ (%@animated)" , @ ( pageIndex ) , animated ? @ "" : @ "not " ) ;
2012-11-05 18:23:45 -08:00
// update the scroll view to the appropriate page
2012-11-06 17:26:08 -08:00
[ self resizeScrollView ] ;
2021-01-29 20:10:53 -08:00
CGRect frame = self . scrollView . frame ;
CGPoint offset = self . scrollView . contentOffset ;
if ( self . isHorizontal ) {
frame . origin . x = frame . size . width * pageIndex ;
frame . origin . y = 0 ;
} else {
frame . origin . x = 0 ;
2022-05-03 20:03:25 -06:00
frame . origin . y = ( frame . size . height * pageIndex ) - self . view . safeAreaInsets . bottom + self . view . safeAreaInsets . bottom ;
2021-01-29 20:10:53 -08:00
}
2022-05-03 20:03:25 -06:00
2012-11-14 17:31:52 -08:00
self . scrollingToPage = pageIndex ;
2021-01-29 20:10:53 -08:00
[ self . currentPage hideNoStoryMessage ] ;
[ self . nextPage hideNoStoryMessage ] ;
[ self . previousPage hideNoStoryMessage ] ;
2013-09-12 21:26:38 -07:00
2012-11-28 15:46:11 -08:00
// Check if already on the selected page
2021-01-29 20:10:53 -08:00
if ( self . isHorizontal ? offset . x = = frame . origin . x : offset . y = = frame . origin . y ) {
[ self applyNewIndex : pageIndex pageController : currentPage ] ;
2012-11-08 17:39:32 -08:00
[ self setStoryFromScroll ] ;
2021-01-29 20:10:53 -08:00
} else {
[ self . scrollView scrollRectToVisible : frame animated : animated ] ;
if ( ! animated ) {
[ self setStoryFromScroll ] ;
}
}
2021-05-08 21:27:11 -07:00
if ( self . isPhoneOrCompact || animated ) {
2021-06-04 21:49:08 -07:00
[ appDelegate showColumn : UISplitViewControllerColumnSecondary debugInfo : @ "changePage" ] ;
2021-05-08 21:27:11 -07:00
}
2015-11-22 21:11:23 -05:00
[ self becomeFirstResponder ] ;
2015-11-21 23:23:37 -05:00
}
- ( void ) changeToNextPage : ( id ) sender {
2021-01-29 20:10:53 -08:00
if ( nextPage . pageIndex < 0 && currentPage . pageIndex < 0 ) {
// just displaying a placeholder - display the first story instead
[ self changePage : 0 animated : YES ] ;
return ;
}
[ self changePage : currentPage . pageIndex + 1 animated : YES ] ;
2015-11-21 23:23:37 -05:00
}
- ( void ) changeToPreviousPage : ( id ) sender {
2021-01-29 20:10:53 -08:00
if ( previousPage . pageIndex < 0 ) {
if ( currentPage . pageIndex < 0 ) {
[ self changeToNextPage : sender ] ;
}
return ;
}
[ self changePage : currentPage . pageIndex - 1 animated : YES ] ;
2012-11-05 18:23:45 -08:00
}
2012-11-08 17:39:32 -08:00
- ( void ) setStoryFromScroll {
2012-11-26 09:54:20 -08:00
[ self setStoryFromScroll : NO ] ;
}
- ( void ) setStoryFromScroll : ( BOOL ) force {
2021-01-29 20:10:53 -08:00
CGSize size = self . scrollView . bounds . size ;
CGPoint offset = self . scrollView . contentOffset ;
CGFloat pageAmount = self . isHorizontal ? size . width : size . height ;
float fractionalPage = ( self . isHorizontal ? offset . x : offset . y ) / pageAmount ;
NSInteger nearestNumber = lround ( fractionalPage ) ;
// NSLog ( @ "setStoryFromScroll: fractional page %@" , @ ( fractionalPage ) ) ; // log
if ( ! force && currentPage . pageIndex >= 0 &&
currentPage . pageIndex = = nearestNumber &&
currentPage . pageIndex ! = self . scrollingToPage ) {
// NSLog ( @ "Skipping setStoryFromScroll: currentPage is %@ (%@, %@)" , @ ( currentPage . pageIndex ) , @ ( nearestNumber ) , @ ( self . scrollingToPage ) ) ;
return ;
}
if ( currentPage . pageIndex < nearestNumber ) {
// NSLog ( @ "Swap next into current, current into previous: %@ / %@" , @ ( currentPage . pageIndex ) , @ ( nearestNumber ) ) ;
StoryDetailViewController * swapCurrentController = currentPage ;
StoryDetailViewController * swapPreviousController = previousPage ;
currentPage = nextPage ;
previousPage = swapCurrentController ;
nextPage = swapPreviousController ;
} else if ( currentPage . pageIndex > nearestNumber ) {
// NSLog ( @ "Swap previous into current: %@ / %@" , @ ( currentPage . pageIndex ) , @ ( nearestNumber ) ) ;
StoryDetailViewController * swapCurrentController = currentPage ;
StoryDetailViewController * swapNextController = nextPage ;
currentPage = previousPage ;
nextPage = swapCurrentController ;
previousPage = swapNextController ;
}
// NSLog ( @ "Set Story from scroll: %@ = %@ (%@/%@/%@)" , @ ( fractionalPage ) , @ ( nearestNumber ) , @ ( previousPage . pageIndex ) , @ ( currentPage . pageIndex ) , @ ( nextPage . pageIndex ) ) ;
2019-02-28 15:29:31 -08:00
self . autoscrollActive = NO ;
2021-01-29 20:10:53 -08:00
// [ self showAutoscrollBriefly : YES ] ;
nextPage . webView . scrollView . scrollsToTop = NO ;
previousPage . webView . scrollView . scrollsToTop = NO ;
currentPage . webView . scrollView . scrollsToTop = YES ;
currentPage . isRecentlyUnread = NO ;
if ( ! self . isPhoneOrCompact ) {
2023-05-25 21:47:34 -07:00
appDelegate . feedDetailViewController . storyTitlesTable . scrollsToTop = NO ;
2021-01-29 20:10:53 -08:00
}
self . scrollView . scrollsToTop = NO ;
if ( self . isDraggingScrollview || self . scrollingToPage = = currentPage . pageIndex ) {
if ( currentPage . pageIndex = = -2 ) return ;
2012-11-26 09:54:20 -08:00
self . scrollingToPage = -1 ;
2021-01-29 20:10:53 -08:00
NSInteger storyIndex = [ appDelegate . storiesCollection indexFromLocation : currentPage . pageIndex ] ;
2018-08-30 16:33:42 -07:00
if ( storyIndex < 0 ) {
2021-01-29 20:10:53 -08:00
NSLog ( @ "invalid story index: %@ for page index: %@" , @ ( storyIndex ) , @ ( currentPage . pageIndex ) ) ; // log
2018-08-30 16:33:42 -07:00
}
2014-02-12 20:09:37 -08:00
appDelegate . activeStory = [ appDelegate . storiesCollection . activeFeedStories objectAtIndex : storyIndex ] ;
2022-10-26 21:57:42 -06:00
[ self updatePageWithActiveStory : currentPage . pageIndex updateFeedDetail : YES ] ;
2022-01-25 15:14:30 -08:00
if ( [ appDelegate . storiesCollection isStoryUnread : appDelegate . activeStory ] ) {
2014-03-05 14:13:49 -08:00
[ appDelegate . storiesCollection markStoryRead : appDelegate . activeStory ] ;
[ appDelegate . storiesCollection syncStoryAsRead : appDelegate . activeStory ] ;
}
[ appDelegate . feedDetailViewController redrawUnreadStory ] ;
2021-01-29 20:10:53 -08:00
}
2021-01-15 21:26:53 -08:00
2020-07-21 20:00:09 -07:00
if ( ! appDelegate . storiesCollection . inSearch ) {
2021-01-29 20:10:53 -08:00
[ currentPage becomeFirstResponder ] ;
2020-07-21 20:00:09 -07:00
}
2012-11-08 17:39:32 -08:00
}
2012-12-13 16:41:52 -08:00
- ( void ) advanceToNextUnread {
2019-03-22 20:55:22 -07:00
if ( self . restoringStoryId . length > 0 ) {
[ self restorePage ] ;
return ;
}
2012-12-13 16:41:52 -08:00
if ( ! self . waitingForNextUnreadFromServer ) {
return ;
}
self . waitingForNextUnreadFromServer = NO ;
2013-10-08 13:57:15 -07:00
[ self doNextUnreadStory : nil ] ;
2012-12-13 16:41:52 -08:00
}
2022-10-26 21:57:42 -06:00
- ( void ) updatePageWithActiveStory : ( NSInteger ) location updateFeedDetail : ( BOOL ) updateFeedDetail {
2023-02-02 21:41:10 -06:00
if ( appDelegate . activeStory = = nil ) {
return ;
}
2014-02-12 20:41:29 -08:00
[ appDelegate . storiesCollection pushReadStory : [ appDelegate . activeStory objectForKey : @ "story_hash" ] ] ;
2012-11-05 17:16:10 -08:00
2020-03-29 16:21:00 -07:00
if ( [ [ UIDevice currentDevice ] userInterfaceIdiom ] = = UIUserInterfaceIdiomPad ) {
2020-11-24 21:34:45 -08:00
if ( appDelegate . detailViewController . storyTitlesOnLeft ) {
2021-01-30 12:49:07 -08:00
appDelegate . detailViewController . navigationItem . rightBarButtonItems = [ NSArray arrayWithObjects :
2017-11-01 22:19:26 -07:00
originalStoryButton ,
separatorBarButton ,
fontSettingsButton , nil ] ;
} else {
2021-01-30 12:49:07 -08:00
appDelegate . detailViewController . navigationItem . rightBarButtonItems = [ NSArray arrayWithObjects :
2017-11-01 22:19:26 -07:00
originalStoryButton ,
separatorBarButton ,
fontSettingsButton ,
separatorBarButton2 ,
markReadBarButton , nil ] ;
}
2013-03-04 17:15:50 -08:00
}
2012-11-05 17:16:10 -08:00
[ self setNextPreviousButtons ] ;
2021-06-05 21:50:57 -07:00
2022-10-26 21:57:42 -06:00
if ( updateFeedDetail ) {
[ appDelegate changeActiveFeedDetailRow ] ;
}
2012-11-08 17:39:32 -08:00
2021-01-29 20:10:53 -08:00
if ( self . currentPage . pageIndex ! = location ) {
// NSLog ( @ "Updating Current: from %d to %d" , currentPage . pageIndex , location ) ;
[ self applyNewIndex : location pageController : self . currentPage ] ;
}
if ( self . nextPage . pageIndex ! = location + 1 ) {
// NSLog ( @ "Updating Next: from %d to %d" , nextPage . pageIndex , location + 1 ) ;
[ self applyNewIndex : location + 1 pageController : self . nextPage ] ;
}
if ( self . previousPage . pageIndex ! = location -1 ) {
// NSLog ( @ "Updating Previous: from %d to %d" , previousPage . pageIndex , location -1 ) ;
[ self applyNewIndex : location -1 pageController : self . previousPage ] ;
2012-11-14 17:31:52 -08:00
}
2012-11-05 15:12:42 -08:00
}
2013-02-06 18:42:15 -08:00
- ( void ) requestFailed : ( id ) request {
2013-09-06 14:31:12 -07:00
[ self informError : @ "The server barfed!" ] ;
2012-11-05 17:16:10 -08:00
}
# pragma mark -
# pragma mark Actions
2017-11-01 22:19:26 -07:00
- ( IBAction ) markAllRead : ( id ) sender {
[ appDelegate . feedDetailViewController doOpenMarkReadMenu : markReadBarButton ] ;
}
2012-11-05 17:16:10 -08:00
- ( void ) setNextPreviousButtons {
// setting up the PREV BUTTON
2013-09-25 10:47:35 -07:00
NSInteger readStoryCount = [ appDelegate . readStories count ] ;
2012-11-05 17:16:10 -08:00
if ( readStoryCount = = 0 ||
( readStoryCount = = 1 &&
2014-02-12 20:41:29 -08:00
[ appDelegate . readStories lastObject ] = = [ appDelegate . activeStory objectForKey : @ "story_hash" ] ) ) {
2013-07-19 16:49:48 -07:00
[ buttonPrevious setEnabled : NO ] ;
} else {
[ buttonPrevious setEnabled : YES ] ;
}
2012-11-05 17:16:10 -08:00
2018-08-30 16:33:42 -07:00
NSString * previousName = self . isHorizontal ? @ "traverse_previous.png" : @ "traverse_previous_vert.png" ;
NSString * previousNameOff = self . isHorizontal ? @ "traverse_previous_off.png" : @ "traverse_previous_off_vert.png" ;
[ buttonPrevious setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : previousName ] ]
2015-12-07 16:09:49 -08:00
forState : UIControlStateNormal ] ;
2018-08-30 16:33:42 -07:00
[ buttonPrevious setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : previousNameOff ] ]
forState : UIControlStateDisabled ] ;
2015-12-07 16:09:49 -08:00
2012-11-05 17:16:10 -08:00
// setting up the NEXT UNREAD STORY BUTTON
2013-03-05 17:00:03 -08:00
buttonNext . enabled = YES ;
2014-02-12 20:09:37 -08:00
NSInteger nextIndex = [ appDelegate . storiesCollection indexOfNextUnreadStory ] ;
2013-09-25 10:47:35 -07:00
NSInteger unreadCount = [ appDelegate unreadCount ] ;
2017-04-03 16:07:01 -07:00
BOOL pageFinished = appDelegate . feedDetailViewController . pageFinished ;
2014-04-18 14:48:38 -07:00
if ( ( nextIndex = = -1 && unreadCount > 0 && ! pageFinished ) ||
2013-03-05 17:00:03 -08:00
nextIndex ! = -1 ) {
2018-08-30 16:33:42 -07:00
NSString * nextName = self . isHorizontal ? @ "traverse_next.png" : @ "traverse_next_vert.png" ;
2021-03-26 21:51:02 -07:00
[ buttonNext setTitle : @ "Next" forState : UIControlStateNormal ] ;
2018-08-30 16:33:42 -07:00
[ buttonNext setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : nextName ] ]
2013-10-03 13:54:15 -07:00
forState : UIControlStateNormal ] ;
2012-11-05 17:16:10 -08:00
} else {
2021-03-26 21:51:02 -07:00
[ buttonNext setTitle : @ "Done" forState : UIControlStateNormal ] ;
2015-12-07 16:09:49 -08:00
[ buttonNext setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "traverse_done.png" ] ]
2013-10-03 13:54:15 -07:00
forState : UIControlStateNormal ] ;
2012-11-05 17:16:10 -08:00
}
float unreads = ( float ) [ appDelegate unreadCount ] ;
float total = [ appDelegate originalStoryCount ] ;
float progress = ( total - unreads ) / total ;
2013-04-10 21:06:17 -07:00
circularProgressView . percentage = progress ;
2012-11-05 17:16:10 -08:00
}
2013-05-29 13:36:39 -07:00
- ( void ) setTextButton {
2021-01-29 20:10:53 -08:00
[ self setTextButton : currentPage ] ;
2015-03-09 14:20:45 -07:00
}
- ( void ) setTextButton : ( StoryDetailViewController * ) storyViewController {
2021-01-29 20:10:53 -08:00
if ( storyViewController ! = currentPage ) return ;
2015-03-09 14:20:45 -07:00
if ( storyViewController . pageIndex >= 0 ) {
2013-05-30 16:31:57 -07:00
[ buttonText setEnabled : YES ] ;
[ buttonText setAlpha : 1 ] ;
2013-07-19 18:19:30 -07:00
[ buttonSend setEnabled : YES ] ;
[ buttonSend setAlpha : 1 ] ;
2021-03-25 18:22:34 -07:00
fontSettingsButton . enabled = YES ;
originalStoryButton . enabled = YES ;
2013-05-30 16:31:57 -07:00
} else {
[ buttonText setEnabled : NO ] ;
[ buttonText setAlpha : .4 ] ;
2013-07-19 18:19:30 -07:00
[ buttonSend setEnabled : NO ] ;
[ buttonSend setAlpha : .4 ] ;
2021-03-25 18:22:34 -07:00
fontSettingsButton . enabled = NO ;
originalStoryButton . enabled = NO ;
2013-05-30 16:31:57 -07:00
}
2015-12-07 16:09:49 -08:00
[ buttonSend setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "traverse_send.png" ] ]
forState : UIControlStateNormal ] ;
2015-03-09 14:20:45 -07:00
if ( storyViewController . inTextView ) {
2021-03-26 21:51:02 -07:00
[ buttonText setTitle : @ "Story" forState : UIControlStateNormal ] ;
2015-12-07 16:09:49 -08:00
[ buttonText setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "traverse_text_on.png" ] ]
2016-10-05 21:03:32 -07:00
forState : 0 ] ;
2013-10-02 17:31:51 -07:00
self . buttonText . titleEdgeInsets = UIEdgeInsetsMake ( 0 , 26 , 0 , 0 ) ;
2013-05-29 13:36:39 -07:00
} else {
2021-03-26 21:51:02 -07:00
[ buttonText setTitle : @ "Text" forState : UIControlStateNormal ] ;
2015-12-07 16:09:49 -08:00
[ buttonText setBackgroundImage : [ [ ThemeManager themeManager ] themedImage : [ UIImage imageNamed : @ "traverse_text.png" ] ]
2016-10-05 21:03:32 -07:00
forState : 0 ] ;
2013-10-02 17:31:51 -07:00
self . buttonText . titleEdgeInsets = UIEdgeInsetsMake ( 0 , 22 , 0 , 0 ) ;
2013-05-29 13:36:39 -07:00
}
}
2013-07-19 16:49:48 -07:00
- ( IBAction ) openSendToDialog : ( id ) sender {
2013-10-08 13:57:15 -07:00
[ self endTouchDown : sender ] ;
2014-01-06 18:37:57 -08:00
[ appDelegate showSendTo : self sender : sender ] ;
2012-11-05 17:16:10 -08:00
}
2015-11-24 15:39:07 -05:00
- ( void ) openStoryTrainerFromKeyboard : ( id ) sender {
// don ' t have a tap target for the popover , but the settings button at least doesn ' t move
[ appDelegate openTrainStory : self . fontSettingsButton ] ;
}
2017-03-19 18:15:36 -07:00
- ( void ) finishMarkAsSaved : ( NSDictionary * ) params {
2013-08-05 17:29:42 -07:00
[ appDelegate . feedDetailViewController redrawUnreadStory ] ;
[ self refreshHeaders ] ;
2021-01-29 20:10:53 -08:00
[ self . currentPage flashCheckmarkHud : @ "saved" ] ;
2012-11-05 17:16:10 -08:00
}
2017-03-19 18:15:36 -07:00
- ( BOOL ) failedMarkAsSaved : ( NSDictionary * ) params {
2017-06-01 22:32:35 -07:00
if ( ! [ [ params objectForKey : @ "story_id" ]
2021-01-29 20:10:53 -08:00
isEqualToString : [ currentPage . activeStory objectForKey : @ "story_hash" ] ] ) {
2014-03-05 14:13:49 -08:00
return NO ;
}
[ self informError : @ "Failed to save story" ] ;
2017-06-01 22:32:35 -07:00
[ appDelegate hidePopover ] ;
2014-03-05 14:13:49 -08:00
return YES ;
2012-11-05 17:16:10 -08:00
}
2017-03-19 18:15:36 -07:00
- ( void ) finishMarkAsUnsaved : ( NSDictionary * ) params {
[ appDelegate . storiesCollection markStory : [ params objectForKey : @ "story" ] asSaved : NO ] ;
2013-08-05 17:29:42 -07:00
[ appDelegate . feedDetailViewController redrawUnreadStory ] ;
[ self refreshHeaders ] ;
2021-01-29 20:10:53 -08:00
[ self . currentPage flashCheckmarkHud : @ "unsaved" ] ;
2012-11-05 17:16:10 -08:00
}
2017-03-19 18:15:36 -07:00
- ( BOOL ) failedMarkAsUnsaved : ( NSDictionary * ) params {
2017-06-01 22:32:35 -07:00
if ( ! [ [ params objectForKey : @ "story_id" ]
2021-01-29 20:10:53 -08:00
isEqualToString : [ currentPage . activeStory objectForKey : @ "story_hash" ] ] ) {
2014-03-05 14:13:49 -08:00
return NO ;
2012-11-05 17:16:10 -08:00
}
2014-03-05 14:13:49 -08:00
[ self informError : @ "Failed to unsave story" ] ;
return YES ;
2012-11-05 17:16:10 -08:00
}
2017-03-19 18:15:36 -07:00
- ( BOOL ) failedMarkAsUnread : ( NSDictionary * ) params {
2017-06-01 22:32:35 -07:00
if ( ! [ [ params objectForKey : @ "story_id" ]
2021-01-29 20:10:53 -08:00
isEqualToString : [ currentPage . activeStory objectForKey : @ "story_hash" ] ] ) {
2014-03-05 14:13:49 -08:00
return NO ;
2013-10-03 18:07:39 -07:00
}
2013-10-04 12:37:51 -07:00
2014-03-05 14:13:49 -08:00
[ self informError : @ "Failed to unread story" ] ;
return YES ;
2013-10-03 18:07:39 -07:00
}
2012-11-05 17:16:10 -08:00
- ( IBAction ) showOriginalSubview : ( id ) sender {
2015-12-15 12:37:18 -08:00
[ appDelegate hidePopover ] ;
2020-04-22 20:18:06 -07:00
NSString * permalink = [ appDelegate . activeStory objectForKey : @ "story_permalink" ] ;
NSURL * url = [ NSURL URLWithString : permalink ] ;
if ( url = = nil ) {
url = [ NSURL URLWithDataRepresentation : [ permalink dataUsingEncoding : NSUTF8StringEncoding ] relativeToURL : nil ] ;
}
2021-04-24 21:55:36 -07:00
[ appDelegate showOriginalStory : url sender : originalStoryButton ] ;
2012-11-05 17:16:10 -08:00
}
- ( IBAction ) tapProgressBar : ( id ) sender {
2021-01-29 20:10:53 -08:00
[ MBProgressHUD hideHUDForView : currentPage . webView animated : NO ] ;
MBProgressHUD * hud = [ MBProgressHUD showHUDAddedTo : currentPage . webView animated : YES ] ;
2012-11-05 17:16:10 -08:00
hud . mode = MBProgressHUDModeText ;
hud . removeFromSuperViewOnHide = YES ;
2013-09-25 17:43:00 -07:00
NSInteger unreadCount = appDelegate . unreadCount ;
2012-11-05 17:16:10 -08:00
if ( unreadCount = = 0 ) {
hud . labelText = @ "No unread stories" ;
} else if ( unreadCount = = 1 ) {
hud . labelText = @ "1 story left" ;
} else {
2013-09-25 17:43:00 -07:00
hud . labelText = [ NSString stringWithFormat : @ "%li stories left" , ( long ) unreadCount ] ;
2012-11-05 17:16:10 -08:00
}
[ hud hide : YES afterDelay : 0.8 ] ;
}
2012-11-28 16:24:15 -08:00
- ( void ) subscribeToBlurblog {
2021-01-29 20:10:53 -08:00
[ self . currentPage subscribeToBlurblog ] ;
2012-11-28 16:24:15 -08:00
}
2012-11-05 17:16:10 -08:00
2015-03-11 11:21:59 -07:00
- ( IBAction ) toggleTextView : ( id ) sender {
2013-10-08 13:57:15 -07:00
[ self endTouchDown : sender ] ;
2015-10-05 11:45:33 -07:00
NSString * feedIdStr = [ NSString stringWithFormat : @ "%@" ,
[ appDelegate . activeStory objectForKey : @ "story_feed_id" ] ] ;
[ appDelegate toggleFeedTextView : feedIdStr ] ;
2013-10-08 13:57:15 -07:00
2021-01-29 20:10:53 -08:00
[ self . currentPage showTextOrStoryView ] ;
[ self . nextPage showTextOrStoryView ] ;
[ self . previousPage showTextOrStoryView ] ;
2023-03-03 21:38:55 -07:00
[ self . appDelegate . feedDetailViewController reload ] ;
// [ self . appDelegate . feedDetailViewController changedStoryHeight : currentPage . webView . scrollView . contentSize . height ] ;
2013-05-28 18:07:19 -07:00
}
2015-11-21 23:23:37 -05:00
- ( void ) toggleStorySaved : ( id ) sender {
[ appDelegate . storiesCollection toggleStorySaved ] ;
}
- ( void ) toggleStoryUnread : ( id ) sender {
[ appDelegate . storiesCollection toggleStoryUnread ] ;
2023-04-19 14:10:09 -07:00
[ appDelegate . feedDetailViewController reload ] ; // XXX only if successful ?
2015-11-21 23:23:37 -05:00
}
2015-11-24 13:52:16 -05:00
- ( BOOL ) canPerformAction : ( SEL ) action withSender : ( id ) sender {
if ( action = = @ selector ( toggleTextView : ) ||
action = = @ selector ( scrollPageDown : ) ||
action = = @ selector ( scrollPageUp : ) ||
action = = @ selector ( toggleStoryUnread : ) ||
action = = @ selector ( toggleStorySaved : ) ||
action = = @ selector ( showOriginalSubview : ) ||
action = = @ selector ( openShareDialog ) ||
2015-11-24 15:39:07 -05:00
action = = @ selector ( scrolltoComment ) ||
action = = @ selector ( openStoryTrainerFromKeyboard : ) ) {
2021-01-29 20:10:53 -08:00
return ( currentPage . pageIndex >= 0 ) ;
2015-11-24 13:52:16 -05:00
}
return [ super canPerformAction : action withSender : sender ] ;
}
2012-11-05 17:16:10 -08:00
# pragma mark -
# pragma mark Styles
2015-10-31 16:35:32 -07:00
- ( IBAction ) toggleFontSize : ( id ) sender {
2017-04-03 16:07:01 -07:00
UINavigationController * fontSettingsNavigationController = appDelegate . fontSettingsNavigationController ;
2016-03-19 13:19:06 -04:00
[ fontSettingsNavigationController popToRootViewControllerAnimated : NO ] ;
2017-04-03 16:07:01 -07:00
[ appDelegate showPopoverWithViewController : fontSettingsNavigationController contentSize : CGSizeZero barButtonItem : self . fontSettingsButton ] ;
2012-11-05 17:16:10 -08:00
}
2012-11-09 14:13:44 -08:00
- ( void ) setFontStyle : ( NSString * ) fontStyle {
2021-01-29 20:10:53 -08:00
[ self . currentPage setFontStyle : fontStyle ] ;
[ self . nextPage setFontStyle : fontStyle ] ;
[ self . previousPage setFontStyle : fontStyle ] ;
2012-11-09 14:13:44 -08:00
}
- ( void ) changeFontSize : ( NSString * ) fontSize {
2021-01-29 20:10:53 -08:00
[ self . currentPage changeFontSize : fontSize ] ;
[ self . nextPage changeFontSize : fontSize ] ;
[ self . previousPage changeFontSize : fontSize ] ;
2012-11-09 14:13:44 -08:00
}
2014-05-15 18:06:56 -07:00
- ( void ) changeLineSpacing : ( NSString * ) lineSpacing {
2021-01-29 20:10:53 -08:00
[ self . currentPage changeLineSpacing : lineSpacing ] ;
[ self . nextPage changeLineSpacing : lineSpacing ] ;
[ self . previousPage changeLineSpacing : lineSpacing ] ;
2014-05-15 18:06:56 -07:00
}
2019-02-27 13:33:38 -08:00
- ( void ) changedFullscreen {
2020-06-20 21:31:21 -07:00
BOOL wantHidden = self . allowFullscreen ;
2019-02-27 13:33:38 -08:00
2021-01-30 20:33:29 -08:00
// self . navigationController . hidesBarsOnSwipe = self . allowFullscreen ;
2020-06-20 21:31:21 -07:00
[ self setNavigationBarHidden : wantHidden alsoTraverse : YES ] ;
2019-02-27 13:33:38 -08:00
}
- ( void ) changedAutoscroll {
2019-02-28 15:29:31 -08:00
self . autoscrollActive = self . autoscrollAvailable ;
2019-02-27 13:33:38 -08:00
}
2018-09-05 13:51:33 -07:00
- ( void ) changedScrollOrientation {
[ self . scrollView setAlwaysBounceHorizontal : self . isHorizontal ] ;
[ self . scrollView setAlwaysBounceVertical : ! self . isHorizontal ] ;
[ self reorientPages ] ;
}
2018-10-22 15:14:12 -07:00
- ( void ) updateStoriesTheme {
2021-01-29 20:10:53 -08:00
[ self . currentPage updateStoryTheme ] ;
[ self . nextPage updateStoryTheme ] ;
[ self . previousPage updateStoryTheme ] ;
2015-12-07 16:09:49 -08:00
}
2020-04-22 19:31:08 -07:00
- ( void ) updateStatusBarTheme {
2020-09-22 17:28:14 -07:00
if ( [ [ UIDevice currentDevice ] userInterfaceIdiom ] = = UIUserInterfaceIdiomPhone ) {
2020-04-22 19:31:08 -07:00
[ self updateStatusBarState ] ;
}
}
2013-07-13 16:56:33 +02:00
# pragma mark -
# pragma mark HUDs
2012-11-09 14:13:44 -08:00
- ( void ) showShareHUD : ( NSString * ) msg {
2018-07-13 15:25:27 -04:00
[ MBProgressHUD hideHUDForView : self . view animated : NO ] ;
2021-01-29 20:10:53 -08:00
self . storyHUD = [ MBProgressHUD showHUDAddedTo : currentPage . view animated : YES ] ;
2012-11-09 14:13:44 -08:00
self . storyHUD . labelText = msg ;
self . storyHUD . margin = 20.0 f ;
2018-07-13 15:25:27 -04:00
self . storyHUD . removeFromSuperViewOnHide = YES ;
2021-01-29 20:10:53 -08:00
self . currentPage . noStoryMessage . hidden = YES ;
2012-11-09 14:13:44 -08:00
}
2013-07-13 16:56:33 +02:00
- ( void ) flashCheckmarkHud : ( NSString * ) messageType {
2021-01-29 20:10:53 -08:00
[ [ self currentPage ] flashCheckmarkHud : messageType ] ;
2013-07-13 16:56:33 +02:00
}
2015-10-28 21:50:23 -07:00
- ( void ) showFetchingTextNotifier {
self . notifier . style = NBSyncingStyle ;
self . notifier . title = @ "Fetching text..." ;
[ self . notifier setProgress : 0 ] ;
[ self . notifier show ] ;
}
- ( void ) hideNotifier {
[ self . notifier hide ] ;
}
2019-02-28 15:29:31 -08:00
# pragma mark -
# pragma mark Story Autoscroll
- ( BOOL ) autoscrollAvailable {
return [ [ NSUserDefaults standardUserDefaults ] boolForKey : @ "story_autoscroll" ] ;
}
- ( void ) setAutoscrollAvailable : ( BOOL ) available {
[ [ NSUserDefaults standardUserDefaults ] setBool : available forKey : @ "story_autoscroll" ] ;
}
- ( NSTimeInterval ) autoscrollSpeed {
CGFloat speed = [ [ NSUserDefaults standardUserDefaults ] doubleForKey : @ "story_autoscroll_speed" ] ;
if ( speed <= 0 ) {
speed = 0.03 ;
}
return speed ;
}
- ( void ) setAutoscrollSpeed : ( NSTimeInterval ) speed {
[ [ NSUserDefaults standardUserDefaults ] setDouble : speed forKey : @ "story_autoscroll_speed" ] ;
// This will update the timer with the new speed .
self . autoscrollActive = self . autoscrollActive ;
NSLog ( @ "set autoscroll speed to: %@" , @ ( speed ) ) ; // log
}
- ( BOOL ) autoscrollActive {
return self . autoscrollTimer ! = nil ;
}
- ( void ) setAutoscrollActive : ( BOOL ) active {
[ self . autoscrollTimer invalidate ] ;
self . autoscrollTimer = nil ;
if ( active && self . autoscrollAvailable ) {
self . autoscrollTimer = [ NSTimer scheduledTimerWithTimeInterval : self . autoscrollSpeed target : self selector : @ selector ( autoscroll : ) userInfo : nil repeats : YES ] ;
}
[ self updateAutoscrollButtons ] ;
}
- ( void ) autoscroll : ( NSTimer * ) timer {
2021-01-29 20:10:53 -08:00
WKWebView * webView = self . currentPage . webView ;
2019-02-28 15:29:31 -08:00
CGFloat position = webView . scrollView . contentOffset . y + 0.5 ;
2020-09-25 20:31:01 -07:00
CGFloat maximum = ( webView . scrollView . contentSize . height - webView . frame . size . height ) + self . view . safeAreaInsets . bottom ;
2019-02-28 15:29:31 -08:00
if ( position < maximum ) {
[ webView . scrollView setContentOffset : CGPointMake ( 0 , position ) animated : NO ] ;
} else {
self . autoscrollActive = NO ;
}
}
2020-06-20 21:31:21 -07:00
- ( void ) tappedStory {
if ( self . autoscrollAvailable ) {
[ self showAutoscrollBriefly : YES ] ;
2021-01-30 20:33:29 -08:00
// } else if ( self . allowFullscreen ) {
// [ self setNavigationBarHidden : ! self . isNavigationBarHidden ] ;
2020-06-20 21:31:21 -07:00
}
}
2019-02-28 15:29:31 -08:00
- ( void ) showAutoscrollBriefly : ( BOOL ) briefly {
2021-01-29 20:10:53 -08:00
if ( ! self . autoscrollAvailable || self . currentPage . webView . scrollView . contentSize . height - 200 <= self . currentPage . view . frame . size . height ) {
2019-05-16 13:58:03 -07:00
[ self hideAutoscrollWithAnimation ] ;
2019-02-28 15:29:31 -08:00
return ;
}
if ( self . autoscrollView . alpha = = 0 ) {
2019-04-16 20:24:42 -07:00
if ( self . isPhoneOrCompact ) {
2021-01-30 20:33:29 -08:00
self . autoscrollBottomConstraint . constant = 70 ;
2019-04-16 20:24:42 -07:00
} else {
2021-01-29 20:10:53 -08:00
self . autoscrollBottomConstraint . constant = 0 ;
2019-04-16 20:24:42 -07:00
}
[ self . view layoutIfNeeded ] ;
2019-02-28 15:29:31 -08:00
[ UIView animateWithDuration : 0.2 animations : ^ {
[ self . view layoutIfNeeded ] ;
self . autoscrollView . alpha = 1 ;
} ] ;
}
if ( briefly ) {
[ self hideAutoscrollAfterDelay ] ;
}
}
- ( void ) hideAutoscrollAfterDelay {
[ self . autoscrollViewTimer invalidate ] ;
2019-05-16 13:58:03 -07:00
self . autoscrollViewTimer = [ NSTimer scheduledTimerWithTimeInterval : 2 target : self selector : @ selector ( hideAutoscrollWithAnimation ) userInfo : nil repeats : NO ] ;
2019-02-28 15:29:31 -08:00
}
2019-05-16 13:58:03 -07:00
- ( void ) hideAutoscrollWithAnimation {
2019-02-28 15:29:31 -08:00
[ self . autoscrollViewTimer invalidate ] ;
self . autoscrollViewTimer = nil ;
2021-08-24 21:01:28 -07:00
[ self . view layoutIfNeeded ] ;
2019-02-28 15:29:31 -08:00
[ UIView animateWithDuration : 1 animations : ^ {
[ self . view layoutIfNeeded ] ;
self . autoscrollView . alpha = 0 ;
} ] ;
}
2019-05-16 13:58:03 -07:00
- ( void ) hideAutoscrollImmediately {
[ self . autoscrollViewTimer invalidate ] ;
self . autoscrollViewTimer = nil ;
self . autoscrollView . alpha = 0 ;
}
2019-02-28 15:29:31 -08:00
- ( void ) resetAutoscrollViewTimerIfNeeded {
if ( self . autoscrollViewTimer ! = nil ) {
[ self hideAutoscrollAfterDelay ] ;
}
}
- ( IBAction ) autoscrollDisable : ( UIButton * ) sender {
self . autoscrollAvailable = NO ;
self . autoscrollActive = NO ;
2019-05-16 13:58:03 -07:00
[ self hideAutoscrollWithAnimation ] ;
2019-02-28 15:29:31 -08:00
}
- ( IBAction ) autoscrollPauseResume : ( UIButton * ) sender {
self . autoscrollActive = ! self . autoscrollActive ;
[ self resetAutoscrollViewTimerIfNeeded ] ;
}
- ( IBAction ) autoscrollSlower : ( UIButton * ) sender {
if ( self . autoscrollSpeed < 1 ) {
self . autoscrollSpeed = self . autoscrollSpeed * 2 ; // + 0.05 ;
} else {
NSLog ( @ "Minimum autoscroll speed reached" ) ; // log
}
[ self resetAutoscrollViewTimerIfNeeded ] ;
}
- ( IBAction ) autoscrollFaster : ( UIButton * ) sender {
if ( self . autoscrollSpeed > 0.001 ) {
self . autoscrollSpeed = self . autoscrollSpeed / 2 ; // - 0.05 ;
} else {
NSLog ( @ "Maximum autoscroll speed reached" ) ; // log
}
[ self resetAutoscrollViewTimerIfNeeded ] ;
}
2012-11-05 17:16:10 -08:00
# pragma mark -
# pragma mark Story Traversal
2013-10-08 13:57:15 -07:00
- ( IBAction ) doNextUnreadStory : ( id ) sender {
2017-04-03 16:07:01 -07:00
FeedDetailViewController * fdvc = appDelegate . feedDetailViewController ;
2014-02-12 20:09:37 -08:00
NSInteger nextLocation = [ appDelegate . storiesCollection locationOfNextUnreadStory ] ;
2013-09-25 17:43:00 -07:00
NSInteger unreadCount = [ appDelegate unreadCount ] ;
2017-04-03 16:07:01 -07:00
BOOL pageFinished = appDelegate . feedDetailViewController . pageFinished ;
2014-04-18 14:48:38 -07:00
2012-11-05 17:16:10 -08:00
[ self . loadingIndicator stopAnimating ] ;
2013-10-08 13:57:15 -07:00
[ self endTouchDown : sender ] ;
2012-12-13 17:25:52 -08:00
// NSLog ( @ "doNextUnreadStory: %d (out of %d)" , nextLocation , unreadCount ) ;
2012-12-13 16:41:52 -08:00
2014-04-18 14:48:38 -07:00
if ( nextLocation = = -1 && unreadCount > 0 && ! pageFinished &&
2014-02-27 14:49:33 -08:00
appDelegate . storiesCollection . feedPage < 100 ) {
2012-11-05 17:16:10 -08:00
[ self . loadingIndicator startAnimating ] ;
2013-04-23 11:52:34 -07:00
self . circularProgressView . hidden = YES ;
2012-11-06 17:26:08 -08:00
self . buttonNext . enabled = NO ;
// Fetch next page and see if it has the unreads .
2012-12-13 16:41:52 -08:00
self . waitingForNextUnreadFromServer = YES ;
[ fdvc fetchNextPage : nil ] ;
2012-11-06 13:45:15 -08:00
} else if ( nextLocation = = -1 ) {
2012-11-05 17:16:10 -08:00
[ appDelegate hideStoryDetailView ] ;
} else {
2012-11-06 13:45:15 -08:00
[ self changePage : nextLocation ] ;
2012-11-05 17:16:10 -08:00
}
}
2013-10-08 13:57:15 -07:00
- ( IBAction ) doPreviousStory : ( id ) sender {
[ self endTouchDown : sender ] ;
2012-11-05 17:16:10 -08:00
[ self . loadingIndicator stopAnimating ] ;
2013-04-23 11:52:34 -07:00
self . circularProgressView . hidden = NO ;
2014-02-12 20:09:37 -08:00
id previousStoryId = [ appDelegate . storiesCollection popReadStory ] ;
2014-02-12 20:41:29 -08:00
if ( ! previousStoryId || previousStoryId = = [ appDelegate . activeStory objectForKey : @ "story_hash" ] ) {
2021-06-04 21:49:08 -07:00
[ self . appDelegate showColumn : UISplitViewControllerColumnSupplementary debugInfo : @ "doPreviousStory" ] ;
2012-11-05 17:16:10 -08:00
[ appDelegate hideStoryDetailView ] ;
} else {
2014-02-12 20:09:37 -08:00
NSInteger previousLocation = [ appDelegate . storiesCollection locationOfStoryId : previousStoryId ] ;
2012-11-06 13:45:15 -08:00
if ( previousLocation = = -1 ) {
2013-10-08 13:57:15 -07:00
return [ self doPreviousStory : sender ] ;
2012-11-05 17:16:10 -08:00
}
2012-11-06 13:45:15 -08:00
[ self changePage : previousLocation ] ;
2012-11-05 17:16:10 -08:00
}
}
2012-11-05 15:12:42 -08:00
@ end