mirror of
https://github.com/viq/NewsBlur.git
synced 2025-09-18 21:43:31 +00:00
iOS: #1160 (state restoration)
- Added a "Restore position" preference in the "Reading Stories" group, with options to restore the previous state on launch always, within a specified interval, or never. - When within the indicated interval, the app restores the feeds, feed detail, and story selections and scrolling positions. - The active story is marked unread to ensure it remains available for restoring, and re-marked read when resumed. - NOTE: only supported on iPhone for now. I’ll add iPad support later.
This commit is contained in:
parent
f10a002d46
commit
ed8d3c76e6
13 changed files with 275 additions and 37 deletions
|
@ -44,6 +44,8 @@
|
|||
@interface FeedDetailViewController ()
|
||||
|
||||
@property (nonatomic) NSUInteger scrollingMarkReadRow;
|
||||
@property (nonatomic, strong) NSString *restoringFolder;
|
||||
@property (nonatomic, strong) NSString *restoringFeedID;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -82,7 +84,9 @@
|
|||
selector:@selector(preferredContentSizeChanged:)
|
||||
name:UIContentSizeCategoryDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(finishedLoadingFeedsNotification:) name:@"FinishedLoadingFeedsNotification" object:nil];
|
||||
|
||||
self.storyTitlesTable.backgroundColor = UIColorFromRGB(0xf4f4f4);
|
||||
self.storyTitlesTable.separatorColor = UIColorFromRGB(0xE9E8E4);
|
||||
if (@available(iOS 11.0, *)) {
|
||||
|
@ -528,6 +532,57 @@
|
|||
return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone || self.appDelegate.isCompactWidth;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark State Restoration
|
||||
|
||||
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {
|
||||
[super encodeRestorableStateWithCoder:coder];
|
||||
|
||||
[coder encodeObject:appDelegate.storiesCollection.activeFolder forKey:@"folder"];
|
||||
|
||||
if (appDelegate.storiesCollection.activeFeed != nil) {
|
||||
[coder encodeObject:[NSString stringWithFormat:@"%@", appDelegate.storiesCollection.activeFeed[@"id"]] forKey:@"feed_id"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder {
|
||||
[super decodeRestorableStateWithCoder:coder];
|
||||
|
||||
NSString *folder = [coder decodeObjectOfClass:[NSString class] forKey:@"folder"];
|
||||
NSString *feedID = [coder decodeObjectOfClass:[NSString class] forKey:@"feed_id"];
|
||||
|
||||
if (folder != nil || feedID != nil) {
|
||||
self.restoringFolder = folder;
|
||||
self.restoringFeedID = feedID;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)finishedLoadingFeedsNotification:(NSNotification *)notification {
|
||||
if (self.restoringFeedID.length > 0) {
|
||||
NSDictionary *feed = [appDelegate getFeed:self.restoringFeedID];
|
||||
|
||||
if (feed != nil) {
|
||||
appDelegate.storiesCollection.isSocialView = NO;
|
||||
appDelegate.storiesCollection.activeFeed = feed;
|
||||
[appDelegate loadFeedDetailView:NO];
|
||||
[self viewWillAppear:NO];
|
||||
}
|
||||
} else if (self.restoringFolder.length > 0) {
|
||||
NSString *folder = self.restoringFolder;
|
||||
NSInteger index = [appDelegate.dictFoldersArray indexOfObject:folder];
|
||||
|
||||
if (index != NSNotFound && index > NewsBlurTopSectionAllStories) {
|
||||
folder = [NSString stringWithFormat:@"%@", @(index)];
|
||||
}
|
||||
|
||||
[appDelegate loadRiverFeedDetailView:self withFolder:folder];
|
||||
[self viewWillAppear:NO];
|
||||
}
|
||||
|
||||
self.restoringFolder = nil;
|
||||
self.restoringFeedID = 0;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
|
||||
|
|
|
@ -321,7 +321,19 @@
|
|||
self.storyPageControl.navigationItem.titleView = titleLabel;
|
||||
}
|
||||
|
||||
# pragma mark Modals and Popovers
|
||||
#pragma mark -
|
||||
#pragma mark State Restoration
|
||||
|
||||
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {
|
||||
[super encodeRestorableStateWithCoder:coder];
|
||||
}
|
||||
|
||||
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder {
|
||||
[super decodeRestorableStateWithCoder:coder];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Modals and Popovers
|
||||
|
||||
- (void)showUserProfilePopover:(id)sender {
|
||||
if ([sender class] == [InteractionCell class] ||
|
||||
|
|
|
@ -79,6 +79,8 @@
|
|||
|
||||
#define CURRENT_DB_VERSION 36
|
||||
|
||||
#define CURRENT_STATE_VERSION 1
|
||||
|
||||
@synthesize window;
|
||||
|
||||
@synthesize ftuxNavigationController;
|
||||
|
@ -193,7 +195,7 @@
|
|||
return (NewsBlurAppDelegate*) [UIApplication sharedApplication].delegate;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
[self registerDefaultsFromSettingsBundle];
|
||||
|
||||
self.navigationController.delegate = self;
|
||||
|
@ -242,6 +244,10 @@
|
|||
// Uncomment below line to test image caching
|
||||
// [[NSURLCache sharedURLCache] removeAllCachedResponses];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
if ([UIApplicationShortcutItem class] && launchOptions[UIApplicationLaunchOptionsShortcutItemKey]) {
|
||||
self.launchedShortcutItem = launchOptions[UIApplicationLaunchOptionsShortcutItemKey];
|
||||
return NO;
|
||||
|
@ -262,6 +268,12 @@
|
|||
[self handleShortcutItem:self.launchedShortcutItem];
|
||||
self.launchedShortcutItem = nil;
|
||||
}
|
||||
|
||||
if (storyPageControl.temporarilyMarkedUnread && [storiesCollection isStoryUnread:activeStory]) {
|
||||
[storiesCollection markStoryRead:activeStory];
|
||||
[storiesCollection syncStoryAsRead:activeStory];
|
||||
storyPageControl.temporarilyMarkedUnread = NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
|
@ -276,6 +288,75 @@
|
|||
[self.feedsViewController refreshHeaderCounts];
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder {
|
||||
// Temporary? bypass to not save on iPad, since that isn't supported yet.
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder {
|
||||
[coder encodeInteger:CURRENT_STATE_VERSION forKey:@"version"];
|
||||
[coder encodeObject:[NSDate date] forKey:@"last_saved_state_date"];
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder {
|
||||
// Temporary? bypass to not restore on iPad, since that isn't supported yet.
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
|
||||
NSString *option = [preferences stringForKey:@"restore_state"];
|
||||
|
||||
if ([option isEqualToString:@"never"]) {
|
||||
return NO;
|
||||
} else if ([option isEqualToString:@"always"]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
NSTimeInterval daysInterval = 60 * 60;
|
||||
NSTimeInterval limitInterval = option.doubleValue * daysInterval;
|
||||
NSInteger version = [coder decodeIntegerForKey:@"version"];
|
||||
NSDate *lastSavedDate = [coder decodeObjectOfClass:[NSDate class] forKey:@"last_saved_state_date"];
|
||||
|
||||
if (limitInterval == 0) {
|
||||
limitInterval = 24 * daysInterval;
|
||||
}
|
||||
|
||||
if (version > CURRENT_STATE_VERSION || lastSavedDate == nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSTimeInterval savedInterval = -[lastSavedDate timeIntervalSinceNow];
|
||||
|
||||
return savedInterval < limitInterval;
|
||||
}
|
||||
|
||||
- (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder {
|
||||
NSString *identifier = identifierComponents.lastObject;
|
||||
|
||||
if ([identifier isEqualToString:@"MainNavigation"]) {
|
||||
return self.navigationController;
|
||||
} else if ([identifier isEqualToString:@"FeedsView"]) {
|
||||
return self.feedsViewController;
|
||||
} else if ([identifier isEqualToString:@"FeedDetailView"]) {
|
||||
return self.feedDetailViewController;
|
||||
} else if ([identifier isEqualToString:@"StoryPageControl"]) {
|
||||
return self.storyPageControl;
|
||||
} else if ([identifier isEqualToString:@"ContainerView"]) {
|
||||
return self.masterContainerViewController;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder {
|
||||
// All done; could do any cleanup here
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
|
||||
completionHandler([self handleShortcutItem:shortcutItem]);
|
||||
}
|
||||
|
@ -1538,7 +1619,7 @@
|
|||
[self.folderCountCache removeObjectForKey:feedDetailView.storiesCollection.activeFolder];
|
||||
}
|
||||
|
||||
if (feedDetailView == feedDetailViewController) {
|
||||
if (feedDetailView == feedDetailViewController && feedDetailView.navigationController == nil) {
|
||||
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle: @"All"
|
||||
style: UIBarButtonItemStylePlain
|
||||
target: nil
|
||||
|
|
|
@ -444,6 +444,17 @@ static NSArray<NSString *> *NewsBlurTopSectionNames;
|
|||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark State Restoration
|
||||
|
||||
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {
|
||||
[super encodeRestorableStateWithCoder:coder];
|
||||
}
|
||||
|
||||
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder {
|
||||
[super decodeRestorableStateWithCoder:coder];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@
|
|||
- (NSInteger)indexOfActiveStory {
|
||||
for (NSInteger i=0; i < self.storyCount; i++) {
|
||||
NSDictionary *story = [activeFeedStories objectAtIndex:i];
|
||||
if ([appDelegate.activeStory objectForKey:@"story_hash"] == [story objectForKey:@"story_hash"]) {
|
||||
if ([[appDelegate.activeStory objectForKey:@"story_hash"] isEqualToString:[story objectForKey:@"story_hash"]]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +186,7 @@
|
|||
- (NSInteger)indexOfStoryId:(id)storyId {
|
||||
for (int i=0; i < self.storyCount; i++) {
|
||||
NSDictionary *story = [activeFeedStories objectAtIndex:i];
|
||||
if ([story objectForKey:@"story_hash"] == storyId) {
|
||||
if ([[story objectForKey:@"story_hash"] isEqualToString:storyId]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +195,7 @@
|
|||
|
||||
- (NSInteger)locationOfStoryId:(id)storyId {
|
||||
for (int i=0; i < [activeFeedStoryLocations count]; i++) {
|
||||
if ([activeFeedStoryLocationIds objectAtIndex:i] == storyId) {
|
||||
if ([[activeFeedStoryLocationIds objectAtIndex:i] isEqualToString:storyId]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -429,6 +429,10 @@
|
|||
// NSLog(@"Already drawn story, drawing anyway: %@", [self.activeStory objectForKey:@"story_title"]);
|
||||
// return;
|
||||
}
|
||||
|
||||
if (self.activeStory == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
scrollPct = 0;
|
||||
hasScrolled = NO;
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
@property (nonatomic) BOOL forceNavigationBarShown;
|
||||
@property (nonatomic) BOOL currentlyTogglingNavigationBar;
|
||||
@property (nonatomic, readonly) BOOL isHorizontal;
|
||||
@property (nonatomic) BOOL temporarilyMarkedUnread;
|
||||
|
||||
- (void)resizeScrollView;
|
||||
- (void)applyNewIndex:(NSInteger)newIndex pageController:(StoryDetailViewController *)pageController;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
@property (nonatomic, strong) NSTimer *autoscrollTimer;
|
||||
@property (nonatomic, strong) NSTimer *autoscrollViewTimer;
|
||||
@property (nonatomic, strong) NSString *restoringStoryId;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -231,7 +232,7 @@
|
|||
context:nil];
|
||||
|
||||
_orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||
|
||||
|
||||
[self addKeyCommandWithInput:UIKeyInputDownArrow modifierFlags:0 action:@selector(changeToNextPage:) discoverabilityTitle:@"Next Story"];
|
||||
[self addKeyCommandWithInput:@"j" modifierFlags:0 action:@selector(changeToNextPage:) discoverabilityTitle:@"Next Story"];
|
||||
[self addKeyCommandWithInput:UIKeyInputUpArrow modifierFlags:0 action:@selector(changeToPreviousPage:) discoverabilityTitle:@"Previous Story"];
|
||||
|
@ -761,6 +762,38 @@
|
|||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark State Restoration
|
||||
|
||||
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {
|
||||
[super encodeRestorableStateWithCoder:coder];
|
||||
|
||||
[coder encodeObject:currentPage.activeStoryId forKey:@"current_story_id"];
|
||||
|
||||
[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];
|
||||
|
||||
if (pageIndex < 0) {
|
||||
[self doNextUnreadStory:nil];
|
||||
} else {
|
||||
[self changePage:pageIndex animated:NO];
|
||||
}
|
||||
|
||||
self.restoringStoryId = nil;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Side scroll view
|
||||
|
||||
|
@ -1166,6 +1199,11 @@
|
|||
}
|
||||
|
||||
- (void)advanceToNextUnread {
|
||||
if (self.restoringStoryId.length > 0) {
|
||||
[self restorePage];
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.waitingForNextUnreadFromServer) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" colorMatched="YES">
|
||||
<device id="ipad9_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -44,7 +44,7 @@
|
|||
<outlet property="window" destination="12" id="78"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<window opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="12" customClass="EventWindow">
|
||||
<window opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" restorationIdentifier="EventWindow" id="12" customClass="EventWindow">
|
||||
<rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
@ -114,7 +114,7 @@
|
|||
<outlet property="appDelegate" destination="3" id="279"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<viewController nibName="FeedDetailViewController" id="51" customClass="FeedDetailViewController">
|
||||
<viewController restorationIdentifier="FeedDetailView" nibName="FeedDetailViewController" id="51" customClass="FeedDetailViewController">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="blackOpaque"/>
|
||||
<connections>
|
||||
|
@ -150,7 +150,7 @@
|
|||
<outlet property="appDelegate" destination="3" id="288"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<viewController nibName="NewsBlurViewController" id="10" customClass="NewsBlurViewController">
|
||||
<viewController restorationIdentifier="FeedsView" nibName="NewsBlurViewController" id="10" customClass="NewsBlurViewController">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="blackOpaque"/>
|
||||
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
|
||||
|
@ -165,14 +165,14 @@
|
|||
<outlet property="appDelegate" destination="3" id="271"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<viewController id="290" customClass="StoryPageControl">
|
||||
<viewController restorationIdentifier="StoryPageControl" id="290" customClass="StoryPageControl">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="blackOpaque"/>
|
||||
<connections>
|
||||
<outlet property="appDelegate" destination="3" id="291"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<viewController nibName="StoryDetailViewController" id="92" customClass="StoryDetailViewController">
|
||||
<viewController restorationIdentifier="StoryDetailView" nibName="StoryDetailViewController" id="92" customClass="StoryDetailViewController">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="blackOpaque"/>
|
||||
<connections>
|
||||
|
@ -186,18 +186,18 @@
|
|||
<outlet property="appDelegate" destination="3" id="237"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<viewController title="Main Container View Controller" id="264" customClass="NBContainerViewController">
|
||||
<viewController restorationIdentifier="ContainerView" title="Main Container View Controller" id="264" customClass="NBContainerViewController">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="blackOpaque"/>
|
||||
<connections>
|
||||
<outlet property="appDelegate" destination="3" id="267"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<navigationController title="Main" id="173">
|
||||
<navigationController restorationIdentifier="MainNavigation" title="Main" id="173">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="blackOpaque"/>
|
||||
<navigationBar key="navigationBar" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="174">
|
||||
<rect key="frame" x="0.0" y="20" width="768" height="44"/>
|
||||
<rect key="frame" x="0.0" y="-50" width="768" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<viewControllers>
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina5_5" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
|
||||
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
|
@ -21,11 +19,11 @@
|
|||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="1">
|
||||
<view contentMode="scaleToFill" restorationIdentifier="FeedDetailView" id="1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" bouncesZoom="NO" style="plain" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="4">
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" restorationIdentifier="FeedDetailTable" showsHorizontalScrollIndicator="NO" bouncesZoom="NO" style="plain" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<inset key="separatorInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
|
@ -44,7 +42,7 @@
|
|||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" alpha="0.40000000596046448" contentMode="scaleToFill" image="big_world.png" translatesAutoresizingMaskIntoConstraints="NO" id="Kdh-D5-esJ">
|
||||
<rect key="frame" x="175.33333333333334" y="24" width="64" height="64"/>
|
||||
<rect key="frame" x="175" y="24" width="64" height="64"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="64" id="1c2-mE-46C"/>
|
||||
<constraint firstAttribute="width" constant="64" id="Odo-if-TOJ"/>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -42,7 +42,7 @@
|
|||
<outlet property="window" destination="12" id="78"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<viewController nibName="NewsBlurViewController" id="10" customClass="NewsBlurViewController">
|
||||
<viewController restorationIdentifier="FeedsView" nibName="NewsBlurViewController" id="10" customClass="NewsBlurViewController">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
|
||||
<connections>
|
||||
|
@ -61,19 +61,19 @@
|
|||
<outlet property="appDelegate" destination="3" id="166"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<viewController nibName="FeedDetailViewController" id="51" customClass="FeedDetailViewController">
|
||||
<viewController restorationIdentifier="FeedDetailView" nibName="FeedDetailViewController" id="51" customClass="FeedDetailViewController">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<connections>
|
||||
<outlet property="appDelegate" destination="3" id="58"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<viewController nibName="StoryDetailViewController" id="92" customClass="StoryDetailViewController">
|
||||
<viewController restorationIdentifier="StoryDetailView" nibName="StoryDetailViewController" id="92" customClass="StoryDetailViewController">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<connections>
|
||||
<outlet property="appDelegate" destination="3" id="105"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<viewController nibName="StoryPageControl" automaticallyAdjustsScrollViewInsets="NO" id="170" customClass="StoryPageControl">
|
||||
<viewController restorationIdentifier="StoryPageControl" nibName="StoryPageControl" automaticallyAdjustsScrollViewInsets="NO" id="170" customClass="StoryPageControl">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
|
||||
<connections>
|
||||
|
@ -162,22 +162,22 @@
|
|||
<outlet property="appDelegate" destination="3" id="158"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<viewController id="177" customClass="DashboardViewController">
|
||||
<viewController restorationIdentifier="DashboardView" id="177" customClass="DashboardViewController">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<connections>
|
||||
<outlet property="appDelegate" destination="3" id="178"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<window opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="12" customClass="EventWindow">
|
||||
<window opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" restorationIdentifier="EventWindow" id="12" customClass="EventWindow">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
</window>
|
||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="39">
|
||||
<navigationController restorationIdentifier="MainNavigation" automaticallyAdjustsScrollViewInsets="NO" id="39">
|
||||
<extendedEdge key="edgesForExtendedLayout"/>
|
||||
<navigationBar key="navigationBar" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="41">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
|
||||
<rect key="frame" x="0.0" y="-44" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<viewControllers>
|
||||
|
|
|
@ -24,14 +24,14 @@
|
|||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="6">
|
||||
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" restorationIdentifier="RootView" id="6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="85">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="436"/>
|
||||
<subviews>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" bouncesZoom="NO" style="plain" separatorStyle="none" rowHeight="6" estimatedRowHeight="6" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="8" userLabel="Table View">
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" restorationIdentifier="FeedTitlesTable" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" bouncesZoom="NO" style="plain" separatorStyle="none" rowHeight="6" estimatedRowHeight="6" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="8" userLabel="Table View">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="436"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="lightTextColor"/>
|
||||
<connections>
|
||||
|
|
|
@ -700,6 +700,44 @@
|
|||
<key>Key</key>
|
||||
<string>story_browser</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Type</key>
|
||||
<string>PSMultiValueSpecifier</string>
|
||||
<key>Title</key>
|
||||
<string>Restore position</string>
|
||||
<key>Titles</key>
|
||||
<array>
|
||||
<string>Always</string>
|
||||
<string>Within 1 hour</string>
|
||||
<string>Within 2 hours</string>
|
||||
<string>Within 4 hours</string>
|
||||
<string>Within 6 hours</string>
|
||||
<string>Within 8 hours</string>
|
||||
<string>Within 12 hours</string>
|
||||
<string>Within 1 day</string>
|
||||
<string>Within 2 days</string>
|
||||
<string>Within 1 week</string>
|
||||
<string>Never</string>
|
||||
</array>
|
||||
<key>DefaultValue</key>
|
||||
<string>24</string>
|
||||
<key>Values</key>
|
||||
<array>
|
||||
<string>always</string>
|
||||
<string>1</string>
|
||||
<string>2</string>
|
||||
<string>4</string>
|
||||
<string>6</string>
|
||||
<string>8</string>
|
||||
<string>12</string>
|
||||
<string>24</string>
|
||||
<string>48</string>
|
||||
<string>168</string>
|
||||
<string>never</string>
|
||||
</array>
|
||||
<key>Key</key>
|
||||
<string>restore_state</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Title</key>
|
||||
<string>App badge</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue