├── .gitignore ├── .gitmodules ├── CREDITS ├── Classes ├── AppDelegate.h ├── AppDelegate.m ├── Categories │ ├── NSArray+Strings.h │ ├── NSArray+Strings.m │ ├── NSDictionary+Parameters.h │ ├── NSDictionary+Parameters.m │ ├── NSString+Entities.h │ ├── NSString+Entities.m │ ├── NSString+Tags.h │ ├── NSString+Tags.m │ ├── UIActionSheet+Context.h │ ├── UIActionSheet+Context.m │ ├── UIApplication+ActivityIndicator.h │ ├── UIApplication+ActivityIndicator.m │ ├── UIColor+Orange.h │ ├── UIColor+Orange.m │ ├── UIImage+Colorize.h │ ├── UIImage+Colorize.m │ ├── UINavigationItem+MultipleItems.h │ └── UINavigationItem+MultipleItems.m ├── Cells │ ├── CommentTableCell.h │ ├── CommentTableCell.m │ ├── LoadMoreCell.h │ ├── LoadMoreCell.m │ ├── SubmissionTableCell.h │ ├── SubmissionTableCell.m │ ├── TableViewCell.h │ └── TableViewCell.m ├── Controllers │ ├── BrowserController.h │ ├── BrowserController.m │ ├── CommentListController.h │ ├── CommentListController.m │ ├── ComposeController.h │ ├── ComposeController.m │ ├── EmptyController.h │ ├── EmptyController.m │ ├── EntryListController.h │ ├── EntryListController.m │ ├── EntryReplyComposeController.h │ ├── EntryReplyComposeController.m │ ├── HackerNewsLoginController.h │ ├── HackerNewsLoginController.m │ ├── InstapaperActivity.h │ ├── InstapaperActivity.m │ ├── InstapaperLoginController.h │ ├── InstapaperLoginController.m │ ├── InstapaperSubmission.h │ ├── InstapaperSubmission.m │ ├── LoadingController.h │ ├── LoadingController.m │ ├── LoginController.h │ ├── LoginController.m │ ├── MainTabBarController.h │ ├── MainTabBarController.m │ ├── ModalNavigationController.h │ ├── ModalNavigationController.m │ ├── MoreController.h │ ├── MoreController.m │ ├── NavigationController.h │ ├── NavigationController.m │ ├── OpenInSafariActivity.h │ ├── OpenInSafariActivity.m │ ├── ProfileController.h │ ├── ProfileController.m │ ├── SearchController.h │ ├── SearchController.m │ ├── SessionListController.h │ ├── SessionListController.m │ ├── SessionProfileController.h │ ├── SessionProfileController.m │ ├── SharingController.h │ ├── SharingController.m │ ├── SplitViewController.h │ ├── SplitViewController.m │ ├── SubmissionListController.h │ ├── SubmissionListController.m │ ├── SubmissionTextComposeController.h │ ├── SubmissionTextComposeController.m │ ├── SubmissionURLComposeController.h │ ├── SubmissionURLComposeController.m │ ├── TabBarController.h │ └── TabBarController.m ├── Follow Model │ ├── HNSession+Following.h │ ├── HNSession+Following.m │ ├── HNTimeline.h │ └── HNTimeline.m ├── HNKit │ ├── HNKit.h │ ├── HNSessionAuthenticator.m │ └── HNShared.h ├── Instapaper │ ├── InstapaperAPI.h │ ├── InstapaperAuthenticator.h │ ├── InstapaperAuthenticator.m │ ├── InstapaperRequest.h │ ├── InstapaperRequest.m │ ├── InstapaperSession.h │ └── InstapaperSession.m ├── PingController.h ├── PingController.m ├── Prefix.pch ├── UMAnalytics_Sdk_3.1.9 │ ├── MobClick.h │ └── MobClickSocialAnalytics.h ├── Views │ ├── ActivityIndicatorItem.h │ ├── ActivityIndicatorItem.m │ ├── BarButtonItem.h │ ├── BarButtonItem.m │ ├── BodyTextView.h │ ├── BodyTextView.m │ ├── DetailsHeaderView.h │ ├── DetailsHeaderView.m │ ├── EmptyView.h │ ├── EmptyView.m │ ├── EntryActionsView.h │ ├── EntryActionsView.m │ ├── ForceClearNavigationBar.h │ ├── ForceClearNavigationBar.m │ ├── LoadMoreButton.h │ ├── LoadMoreButton.m │ ├── LoadingIndicatorView.h │ ├── LoadingIndicatorView.m │ ├── OrangeBarView.h │ ├── OrangeBarView.m │ ├── OrangeNavigationBar.h │ ├── OrangeNavigationBar.m │ ├── OrangeTableView.h │ ├── OrangeTableView.m │ ├── OrangeToolbar.h │ ├── OrangeToolbar.m │ ├── PlacardButton.h │ ├── PlacardButton.m │ ├── PlaceholderTextView.h │ ├── PlaceholderTextView.m │ ├── ProfileHeaderView.h │ ├── ProfileHeaderView.m │ ├── ProgressHUD.h │ ├── ProgressHUD.m │ ├── PullToRefreshView.h │ └── PullToRefreshView.m └── main.m ├── Info.plist ├── LICENSE ├── README.md ├── Resources ├── Icons │ ├── Legacy-Icon-Pad.png │ ├── Legacy-Icon-Pad@2x.png │ ├── Legacy-Icon-Settings.png │ ├── Legacy-Icon-Settings@2x.png │ ├── Legacy-Icon-Spotlight.png │ ├── Legacy-Icon-Spotlight@2x.png │ ├── Legacy-Icon.png │ ├── Legacy-Icon@2x.png │ ├── Legacy-iTunesArtwork.png │ ├── Legacy-iTunesArtwork@2x.png │ ├── Modern-Icon-Pad.png │ ├── Modern-Icon-Pad@2x.png │ ├── Modern-Icon-Settings.png │ ├── Modern-Icon-Settings@2x.png │ ├── Modern-Icon-Spotlight.png │ ├── Modern-Icon-Spotlight@2x.png │ ├── Modern-Icon.png │ ├── Modern-Icon@2x.png │ ├── Modern-iTunesArtwork.png │ └── Modern-iTunesArtwork@2x.png ├── Images │ ├── UIPlacardButtonBkgnd.png │ ├── UIPlacardButtonBkgnd@2x.png │ ├── UIPlacardButtonPressedBkgnd.png │ ├── UIPlacardButtonPressedBkgnd@2x.png │ ├── action.png │ ├── action7@2x.png │ ├── action@2x.png │ ├── arrow.png │ ├── arrow@2x.png │ ├── back.png │ ├── back7@2x.png │ ├── back@2x.png │ ├── check.png │ ├── check@2x.png │ ├── clear.png │ ├── disclosure.png │ ├── disclosure@2x.png │ ├── downvote.png │ ├── downvote7@2x.png │ ├── downvote@2x.png │ ├── flag.png │ ├── flag7@2x.png │ ├── flag@2x.png │ ├── forward.png │ ├── forward7@2x.png │ ├── forward@2x.png │ ├── home.png │ ├── home7-selected@2x.png │ ├── home7@2x.png │ ├── home@2x.png │ ├── instapaper.png │ ├── instapaper@2x.png │ ├── instapaper@2x~ipad.png │ ├── instapaper~ipad.png │ ├── new.png │ ├── new7-selected@2x.png │ ├── new7@2x.png │ ├── new@2x.png │ ├── openinsafari.png │ ├── openinsafari7@2x.png │ ├── openinsafari7@2x~ipad.png │ ├── openinsafari7~ipad.png │ ├── openinsafari@2x.png │ ├── openinsafari@2x~ipad.png │ ├── openinsafari~ipad.png │ ├── person.png │ ├── person7-selected@2x.png │ ├── person7@2x.png │ ├── person@2x.png │ ├── readability.png │ ├── readability@2x.png │ ├── refresh.png │ ├── refresh7@2x.png │ ├── refresh@2x.png │ ├── reply.png │ ├── reply7@2x.png │ ├── reply@2x.png │ ├── toolbar-expanded.png │ ├── upvote.png │ ├── upvote7@2x.png │ ├── upvote@2x.png │ ├── x.png │ └── x@2x.png ├── Launch Images │ ├── Modern-Default-568h.png │ ├── Modern-Default-568h@2x.png │ ├── Modern-Default-667h@2x.png │ ├── Modern-Default-736h@2x.png │ ├── Modern-Default-Landscape.png │ ├── Modern-Default-Landscape@2x.png │ ├── Modern-Default-Portrait.png │ ├── Modern-Default-Portrait@2x.png │ ├── Modern-Default.png │ └── Modern-Default@2x.png ├── Settings.bundle │ ├── Root.plist │ └── en.lproj │ │ └── Root.strings └── Source │ ├── icon-6.psd │ ├── icon-old.psd │ ├── icon.pxm │ ├── instapaper7.pdf │ ├── instapaper7.pxm │ ├── openinsafari.pxm │ └── openinsafari7.pxm └── newsyc.xcodeproj ├── project.pbxproj ├── project.xcworkspace └── contents.xcworkspacedata └── xcuserdata ├── Mark.xcuserdatad ├── xcdebugger │ └── Breakpoints.xcbkptlist └── xcschemes │ ├── newsyc.xcscheme │ └── xcschememanagement.plist └── Xuzz.xcuserdatad ├── xcdebugger └── Breakpoints.xcbkptlist └── xcschemes ├── newsyc.xcscheme └── xcschememanagement.plist /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | *.pbxuser 3 | !default.pbxuser 4 | *.mode1v3 5 | !default.mode1v3 6 | *.mode2v3 7 | !default.mode2v3 8 | *.perspectivev3 9 | !default.perspectivev3 10 | *.xcworkspace 11 | !default.xcworkspace 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | 16 | #Mac OS 17 | .DS_Store 18 | 19 | # Other 20 | *.[oa] 21 | .hg. 22 | svn 23 | CVS 24 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "HNKit"] 2 | path = HNKit 3 | url = git://github.com/Xuzz/HNKit.git 4 | -------------------------------------------------------------------------------- /Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/3/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "LoginController.h" 10 | #import "SplitViewController.h" 11 | #import "NavigationController.h" 12 | #import "PingController.h" 13 | 14 | @interface AppDelegate : NSObject { 15 | UIWindow *window; 16 | 17 | SplitViewController *splitController; 18 | 19 | NavigationController *navigationController; 20 | NavigationController *rightNavigationController; 21 | 22 | UIPopoverController *popover; 23 | UIBarButtonItem *popoverItem; 24 | 25 | PingController *pingController; 26 | } 27 | 28 | - (void)pushBranchViewController:(UIViewController *)branchController animated:(BOOL)animated; 29 | - (void)pushLeafViewController:(UIViewController *)leafController animated:(BOOL)animated; 30 | 31 | - (BOOL)leafContainsViewController:(UIViewController *)leafController; 32 | - (void)setLeafViewController:(UIViewController *)leafController animated:(BOOL)animated; 33 | - (void)clearLeafViewControllerAnimated:(BOOL)animated; 34 | 35 | - (NSArray *)branchControllers; 36 | - (void)setBranchControllers:(NSArray *)branchControllers animated:(BOOL)animated; 37 | 38 | - (void)popBranchToViewController:(UIViewController *)branchController animated:(BOOL)animated; 39 | - (void)popLeafToViewController:(UIViewController *)leafController animated:(BOOL)animated; 40 | 41 | @end 42 | 43 | @interface UINavigationController (AppDelegate) 44 | 45 | - (void)pushController:(UIViewController *)controller animated:(BOOL)animated; 46 | - (void)popToController:(UIViewController *)controller animated:(BOOL)animated; 47 | - (void)willShowController:(UIViewController *)controller animated:(BOOL)animated; 48 | - (void)setControllers:(NSArray *)controllers animated:(BOOL)animated; 49 | - (NSArray *)controllers; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Classes/Categories/NSArray+Strings.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Strings.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/14/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface NSArray (Strings) 13 | 14 | - (BOOL)containsString:(NSString *)string; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Categories/NSArray+Strings.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Strings.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/14/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "NSArray+Strings.h" 10 | 11 | 12 | @implementation NSArray (Strings) 13 | 14 | - (BOOL)containsString:(NSString *)string { 15 | for(NSString *element in self) { 16 | if([element isKindOfClass:[NSString class]] && [element isEqualToString:string]) 17 | return true; 18 | } 19 | return false; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Classes/Categories/NSDictionary+Parameters.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+Parameters.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/13/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | @interface NSDictionary (Parameters) 10 | 11 | - (NSString *)queryString; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/Categories/NSDictionary+Parameters.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+Parameters.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/13/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+Parameters.h" 10 | #import 11 | 12 | @implementation NSDictionary (Parameters) 13 | 14 | - (NSString *)queryString { 15 | NSMutableArray *parameters = [NSMutableArray array]; 16 | for (NSString *key in [self allKeys]) { 17 | NSString *escapedk = [key stringByURLEncodingString]; 18 | NSString *v = [[self objectForKey:key] isKindOfClass:[NSString class]] ? [self objectForKey:key] : [[self objectForKey:key] stringValue]; 19 | NSString *escapedv = [v stringByURLEncodingString]; 20 | [parameters addObject:[NSString stringWithFormat:@"%@=%@", escapedk, escapedv]]; 21 | } 22 | 23 | NSString *query = [parameters count] > 0 ? @"?" : @""; 24 | query = [query stringByAppendingString:[parameters componentsJoinedByString:@"&"]]; 25 | return query; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Classes/Categories/NSString+Entities.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+HTML.m 3 | // MWFeedParser 4 | // 5 | // Copyright (c) 2010 Michael Waterfall 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // 1. The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // 2. This Software cannot be used to archive or collect data such as (but not 18 | // limited to) that of events, news, experiences and activities, for the 19 | // purpose of any concept relating to diary/journal keeping. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | // 29 | 30 | @interface NSString (Entities) 31 | 32 | - (NSString *)stringByDecodingHTMLEntities; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/Categories/NSString+Entities.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+HTML.m 3 | // MWFeedParser 4 | // 5 | // Copyright (c) 2010 Michael Waterfall 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // 1. The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // 2. This Software cannot be used to archive or collect data such as (but not 18 | // limited to) that of events, news, experiences and activities, for the 19 | // purpose of any concept relating to diary/journal keeping. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | // 29 | 30 | #import "NSString+Entities.h" 31 | 32 | 33 | @implementation NSString (Entities) 34 | 35 | - (NSString *)stringByDecodingHTMLEntities { 36 | NSUInteger myLength = [self length]; 37 | NSUInteger ampIndex = [self rangeOfString:@"&" options:NSLiteralSearch].location; 38 | 39 | if (ampIndex == NSNotFound) return self; 40 | 41 | NSMutableString *result = [NSMutableString stringWithCapacity:(myLength * 1.25f)]; 42 | 43 | // First iteration doesn't need to scan to & since we did that already, but for code simplicity's sake we'll do it again with the scanner. 44 | NSScanner *scanner = [NSScanner scannerWithString:self]; 45 | [scanner setCharactersToBeSkipped:nil]; 46 | 47 | NSCharacterSet *boundaryCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@" \t\n\r;"]; 48 | 49 | do { 50 | NSString *nonEntityString; 51 | if ([scanner scanUpToString:@"&" intoString:&nonEntityString]) { 52 | [result appendString:nonEntityString]; 53 | } 54 | 55 | if ([scanner isAtEnd]) goto finish; 56 | 57 | if ([scanner scanString:@"&" intoString:NULL]) { 58 | [result appendString:@"&"]; 59 | } else if ([scanner scanString:@"'" intoString:NULL]) { 60 | [result appendString:@"'"]; 61 | } else if ([scanner scanString:@""" intoString:NULL]) { 62 | [result appendString:@"\""]; 63 | } else if ([scanner scanString:@"<" intoString:NULL]) { 64 | [result appendString:@"<"]; 65 | } else if ([scanner scanString:@">" intoString:NULL]) { 66 | [result appendString:@">"]; 67 | } else if ([scanner scanString:@"&#" intoString:NULL]) { 68 | BOOL gotNumber; 69 | unsigned charCode; 70 | NSString *xForHex = @""; 71 | 72 | // Is it hex or decimal? 73 | if ([scanner scanString:@"x" intoString:&xForHex]) { 74 | gotNumber = [scanner scanHexInt:&charCode]; 75 | } 76 | else { 77 | gotNumber = [scanner scanInt:(int*)&charCode]; 78 | } 79 | 80 | if (gotNumber) { 81 | [result appendFormat:@"%u", charCode]; 82 | [scanner scanString:@";" intoString:NULL]; 83 | } else { 84 | NSString *unknownEntity = nil; 85 | [scanner scanUpToCharactersFromSet:boundaryCharacterSet intoString:&unknownEntity]; 86 | [result appendFormat:@"&#%@%@", xForHex, unknownEntity]; 87 | } 88 | } else { 89 | NSString *amp; 90 | 91 | [scanner scanString:@"&" intoString:&]; //an isolated & symbol 92 | [result appendString:amp]; 93 | } 94 | } while (![scanner isAtEnd]); 95 | 96 | finish: 97 | return result; 98 | } 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /Classes/Categories/NSString+Tags.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Tags.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/13/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (Tags) 12 | 13 | - (NSString *)stringByRemovingHTMLTags; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/Categories/NSString+Tags.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Tags.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/13/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "NSString+Tags.h" 10 | 11 | @implementation NSString (Tags) 12 | 13 | - (NSString *)stringByRemovingHTMLTags { 14 | NSString *html = self; 15 | NSScanner *scanner = [NSScanner scannerWithString:html]; 16 | NSString *text = nil; 17 | 18 | while ([scanner isAtEnd] == NO) { 19 | [scanner scanUpToString:@"<" intoString:NULL]; 20 | [scanner scanUpToString:@">" intoString:&text]; 21 | 22 | html = [html stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@>", text] withString:@" "]; 23 | } 24 | 25 | return html; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Classes/Categories/UIActionSheet+Context.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIActionSheet+Context.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/31/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | // The idea of this is that there is a private "context" property on 10 | // UIActionSheet (as well as UIAlertView), and it's actually quite 11 | // essential: while a "tag" might work as well, it's not anywhere near 12 | // as clean (to me). 13 | // 14 | // Since we can't name it the same as Apple's "context" property, I've 15 | // called it "sheetContext" (for lack of a better name), and simulated 16 | // the ivar using objc_setAssociatedObject(). 17 | 18 | @interface UIActionSheet (Context) 19 | 20 | - (void)setSheetContext:(NSString *)context; 21 | - (NSString *)sheetContext; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/Categories/UIActionSheet+Context.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIActionSheet+Context.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/31/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "UIActionSheet+Context.h" 12 | 13 | @implementation UIActionSheet (Context) 14 | static NSString *UIActionSheetNameKey = @"UIActionSheetSheetContextKey"; 15 | 16 | - (void)setSheetContext:(NSString *)name { 17 | objc_setAssociatedObject(self, &UIActionSheetNameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC); 18 | } 19 | 20 | - (NSString *)sheetContext { 21 | return objc_getAssociatedObject(self, &UIActionSheetNameKey); 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/Categories/UIApplication+ActivityIndicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIApplication+ActivityIndicator.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 5/28/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | @interface UIApplication (ActivityIndicator) 10 | 11 | - (void)retainNetworkActivityIndicator; 12 | - (void)releaseNetworkActivityIndicator; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Classes/Categories/UIApplication+ActivityIndicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIApplication+ActivityIndicator.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 5/28/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "UIApplication+ActivityIndicator.h" 10 | 11 | @implementation UIApplication (ActivityIndicator) 12 | 13 | - (void)_updateNetworkActivityIndicator:(BOOL)visible { 14 | static NSInteger count = 0; 15 | 16 | if (visible) count += 1; 17 | else count -= 1; 18 | 19 | [self setNetworkActivityIndicatorVisible:(count > 0)]; 20 | } 21 | 22 | 23 | - (void)retainNetworkActivityIndicator { 24 | [self _updateNetworkActivityIndicator:YES]; 25 | } 26 | 27 | - (void)releaseNetworkActivityIndicator { 28 | [self _updateNetworkActivityIndicator:NO]; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Classes/Categories/UIColor+Orange.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // UIColor_Orange.h 4 | // newsyc 5 | // 6 | // Created by Grant Paul on 1/10/13. 7 | // 8 | // 9 | 10 | #import 11 | 12 | @interface UIColor (Orange) 13 | 14 | + (UIColor *)mainOrangeColor; 15 | + (UIColor *)lightOrangeColor; 16 | + (UIColor *)paleOrangeColor; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Categories/UIColor+Orange.m: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // UIColor+Orange.m 4 | // newsyc 5 | // 6 | // Created by Grant Paul on 1/10/13. 7 | // 8 | // 9 | 10 | #import "UIColor+Orange.h" 11 | 12 | @implementation UIColor (Orange) 13 | 14 | + (UIColor *)mainOrangeColor { 15 | return [UIColor colorWithRed:1.0f green:0.4f blue:0.0f alpha:1.0f]; 16 | } 17 | 18 | + (UIColor *)lightOrangeColor { 19 | return [UIColor colorWithRed:1.0f green:0.6f blue:0.2f alpha:1.0f]; 20 | } 21 | 22 | + (UIColor *)paleOrangeColor { 23 | return [UIColor colorWithRed:(234.0f / 255.0f) green:(232.0f / 255.0f) blue:(224.0f / 255.0f) alpha:1.0f]; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/Categories/UIImage+Colorize.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Colorize.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/9/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | @interface UIImage (Colorize) 10 | 11 | - (UIImage *)imageTintedToColor:(UIColor *)color; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/Categories/UIImage+Colorize.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Colorize.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/9/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "UIImage+Colorize.h" 10 | 11 | @implementation UIImage (Colorize) 12 | 13 | - (UIImage *)imageTintedToColor:(UIColor *)color { 14 | UIGraphicsBeginImageContext([self size]); 15 | CGContextRef context = UIGraphicsGetCurrentContext(); 16 | 17 | // flip to UIKit coordinates 18 | CGContextTranslateCTM(context, 0, [self size].height); 19 | CGContextScaleCTM(context, 1.0, -1.0); 20 | 21 | CGContextSetBlendMode(context, kCGBlendModeColorBurn); 22 | CGRect rect = CGRectMake(0, 0, [self size].width, [self size].height); 23 | CGContextDrawImage(context, rect, [self CGImage]); 24 | 25 | [color setFill]; 26 | CGContextClipToMask(context, rect, [self CGImage]); 27 | CGContextAddRect(context, rect); 28 | CGContextDrawPath(context,kCGPathFill); 29 | 30 | UIImage *colored = UIGraphicsGetImageFromCurrentImageContext(); 31 | UIGraphicsEndImageContext(); 32 | 33 | return colored; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Classes/Categories/UINavigationItem+MultipleItems.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIBarButtonItem+MultipleItems.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/23/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum { 12 | UINavigationItemPositionLeft, 13 | UINavigationItemPositionRight 14 | } UINavigationItemPosition; 15 | 16 | @interface UINavigationItem (MultipleItems) 17 | 18 | - (void)addLeftBarButtonItem:(UIBarButtonItem *)item atPosition:(UINavigationItemPosition)position; 19 | - (void)addRightBarButtonItem:(UIBarButtonItem *)item atPosition:(UINavigationItemPosition)position; 20 | 21 | - (void)removeLeftBarButtonItem:(UIBarButtonItem *)item; 22 | - (void)removeRightBarButtonItem:(UIBarButtonItem *)item; 23 | - (void)removeBarButtonItem:(UIBarButtonItem *)item; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Classes/Categories/UINavigationItem+MultipleItems.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIBarButtonItem+MultipleItems.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/23/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "UINavigationItem+MultipleItems.h" 10 | 11 | @implementation UINavigationItem (MultipleItems) 12 | 13 | - (void)addLeftBarButtonItem:(UIBarButtonItem *)item atPosition:(UINavigationItemPosition)position { 14 | [self removeBarButtonItem:item]; 15 | 16 | NSArray *current = [self leftBarButtonItems]; 17 | NSArray *added = nil; 18 | if (current == nil) current = [NSArray array]; 19 | 20 | if (position == UINavigationItemPositionLeft) { 21 | added = [[NSArray arrayWithObject:item] arrayByAddingObjectsFromArray:current]; 22 | } else if (position == UINavigationItemPositionRight) { 23 | added = [current arrayByAddingObject:item]; 24 | } 25 | 26 | [self setLeftBarButtonItems:added]; 27 | 28 | [self setLeftItemsSupplementBackButton:YES]; 29 | } 30 | 31 | - (void)addRightBarButtonItem:(UIBarButtonItem *)item atPosition:(UINavigationItemPosition)position { 32 | [self removeBarButtonItem:item]; 33 | 34 | NSArray *current = [self rightBarButtonItems]; 35 | NSArray *added = nil; 36 | if (current == nil) current = [NSArray array]; 37 | 38 | if (position == UINavigationItemPositionLeft) { 39 | added = [current arrayByAddingObject:item]; 40 | } else if (position == UINavigationItemPositionRight) { 41 | added = [[NSArray arrayWithObject:item] arrayByAddingObjectsFromArray:current]; 42 | } 43 | 44 | [self setRightBarButtonItems:added]; 45 | } 46 | 47 | - (void)removeLeftBarButtonItem:(UIBarButtonItem *)item { 48 | NSMutableArray *current = [[self leftBarButtonItems] mutableCopy]; 49 | [current removeObject:item]; 50 | [current autorelease]; 51 | 52 | [self setLeftBarButtonItems:current]; 53 | } 54 | 55 | - (void)removeRightBarButtonItem:(UIBarButtonItem *)item { 56 | NSMutableArray *current = [[self rightBarButtonItems] mutableCopy]; 57 | [current removeObject:item]; 58 | [current autorelease]; 59 | 60 | [self setRightBarButtonItems:current]; 61 | } 62 | 63 | - (void)removeBarButtonItem:(UIBarButtonItem *)item { 64 | [self removeLeftBarButtonItem:item]; 65 | [self removeRightBarButtonItem:item]; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /Classes/Cells/CommentTableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommentTableCell.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/5/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "TableViewCell.h" 10 | #import "EntryActionsView.h" 11 | #import "BodyTextView.h" 12 | 13 | @protocol CommentTableCellDelegate; 14 | 15 | @class HNEntry; 16 | @interface CommentTableCell : TableViewCell { 17 | HNEntry *comment; 18 | NSInteger indentationLevel; 19 | 20 | BOOL userHighlighted; 21 | BodyTextView *bodyTextView; 22 | 23 | __weak id delegate; 24 | 25 | BOOL expanded; 26 | EntryActionsView *toolbarView; 27 | 28 | UITapGestureRecognizer *tapRecognizer; 29 | UITapGestureRecognizer *doubleTapRecognizer; 30 | } 31 | 32 | @property (nonatomic, assign) id delegate; 33 | @property (nonatomic, retain) HNEntry *comment; 34 | @property (nonatomic, assign) NSInteger indentationLevel; 35 | @property (nonatomic, assign) BOOL expanded; 36 | 37 | + (CGFloat)heightForEntry:(HNEntry *)entry withWidth:(CGFloat)width expanded:(BOOL)expanded indentationLevel:(NSInteger)indentationLevel; 38 | 39 | - (id)initWithReuseIdentifier:(NSString *)identifier; 40 | 41 | @end 42 | 43 | @protocol CommentTableCellDelegate 44 | @optional 45 | 46 | - (void)commentTableCellTapped:(CommentTableCell *)cell; 47 | - (void)commentTableCellTappedUser:(CommentTableCell *)cell; 48 | - (void)commentTableCellDoubleTapped:(CommentTableCell *)cell; 49 | - (void)commentTableCell:(CommentTableCell *)cell selectedURL:(NSURL *)url; 50 | 51 | @end 52 | 53 | -------------------------------------------------------------------------------- /Classes/Cells/LoadMoreCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoadMoreCell.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/25/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "TableViewCell.h" 10 | #import "LoadMoreButton.h" 11 | 12 | @interface LoadMoreCell : TableViewCell { 13 | LoadMoreButton *button; 14 | } 15 | 16 | @property (nonatomic, readonly, retain) LoadMoreButton *button; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Cells/LoadMoreCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoadMoreCell.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/25/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "LoadMoreCell.h" 10 | 11 | @implementation LoadMoreCell 12 | @synthesize button; 13 | 14 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 15 | if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { 16 | button = [[LoadMoreButton alloc] initWithFrame:[self bounds]]; 17 | [button setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 18 | [self addSubview:button]; 19 | } 20 | 21 | return self; 22 | } 23 | 24 | - (void)layoutSubviews { 25 | [super layoutSubviews]; 26 | 27 | if ([self respondsToSelector:@selector(setSeparatorInset:)]) { 28 | // Hide the cell separator by giving it zero width. 29 | [self setSeparatorInset:UIEdgeInsetsMake(0, self.bounds.size.width, 0, 0)]; 30 | } 31 | } 32 | 33 | - (void)dealloc { 34 | [button release]; 35 | 36 | [super dealloc]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Classes/Cells/SubmissionTableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SubmissionTableCell.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/5/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "TableViewCell.h" 10 | 11 | @class HNEntry; 12 | @interface SubmissionTableCell : TableViewCell { 13 | HNEntry *submission; 14 | } 15 | 16 | @property (nonatomic, retain) HNEntry *submission; 17 | 18 | + (CGFloat)heightForEntry:(HNEntry *)entry withWidth:(CGFloat)width; 19 | - (id)initWithReuseIdentifier:(NSString *)identifier; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Classes/Cells/TableViewCell.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2008 Loren Brichter 2 | // 3 | // Permission is hereby granted, free of charge, to any person 4 | // obtaining a copy of this software and associated documentation 5 | // files (the "Software"), to deal in the Software without 6 | // restriction, including without limitation the rights to use, 7 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following 10 | // conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | // OTHER DEALINGS IN THE SOFTWARE. 23 | // 24 | // ABTableViewCell.h 25 | // 26 | // Created by Loren Brichter 27 | // Copyright 2008 Loren Brichter. All rights reserved. 28 | // 29 | 30 | #import 31 | 32 | @interface TableViewCell : UITableViewCell { 33 | UIView *contentView; 34 | BOOL showsDividing; 35 | } 36 | 37 | - (void)drawContentView:(CGRect)rect; // subclasses should implement 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Classes/Cells/TableViewCell.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2008 Loren Brichter 2 | // 3 | // Permission is hereby granted, free of charge, to any person 4 | // obtaining a copy of this software and associated documentation 5 | // files (the "Software"), to deal in the Software without 6 | // restriction, including without limitation the rights to use, 7 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following 10 | // conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | // OTHER DEALINGS IN THE SOFTWARE. 23 | // 24 | // ABTableViewCell.m 25 | // 26 | // Created by Loren Brichter 27 | // Copyright 2008 Loren Brichter. All rights reserved. 28 | // 29 | 30 | #import "TableViewCell.h" 31 | 32 | @interface TableViewCellView : UIView { 33 | __weak TableViewCell *cell; 34 | } 35 | @end 36 | 37 | @implementation TableViewCellView 38 | 39 | - (id)initWithCell:(TableViewCell *)cell_ { 40 | if ((self = [super initWithFrame:CGRectZero])) { 41 | cell = cell_; 42 | } 43 | 44 | return self; 45 | } 46 | 47 | - (void)drawRect:(CGRect)rect { 48 | [super drawRect:rect]; 49 | 50 | [cell drawContentView:rect]; 51 | } 52 | 53 | @end 54 | 55 | @implementation TableViewCell 56 | 57 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 58 | if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { 59 | contentView = [[TableViewCellView alloc] initWithCell:self]; 60 | [contentView setOpaque:YES]; 61 | [self.contentView addSubview:contentView]; 62 | [contentView release]; 63 | } 64 | 65 | return self; 66 | } 67 | 68 | - (void)layoutSubviews { 69 | [super layoutSubviews]; 70 | 71 | [contentView setFrame:[[self contentView] bounds]]; 72 | } 73 | 74 | - (void)setNeedsDisplay { 75 | [super setNeedsDisplay]; 76 | [contentView setNeedsDisplay]; 77 | } 78 | 79 | - (void)drawContentView:(CGRect)rect { 80 | // subclasses should implement this 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /Classes/Controllers/BrowserController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BrowserController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/7/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "InstapaperRequest.h" 10 | #import "InstapaperSession.h" 11 | #import "InstapaperLoginController.h" 12 | #import "ProgressHUD.h" 13 | #import "ActivityIndicatorItem.h" 14 | #import "BarButtonItem.h" 15 | #import "OrangeToolbar.h" 16 | 17 | #import 18 | 19 | #define kReadabilityBookmarkletCode @"(function(){window.baseUrl='https://www.readability.com';window.readabilityToken='';var s=document.createElement('script');s.setAttribute('type','text/javascript');s.setAttribute('charset','UTF-8');s.setAttribute('src',baseUrl+'/bookmarklet/read.js');document.documentElement.appendChild(s);})()" 20 | 21 | @interface BrowserController : UIViewController { 22 | UIWebView *webview; 23 | 24 | NSURL *rootURL; 25 | NSURL *currentURL; 26 | NSURL *externalURL; 27 | 28 | OrangeToolbar *toolbar; 29 | BarButtonItem *toolbarItem; 30 | 31 | BarButtonItem *backItem; 32 | BarButtonItem *forwardItem; 33 | ActivityIndicatorItem *loadingItem; 34 | BarButtonItem *refreshItem; 35 | BarButtonItem *shareItem; 36 | BarButtonItem *spacerItem; 37 | BarButtonItem *readabilityItem; 38 | 39 | NSInteger networkRetainCount; 40 | } 41 | 42 | @property (nonatomic, copy) NSURL *currentURL; 43 | 44 | - (id)initWithURL:(NSURL *)url; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Classes/Controllers/CommentListController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommentListController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/5/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "EntryListController.h" 10 | #import "ComposeController.h" 11 | #import "EntryActionsView.h" 12 | #import "DetailsHeaderView.h" 13 | #import "LoginController.h" 14 | #import "CommentTableCell.h" 15 | #import "BarButtonItem.h" 16 | 17 | @interface CommentListController : EntryListController { 18 | CGFloat suggestedHeaderHeight; 19 | DetailsHeaderView *detailsHeaderView; 20 | 21 | EntryActionsView *entryActionsView; 22 | BarButtonItem *entryActionsViewItem; 23 | 24 | void (^savedAction)(); 25 | void (^savedCompletion)(int); 26 | BOOL shouldCompleteOnAppear; 27 | 28 | HNEntry *expandedEntry; 29 | CommentTableCell *expandedCell; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Classes/Controllers/ComposeController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ComposeController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/30/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "BarButtonItem.h" 12 | #import "ActivityIndicatorItem.h" 13 | 14 | @protocol ComposeControllerDelegate; 15 | @class PlaceholderTextView; 16 | 17 | @interface ComposeController : UIViewController { 18 | HNSession *session; 19 | 20 | UITableView *tableView; 21 | NSArray *entryCells; 22 | PlaceholderTextView *textView; 23 | BarButtonItem *cancelItem; 24 | BarButtonItem *completeItem; 25 | ActivityIndicatorItem *loadingItem; 26 | BOOL keyboardVisible; 27 | __weak id delegate; 28 | } 29 | 30 | @property (nonatomic, assign) id delegate; 31 | 32 | - (id)initWithSession:(HNSession *)session_; 33 | 34 | - (UITableViewCell *)generateTextFieldCell; 35 | - (UITextField *)generateTextFieldForCell:(UITableViewCell *)cell; 36 | - (UIResponder *)initialFirstResponder; 37 | 38 | - (void)sendComplete; 39 | - (void)sendFailed; 40 | - (void)performSubmission; 41 | - (BOOL)ableToSubmit; 42 | - (void)textDidChange:(NSNotification *)notification; 43 | 44 | @end 45 | 46 | @protocol ComposeControllerDelegate 47 | @optional 48 | 49 | - (void)composeControllerDidSubmit:(ComposeController *)controller; 50 | - (void)composeControllerDidCancel:(ComposeController *)controller; 51 | 52 | @end 53 | 54 | -------------------------------------------------------------------------------- /Classes/Controllers/EmptyController.h: -------------------------------------------------------------------------------- 1 | // 2 | // EmptyController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/22/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | @class EmptyView; 10 | @class OrangeTableView; 11 | 12 | @interface EmptyController : UIViewController { 13 | OrangeTableView *tableView; 14 | EmptyView *emptyView; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Controllers/EmptyController.m: -------------------------------------------------------------------------------- 1 | // 2 | // EmptyController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/22/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "EmptyController.h" 10 | #import "EmptyView.h" 11 | #import "OrangeTableView.h" 12 | 13 | @implementation EmptyController 14 | 15 | - (void)dealloc { 16 | [tableView release]; 17 | [emptyView release]; 18 | 19 | [super dealloc]; 20 | } 21 | 22 | - (void)viewDidUnload { 23 | [super viewDidUnload]; 24 | 25 | [tableView release]; 26 | tableView = nil; 27 | [emptyView release]; 28 | emptyView = nil; 29 | } 30 | 31 | - (void)loadView { 32 | [super loadView]; 33 | 34 | tableView = [[OrangeTableView alloc] initWithFrame:[[self view] bounds]]; 35 | [tableView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 36 | [[self view] addSubview:tableView]; 37 | 38 | emptyView = [[EmptyView alloc] initWithFrame:[[self view] bounds]]; 39 | [emptyView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 40 | [emptyView setText:@"No Submission Selected"]; 41 | [emptyView setBackgroundColor:[UIColor clearColor]]; 42 | [[self view] addSubview:emptyView]; 43 | } 44 | 45 | - (void)viewWillAppear:(BOOL)animated { 46 | [super viewWillAppear:animated]; 47 | 48 | [tableView setOrange:![[NSUserDefaults standardUserDefaults] boolForKey:@"disable-orange"]]; 49 | } 50 | 51 | AUTOROTATION_FOR_PAD_ONLY 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /Classes/Controllers/EntryListController.h: -------------------------------------------------------------------------------- 1 | // 2 | // EntryListController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/5/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "LoadingController.h" 10 | #import "PullToRefreshView.h" 11 | #import "LoadMoreCell.h" 12 | 13 | @class EmptyView; 14 | 15 | @interface EntryListController : LoadingController { 16 | UITableViewController *tableViewController; 17 | UITableView *tableView; 18 | EmptyView *emptyView; 19 | 20 | LoadMoreCell *moreCell; 21 | PullToRefreshView *pullToRefreshView; 22 | UIRefreshControl *refreshControl; 23 | 24 | NSArray *entries; 25 | } 26 | 27 | - (HNEntry *)entryAtIndexPath:(NSIndexPath *)indexPath; 28 | - (NSIndexPath *)indexPathOfEntry:(HNEntry *)entry; 29 | 30 | + (Class)cellClass; 31 | - (CGFloat)cellHeightForEntry:(HNEntry *)entry; 32 | - (void)configureCell:(UITableViewCell *)cell forEntry:(HNEntry *)entry; 33 | - (void)cellSelected:(UITableViewCell *)cell forEntry:(HNEntry *)entry; 34 | - (void)deselectWithAnimation:(BOOL)animated; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Classes/Controllers/EntryReplyComposeController.h: -------------------------------------------------------------------------------- 1 | // 2 | // EntryReplyComposeController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/31/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "ComposeController.h" 10 | 11 | @interface EntryReplyComposeController : ComposeController { 12 | HNEntry *entry; 13 | UILabel *replyLabel; 14 | } 15 | 16 | @property (nonatomic, readonly, retain) HNEntry *entry; 17 | 18 | - (id)initWithEntry:(HNEntry *)entry_; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Classes/Controllers/HackerNewsLoginController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HackerNewsLoginController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/6/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LoginController.h" 11 | 12 | @interface HackerNewsLoginController : LoginController { 13 | HNSession *session; 14 | } 15 | 16 | @property (nonatomic, retain, readonly) HNSession *session; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Controllers/HackerNewsLoginController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HackerNewsLoginController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/6/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "HackerNewsLoginController.h" 10 | 11 | #import "UIColor+Orange.h" 12 | 13 | @implementation HackerNewsLoginController 14 | @synthesize session; 15 | 16 | - (void)viewDidLoad { 17 | [super viewDidLoad]; 18 | 19 | 20 | [topLabel setText:@"Startup News"]; 21 | [topLabel setTextColor:[UIColor whiteColor]]; 22 | [topLabel setShadowColor:[UIColor blackColor]]; 23 | [bottomLabel setText:@"Your info is only shared with Startup News.\n 免费注册,请访问 news.dbanotes.net"]; 24 | [bottomLabel setTextColor:[UIColor whiteColor]]; 25 | 26 | if ([self respondsToSelector:@selector(topLayoutGuide)]) { 27 | [topLabel setTextColor:[UIColor blackColor]]; 28 | [bottomLabel setTextColor:[UIColor darkGrayColor]]; 29 | 30 | [topLabel setFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:34.0]]; 31 | } else { 32 | [topLabel setTextColor:[UIColor whiteColor]]; 33 | [topLabel setShadowColor:[UIColor blackColor]]; 34 | [bottomLabel setTextColor:[UIColor whiteColor]]; 35 | 36 | [topLabel setFont:[UIFont boldSystemFontOfSize:30.0f]]; 37 | [topLabel setShadowOffset:CGSizeMake(0, 1.0f)]; 38 | } 39 | 40 | [bottomLabel setFont:[UIFont systemFontOfSize:14.0f]]; 41 | } 42 | 43 | - (BOOL)requiresPassword { 44 | return YES; 45 | } 46 | 47 | - (void)sessionAuthenticatorDidRecieveFailure:(HNSessionAuthenticator *)authenticator { 48 | [authenticator autorelease]; 49 | [self finish]; 50 | [self fail]; 51 | } 52 | 53 | - (void)sessionAuthenticator:(HNSessionAuthenticator *)authenticator didRecieveToken:(HNSessionToken)token { 54 | session = [[HNSession alloc] initWithUsername:[usernameField text] password:[passwordField text] token:token]; 55 | [[HNSessionController sessionController] addSession:session]; 56 | [authenticator autorelease]; 57 | 58 | [self finish]; 59 | [self succeed]; 60 | } 61 | 62 | - (void)dealloc { 63 | [session release]; 64 | 65 | [super dealloc]; 66 | } 67 | 68 | - (NSArray *)gradientColors { 69 | NSMutableArray *array = [NSMutableArray array]; 70 | [array addObject:(id) [[UIColor lightOrangeColor] CGColor]]; 71 | [array addObject:(id) [[UIColor mainOrangeColor] CGColor]]; 72 | return array; 73 | } 74 | 75 | - (void)authenticate { 76 | [super authenticate]; 77 | 78 | NSString *username = [usernameField text]; 79 | 80 | for (HNSession *session_ in [[HNSessionController sessionController] sessions]) { 81 | if ([[session_ identifier] isEqual:username]) { 82 | [self finish]; 83 | [self fail]; 84 | return; 85 | } 86 | } 87 | 88 | HNSessionAuthenticator *authenticator = [[HNSessionAuthenticator alloc] initWithUsername:username password:[passwordField text]]; 89 | [authenticator setDelegate:self]; 90 | [authenticator beginAuthenticationRequest]; 91 | } 92 | 93 | AUTOROTATION_FOR_PAD_ONLY 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /Classes/Controllers/InstapaperActivity.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReadLaterActivity.h 3 | // newsyc 4 | // 5 | // Created by Mark Nemec on 22/10/12. 6 | // 7 | // 8 | 9 | @class InstapaperSubmission; 10 | 11 | @interface InstapaperActivity : UIActivity { 12 | InstapaperSubmission *submission; 13 | } 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/Controllers/InstapaperActivity.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReadLaterActivity.m 3 | // newsyc 4 | // 5 | // Created by Mark Nemec on 22/10/12. 6 | // 7 | // 8 | 9 | #import "InstapaperActivity.h" 10 | #import "InstapaperSubmission.h" 11 | 12 | @implementation InstapaperActivity 13 | 14 | - (void)dealloc { 15 | [submission release]; 16 | 17 | [super dealloc]; 18 | } 19 | 20 | - (NSString *)activityType { 21 | return @"com.instapaper.instapaper.read-later"; 22 | } 23 | 24 | - (NSString *)activityTitle { 25 | return @"Read Later"; 26 | } 27 | 28 | - (UIImage *)activityImage { 29 | return [UIImage imageNamed:@"instapaper.png"]; 30 | } 31 | 32 | - (BOOL)canPerformWithActivityItems:(NSArray *)activityItems { 33 | return YES; 34 | } 35 | 36 | - (void)prepareWithActivityItems:(NSArray *)activityItems { 37 | [submission release]; 38 | 39 | submission = [[InstapaperSubmission alloc] initWithURL:[activityItems objectAtIndex:0]]; 40 | 41 | [submission setLoginCompletion:^(BOOL loggedIn) { 42 | [self activityDidFinish:YES]; 43 | }]; 44 | } 45 | 46 | - (UIViewController *)activityViewController { 47 | return [submission submitFromController:nil]; 48 | } 49 | 50 | - (void)performActivity { 51 | [self activityDidFinish:YES]; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Classes/Controllers/InstapaperLoginController.h: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperLoginController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/6/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "LoginController.h" 10 | #import "InstapaperAuthenticator.h" 11 | 12 | @interface InstapaperLoginController : LoginController { 13 | NSURL *pendingURL; 14 | } 15 | 16 | @property (nonatomic, copy) NSURL *pendingURL; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Controllers/InstapaperLoginController.m: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperLoginController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/6/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "InstapaperLoginController.h" 10 | #import "InstapaperSession.h" 11 | 12 | @implementation InstapaperLoginController 13 | @synthesize pendingURL; 14 | 15 | - (void)dealloc { 16 | [pendingURL release]; 17 | 18 | [super dealloc]; 19 | } 20 | 21 | - (BOOL)requiresPassword { 22 | return NO; 23 | } 24 | 25 | - (void)viewDidLoad{ 26 | [super viewDidLoad]; 27 | 28 | [topLabel setText:@"Instapaper"]; 29 | [bottomLabel setText:@"Enter your password if you have one."]; 30 | 31 | 32 | [[usernameCell textLabel] setText:@"Email"]; 33 | 34 | if ([self respondsToSelector:@selector(topLayoutGuide)]) { 35 | [topLabel setTextColor:[UIColor blackColor]]; 36 | [bottomLabel setTextColor:[UIColor darkGrayColor]]; 37 | } else { 38 | [topLabel setTextColor:[UIColor blackColor]]; 39 | [bottomLabel setTextColor:[UIColor blackColor]]; 40 | } 41 | 42 | [topLabel setFont:[UIFont fontWithName:@"HoeflerText-Regular" size:34.0f]]; 43 | [bottomLabel setFont:[UIFont systemFontOfSize:14.0f]]; 44 | } 45 | 46 | - (NSArray *)gradientColors { 47 | NSMutableArray *array = [NSMutableArray array]; 48 | [array addObject:(id) [[UIColor colorWithRed:0.9f green:0.9f blue:0.9f alpha:1.0f] CGColor]]; 49 | [array addObject:(id) [[UIColor colorWithRed:0.7f green:0.7f blue:0.7f alpha:1.0f] CGColor]]; 50 | return array; 51 | } 52 | 53 | - (void)instapaperAuthenticator:(InstapaperAuthenticator *)auth didFailWithError:(NSError *)error { 54 | [bottomLabel setText:[NSString stringWithFormat:@"Error: %@", [error localizedDescription]]]; 55 | [auth release]; 56 | 57 | [self finish]; 58 | [self fail]; 59 | } 60 | 61 | - (void)instapaperAuthenticatorDidSucceed:(InstapaperAuthenticator *)auth { 62 | InstapaperSession *session = [[InstapaperSession alloc] init]; 63 | [session setUsername:[usernameField text]]; 64 | [session setPassword:[passwordField text]]; 65 | [InstapaperSession setCurrentSession:session]; 66 | [auth release]; 67 | [session release]; 68 | 69 | [self finish]; 70 | [self succeed]; 71 | } 72 | 73 | - (void)authenticate { 74 | [super authenticate]; 75 | InstapaperAuthenticator *auth = [[InstapaperAuthenticator alloc] initWithUsername:[usernameField text] password:[passwordField text]]; 76 | [auth setDelegate:self]; 77 | [auth beginAuthentication]; 78 | } 79 | 80 | AUTOROTATION_FOR_PAD_ONLY 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /Classes/Controllers/InstapaperSubmission.h: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperSubmission.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 10/30/12. 6 | // 7 | // 8 | 9 | @class LoadingController; 10 | 11 | @interface InstapaperSubmission : NSObject { 12 | NSURL *url; 13 | BOOL presented; 14 | void (^loginCompletion)(BOOL); 15 | } 16 | 17 | @property (nonatomic, copy) void (^loginCompletion)(BOOL); 18 | 19 | - (id)initWithURL:(NSURL *)url; 20 | - (UIViewController *)submitFromController:(UIViewController *)controller; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Classes/Controllers/InstapaperSubmission.m: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperSubmission.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 10/30/12. 6 | // 7 | // 8 | 9 | #import "InstapaperSubmission.h" 10 | 11 | #import "InstapaperSession.h" 12 | #import "InstapaperRequest.h" 13 | 14 | #import "NavigationController.h" 15 | #import "InstapaperLoginController.h" 16 | 17 | #import "ProgressHUD.h" 18 | 19 | @interface InstapaperSubmission () 20 | @end 21 | 22 | @implementation InstapaperSubmission 23 | @synthesize loginCompletion; 24 | 25 | - (id)initWithURL:(NSURL *)url_ { 26 | if ((self = [super init])) { 27 | url = [url_ copy]; 28 | } 29 | 30 | return self; 31 | } 32 | 33 | - (void)dealloc { 34 | [url release]; 35 | [loginCompletion release]; 36 | 37 | [super dealloc]; 38 | } 39 | 40 | - (void)submitInstapaperRequest { 41 | InstapaperRequest *request = [[InstapaperRequest alloc] initWithSession:[InstapaperSession currentSession]]; 42 | 43 | ProgressHUD *hud = [[ProgressHUD alloc] init]; 44 | [hud setText:@"Saving"]; 45 | [hud showInWindow:[[UIApplication sharedApplication] keyWindow]]; 46 | [hud release]; 47 | 48 | // Yes, really: this allows callers to fire-and-forget, and then we disappear on completion. 49 | [self retain]; 50 | 51 | __block id succeededObserver = nil; 52 | [[NSNotificationCenter defaultCenter] addObserverForName:kInstapaperRequestSucceededNotification object:request queue:nil usingBlock:^(NSNotification *notification) { 53 | [hud setText:@"Saved!"]; 54 | [hud setState:kProgressHUDStateCompleted]; 55 | [hud dismissAfterDelay:0.8f animated:YES]; 56 | 57 | [[NSNotificationCenter defaultCenter] removeObserver:succeededObserver]; 58 | [self release]; 59 | }]; 60 | 61 | __block id failedObserver = nil; 62 | failedObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kInstapaperRequestFailedNotification object:request queue:nil usingBlock:^(NSNotification *notification) { 63 | [hud setText:@"Error Saving"]; 64 | [hud setState:kProgressHUDStateError]; 65 | [hud dismissAfterDelay:0.8f animated:YES]; 66 | 67 | [[NSNotificationCenter defaultCenter] removeObserver:failedObserver]; 68 | [self release]; 69 | }]; 70 | 71 | [request addItemWithURL:url]; 72 | [request autorelease]; 73 | } 74 | 75 | - (UIViewController *)submitFromController:(UIViewController *)controller { 76 | if ([InstapaperSession currentSession] != nil) { 77 | [self submitInstapaperRequest]; 78 | return nil; 79 | } else { 80 | InstapaperLoginController *login = [[InstapaperLoginController alloc] init]; 81 | [login setPendingURL:url]; 82 | [login setDelegate:self]; 83 | 84 | NavigationController *navigation = [[NavigationController alloc] initWithRootViewController:login]; 85 | if (controller != nil) { 86 | presented = YES; 87 | [self retain]; 88 | 89 | [controller presentViewController:navigation animated:YES completion:NULL]; 90 | } 91 | [navigation autorelease]; 92 | 93 | return navigation; 94 | } 95 | } 96 | 97 | - (void)dismissLoginController:(InstapaperLoginController *)controller loggedIn:(BOOL)loggedIn { 98 | if (presented) { 99 | [self release]; 100 | presented = NO; 101 | 102 | [controller dismissViewControllerAnimated:YES completion:NULL]; 103 | } 104 | 105 | if (loginCompletion != NULL) { 106 | loginCompletion(loggedIn); 107 | 108 | [loginCompletion release]; 109 | loginCompletion = nil; 110 | } 111 | } 112 | 113 | - (void)loginControllerDidLogin:(InstapaperLoginController *)controller { 114 | [self submitInstapaperRequest]; 115 | [self dismissLoginController:controller loggedIn:YES]; 116 | } 117 | 118 | - (void)loginControllerDidCancel:(InstapaperLoginController *)controller { 119 | [self dismissLoginController:controller loggedIn:NO]; 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /Classes/Controllers/LoadingController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoadingController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/4/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | 13 | #import "LoginController.h" 14 | 15 | #import "BarButtonItem.h" 16 | #import "ActivityIndicatorItem.h" 17 | #import "PlacardButton.h" 18 | 19 | @class LoadingIndicatorView; 20 | @interface LoadingController : UIViewController { 21 | HNObject *source; 22 | 23 | UIView *statusView; 24 | NSMutableSet *statusViews; 25 | 26 | PlacardButton *retryButton; 27 | LoadingIndicatorView *indicator; 28 | 29 | NSDate *lastUpdatedOnAppearDate; 30 | 31 | BarButtonItem *actionItem; 32 | NSInteger openInSafariIndex; 33 | NSInteger mailLinkIndex; 34 | NSInteger copyLinkIndex; 35 | NSInteger readLaterIndex; 36 | } 37 | 38 | @property (nonatomic, retain) HNObject *source; 39 | 40 | - (id)initWithSource:(HNObject *)source_; 41 | - (NSString *)sourceTitle; 42 | - (void)finishedLoading; 43 | 44 | - (void)addStatusView:(UIView *)view; 45 | - (void)removeStatusView:(UIView *)view; 46 | - (void)updateStatusDisplay; 47 | 48 | - (void)sourceStartedLoading; 49 | - (void)sourceFinishedLoading; 50 | - (void)sourceFailedLoading; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Classes/Controllers/LoginController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoginController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/22/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "BarButtonItem.h" 10 | #import "ActivityIndicatorItem.h" 11 | 12 | @protocol LoginControllerDelegate; 13 | 14 | @interface LoginController : UIViewController { 15 | UIImageView *backgroundImageView; 16 | UIView *centeringAlignmentView; 17 | UIView *tableContainerView; 18 | UITableView *tableView; 19 | 20 | UITableViewCell *usernameCell; 21 | UITextField *usernameField; 22 | UITableViewCell *passwordCell; 23 | UITextField *passwordField; 24 | UITableViewCell *loadingCell; 25 | 26 | BarButtonItem *cancelItem; 27 | BarButtonItem *completeItem; 28 | ActivityIndicatorItem *loadingItem; 29 | 30 | __weak id delegate; 31 | 32 | UILabel *topLabel; 33 | UILabel *bottomLabel; 34 | 35 | BOOL isAuthenticating; 36 | } 37 | 38 | @property (nonatomic, assign) id delegate; 39 | 40 | - (void)finish; 41 | - (void)authenticate; 42 | 43 | - (void)fail; 44 | - (void)succeed; 45 | - (void)cancel; 46 | 47 | @end 48 | 49 | @protocol LoginControllerDelegate 50 | @optional 51 | 52 | - (void)loginControllerDidLogin:(LoginController *)controller; 53 | - (void)loginControllerDidCancel:(LoginController *)controller; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Classes/Controllers/MainTabBarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MainTabBarController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/30/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "BarButtonItem.h" 10 | 11 | #import "LoginController.h" 12 | #import "TabBarController.h" 13 | 14 | @class EntryListController, SessionProfileController, MoreController, SearchController, HNSession; 15 | 16 | @interface MainTabBarController : UITabBarController { 17 | HNSession *session; 18 | 19 | EntryListController *home; 20 | EntryListController *latest; 21 | SearchController *search; 22 | SessionProfileController *profile; 23 | MoreController *more; 24 | 25 | BarButtonItem *composeItem; 26 | } 27 | 28 | - (id)initWithSession:(HNSession *)session_; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Classes/Controllers/ModalNavigationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ModalNavigationController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/22/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "NavigationController.h" 10 | 11 | #import "BarButtonItem.h" 12 | 13 | @interface ModalNavigationController : NavigationController { 14 | BarButtonItem *doneItem; 15 | UIViewController *currentController; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Controllers/ModalNavigationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ModalNavigationController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/22/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "ModalNavigationController.h" 10 | 11 | #import "UINavigationItem+MultipleItems.h" 12 | 13 | @implementation ModalNavigationController 14 | 15 | - (void)viewDidLoad { 16 | [super viewDidLoad]; 17 | 18 | [self setModalPresentationStyle:UIModalPresentationFormSheet]; 19 | [self setDelegate:self]; 20 | 21 | doneItem = [[BarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismiss)]; 22 | } 23 | 24 | - (void)viewDidUnload { 25 | [super viewDidUnload]; 26 | 27 | // Don't release doneItem here, because we depend on it staying the same 28 | // object for the lifetime of this navigation controller (for removal). 29 | } 30 | 31 | - (void)dealloc { 32 | [doneItem release]; 33 | 34 | [super dealloc]; 35 | } 36 | 37 | - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { 38 | [[currentController navigationItem] removeRightBarButtonItem:doneItem]; 39 | [[viewController navigationItem] addRightBarButtonItem:doneItem atPosition:UINavigationItemPositionRight]; 40 | 41 | currentController = viewController; 42 | } 43 | 44 | - (void)dismiss { 45 | [self dismissViewControllerAnimated:YES completion:NULL]; 46 | } 47 | 48 | AUTOROTATION_FOR_PAD_ONLY 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Classes/Controllers/MoreController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MoreController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/9/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "OrangeTableView.h" 10 | 11 | @interface MoreController : UIViewController { 12 | HNSession *session; 13 | 14 | OrangeTableView *tableView; 15 | } 16 | 17 | - (id)initWithSession:(HNSession *)session_; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Controllers/NavigationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/29/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | // An orange navigation controller. Sometimes. 10 | 11 | #import "LoginController.h" 12 | #import "HackerNewsLoginController.h" 13 | 14 | @protocol NavigationControllerLoginDelegate; 15 | 16 | @interface NavigationController : UINavigationController { 17 | id loginDelegate; 18 | } 19 | 20 | @property (nonatomic, assign) id loginDelegate; 21 | - (void)requestLogin; 22 | - (void)requestSessions; 23 | 24 | @end 25 | 26 | @interface UIViewController (NavigationController) 27 | 28 | - (NavigationController *)navigation; 29 | 30 | @end 31 | 32 | @protocol NavigationControllerLoginDelegate 33 | 34 | - (void)navigationController:(NavigationController *)navigationController didLoginWithSession:(HNSession *)session; 35 | - (void)navigationControllerRequestedSessions:(NavigationController *)navigationController; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Classes/Controllers/NavigationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/29/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "NavigationController.h" 10 | 11 | #import "LoginController.h" 12 | #import "UIColor+Orange.h" 13 | #import "HackerNewsLoginController.h" 14 | #import "OrangeNavigationBar.h" 15 | 16 | @implementation NavigationController 17 | @synthesize loginDelegate; 18 | 19 | - (id)init { 20 | return [self initWithRootViewController:nil]; 21 | } 22 | 23 | - (id)initWithRootViewController:(UIViewController *)rootViewController { 24 | if ((self = [super initWithNavigationBarClass:[OrangeNavigationBar class] toolbarClass:nil])) { 25 | if (rootViewController != nil) { 26 | [self pushViewController:rootViewController animated:NO]; 27 | } 28 | } 29 | 30 | return self; 31 | } 32 | 33 | - (void)viewDidLoad { 34 | [super viewDidLoad]; 35 | 36 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enteredForeground) name:UIApplicationWillEnterForegroundNotification object:nil]; 37 | } 38 | 39 | - (void)viewDidUnload { 40 | [super viewDidUnload]; 41 | 42 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; 43 | } 44 | 45 | - (void)dealloc { 46 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; 47 | 48 | [super dealloc]; 49 | } 50 | 51 | - (void)enteredForeground { 52 | [self viewWillAppear:NO]; 53 | [self viewDidAppear:NO]; 54 | } 55 | 56 | - (void)viewWillAppear:(BOOL)animated { 57 | [super viewWillAppear:animated]; 58 | 59 | OrangeNavigationBar *navigationBar = (OrangeNavigationBar *)[self navigationBar]; 60 | [navigationBar setOrange:![[NSUserDefaults standardUserDefaults] boolForKey:@"disable-orange"]]; 61 | 62 | if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { 63 | [self setNeedsStatusBarAppearanceUpdate]; 64 | } 65 | } 66 | 67 | - (UIStatusBarStyle)preferredStatusBarStyle { 68 | if (![[NSUserDefaults standardUserDefaults] boolForKey:@"disable-orange"]) { 69 | return UIStatusBarStyleLightContent; 70 | } else { 71 | return UIStatusBarStyleDefault; 72 | } 73 | } 74 | 75 | - (UIViewController *)childViewControllerForStatusBarStyle { 76 | return nil; 77 | } 78 | 79 | // Why this isn't delegated by UIKit to the top view controller, I have no clue. 80 | // This, however, should unobstrusively add that delegation. 81 | - (UIModalPresentationStyle)modalPresentationStyle { 82 | UIModalPresentationStyle style = [super modalPresentationStyle]; 83 | 84 | if (style != UIModalPresentationFullScreen) { 85 | return style; 86 | } else if ([self topViewController]) { 87 | return [[self topViewController] modalPresentationStyle]; 88 | } else { 89 | return style; 90 | } 91 | } 92 | 93 | - (void)loginControllerDidLogin:(HackerNewsLoginController *)controller { 94 | [self dismissViewControllerAnimated:YES completion:^{ 95 | [loginDelegate navigationController:self didLoginWithSession:[controller session]]; 96 | }]; 97 | } 98 | 99 | - (void)loginControllerDidCancel:(HackerNewsLoginController *)controller { 100 | [self dismissViewControllerAnimated:YES completion:NULL]; 101 | } 102 | 103 | - (void)requestLogin { 104 | LoginController *login = [[HackerNewsLoginController alloc] init]; 105 | [login setDelegate:self]; 106 | 107 | NavigationController *navigation = [[NavigationController alloc] initWithRootViewController:login]; 108 | [self presentViewController:navigation animated:YES completion:NULL]; 109 | 110 | [navigation release]; 111 | [login release]; 112 | } 113 | 114 | - (void)requestSessions { 115 | [loginDelegate navigationControllerRequestedSessions:self]; 116 | } 117 | 118 | AUTOROTATION_FOR_PAD_ONLY 119 | 120 | @end 121 | 122 | @implementation UIViewController (NavigationController) 123 | 124 | - (NavigationController *)navigation { 125 | UIViewController *parentViewController = [self parentViewController]; 126 | 127 | while (parentViewController != nil) { 128 | if ([parentViewController isKindOfClass:[NavigationController class]]) { 129 | return (NavigationController *)parentViewController; 130 | } 131 | 132 | parentViewController = [parentViewController parentViewController]; 133 | } 134 | 135 | return nil; 136 | } 137 | 138 | @end 139 | -------------------------------------------------------------------------------- /Classes/Controllers/OpenInSafariActivity.h: -------------------------------------------------------------------------------- 1 | // 2 | // OpenInSafariActivity.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 11/8/12. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface OpenInSafariActivity : UIActivity { 12 | NSURL *url; 13 | } 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/Controllers/OpenInSafariActivity.m: -------------------------------------------------------------------------------- 1 | // 2 | // OpenInSafariActivity.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 11/8/12. 6 | // 7 | // 8 | 9 | #import "OpenInSafariActivity.h" 10 | 11 | @implementation OpenInSafariActivity 12 | 13 | - (void)dealloc { 14 | [url release]; 15 | 16 | [super dealloc]; 17 | } 18 | 19 | - (NSString *)activityType { 20 | return @"com.apple.safari.open-in"; 21 | } 22 | 23 | - (NSString *)activityTitle { 24 | return @"Open in Safari"; 25 | } 26 | 27 | - (UIImage *)activityImage { 28 | if ([[self class] respondsToSelector:@selector(activityCategory)]) { 29 | return [UIImage imageNamed:@"openinsafari7.png"]; 30 | } else { 31 | return [UIImage imageNamed:@"openinsafari.png"]; 32 | } 33 | } 34 | 35 | - (BOOL)canPerformWithActivityItems:(NSArray *)activityItems { 36 | return YES; 37 | } 38 | 39 | - (void)prepareWithActivityItems:(NSArray *)activityItems { 40 | [url release]; 41 | 42 | url = [[activityItems lastObject] copy]; 43 | } 44 | 45 | - (void)performActivity { 46 | [[UIApplication sharedApplication] openURL:url]; 47 | [self activityDidFinish:YES]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Classes/Controllers/ProfileController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/4/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "LoadingController.h" 10 | #import "OrangeTableView.h" 11 | #import "BodyTextView.h" 12 | 13 | @class ProfileHeaderView; 14 | @interface ProfileController : LoadingController { 15 | OrangeTableView *tableView; 16 | ProfileHeaderView *header; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Controllers/SearchController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SearchController.h 3 | // newsyc 4 | // 5 | // Created by Quin Hoxie on 6/2/11. 6 | // 7 | 8 | #import 9 | 10 | @class EmptyView; 11 | @class OrangeToolbar; 12 | @class LoadingIndicatorView; 13 | 14 | @interface SearchController : UIViewController { 15 | HNSession *session; 16 | HNAPISearch *searchAPI; 17 | NSMutableArray *entries; 18 | 19 | UISearchBar *searchBar; 20 | OrangeToolbar *coloredView; 21 | UISegmentedControl *facetControl; 22 | 23 | UITableView *tableView; 24 | EmptyView *emptyView; 25 | LoadingIndicatorView *indicator; 26 | BOOL searchPerformed; 27 | } 28 | 29 | - (id)initWithSession:(HNSession *)session_; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Classes/Controllers/SessionListController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SessionListController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 1/8/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | #import "NavigationController.h" 12 | 13 | @interface SessionListController : UIViewController { 14 | NSArray *sessions; 15 | HNSession *automaticDisplaySession; 16 | 17 | UITableView *tableView; 18 | BarButtonItem *editBarButtonItem; 19 | BarButtonItem *doneBarButtonItem; 20 | BarButtonItem *addBarButtonItem; 21 | } 22 | 23 | @property (nonatomic, retain) HNSession *automaticDisplaySession; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Classes/Controllers/SessionProfileController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SessionProfileController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/29/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "ProfileController.h" 12 | #import "LoginController.h" 13 | 14 | #import "BarButtonItem.h" 15 | 16 | @interface SessionProfileController : ProfileController 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Controllers/SessionProfileController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SessionProfileController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/29/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "UIActionSheet+Context.h" 10 | 11 | #import "SessionProfileController.h" 12 | #import "LoginController.h" 13 | #import "HackerNewsLoginController.h" 14 | #import "NavigationController.h" 15 | #import "PlacardButton.h" 16 | #import "SubmissionListController.h" 17 | 18 | #import "AppDelegate.h" 19 | 20 | @implementation SessionProfileController 21 | 22 | - (BOOL)showSessionListButton { 23 | return [[HNSessionController sessionController] numberOfSessions] == 1; 24 | } 25 | 26 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)table { 27 | return [super numberOfSectionsInTableView:tableView] + ([self showSessionListButton] ? 1 : 0); 28 | } 29 | 30 | - (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section { 31 | if (section == 1) { 32 | return [super tableView:table numberOfRowsInSection:section] + 1; 33 | } else if (section == 2) { 34 | return 1; 35 | } else { 36 | return [super tableView:table numberOfRowsInSection:section]; 37 | } 38 | } 39 | 40 | - (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath { 41 | if ([indexPath section] == 1 && [indexPath row] == [tableView numberOfRowsInSection:[indexPath section]] - 1) { 42 | UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; 43 | [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; 44 | 45 | [[cell textLabel] setText:@"Saved"]; 46 | 47 | return [cell autorelease]; 48 | } else if ([indexPath section] == 2) { 49 | UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; 50 | 51 | [cell setAccessoryType:UITableViewCellAccessoryNone]; 52 | [[cell textLabel] setTextAlignment:NSTextAlignmentCenter]; 53 | [[cell textLabel] setText:@"Accounts"]; 54 | 55 | return [cell autorelease]; 56 | } else { 57 | return [super tableView:table cellForRowAtIndexPath:indexPath]; 58 | } 59 | } 60 | 61 | - (void)tableView:(UITableView *)table didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 62 | if ([indexPath section] == 1 && [indexPath row] == [tableView numberOfRowsInSection:[indexPath section]] - 1) { 63 | HNEntryList *list = [HNEntryList session:[source session] entryListWithIdentifier:kHNEntryListIdentifierSaved user:(HNUser *) source]; 64 | 65 | SubmissionListController *controller = [[SubmissionListController alloc] initWithSource:list]; 66 | [controller setTitle:@"Saved"]; 67 | [[self navigation] pushController:[controller autorelease] animated:YES]; 68 | } else if ([indexPath section] == 2) { 69 | [[self navigation] requestSessions]; 70 | } else { 71 | [super tableView:table didSelectRowAtIndexPath:indexPath]; 72 | } 73 | } 74 | 75 | AUTOROTATION_FOR_PAD_ONLY 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Classes/Controllers/SharingController.h: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 2/24/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | @class BarButtonItem; 10 | 11 | @interface SharingController : NSObject { 12 | NSURL *url; 13 | NSString *title; 14 | UIViewController *controller; 15 | } 16 | 17 | - (id)initWithURL:(NSURL *)url title:(NSString *)title fromController:(UIViewController *)controller; 18 | 19 | - (void)showFromView:(UIView *)view; 20 | - (void)showFromView:(UIView *)view atRect:(CGRect)rect; 21 | - (void)showFromBarButtonItem:(BarButtonItem *)item; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/Controllers/SharingController.m: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 2/24/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "SharingController.h" 10 | 11 | #import 12 | 13 | #import "InstapaperLoginController.h" 14 | #import "InstapaperRequest.h" 15 | #import "InstapaperSession.h" 16 | 17 | #import "InstapaperSubmission.h" 18 | #import "InstapaperActivity.h" 19 | 20 | #import "OpenInSafariActivity.h" 21 | 22 | #import "BarButtonItem.h" 23 | 24 | @implementation SharingController 25 | 26 | - (id)initWithURL:(NSURL *)url_ title:(NSString *)title_ fromController:(UIViewController *)controller_ { 27 | if ((self = [super init])) { 28 | url = [url_.absoluteURL copy]; 29 | title = [title_ copy]; 30 | controller = controller_; // XXX: retain this? 31 | } 32 | 33 | return self; 34 | } 35 | 36 | - (void)dealloc { 37 | [url release]; 38 | [title release]; 39 | 40 | [super dealloc]; 41 | } 42 | 43 | - (void)showFromView:(UIView *)view barButtonItem:(BarButtonItem *)item atRect:(CGRect)rect { 44 | if (CGRectIsNull(rect)) { 45 | rect = [view frame]; 46 | } else { 47 | rect = [[view superview] convertRect:rect fromView:view]; 48 | } 49 | 50 | if (controller == nil) { 51 | controller = [[view window] rootViewController]; 52 | } 53 | 54 | InstapaperActivity *instapaperActivity = [[InstapaperActivity alloc] init]; 55 | OpenInSafariActivity *openInSafariActivity = [[OpenInSafariActivity alloc] init]; 56 | 57 | NSArray *activityItems = [NSArray arrayWithObject:url]; 58 | NSArray *applicationActivities = [NSArray arrayWithObjects:instapaperActivity, openInSafariActivity, nil]; 59 | 60 | [instapaperActivity release]; 61 | [openInSafariActivity release]; 62 | 63 | UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities]; 64 | 65 | NSMutableArray *excludedActivityTypes = [NSMutableArray array]; 66 | [excludedActivityTypes addObject:UIActivityTypePrint]; 67 | [excludedActivityTypes addObject:UIActivityTypeSaveToCameraRoll]; 68 | [excludedActivityTypes addObject:UIActivityTypeMessage]; 69 | if ([UIActivityViewController instancesRespondToSelector:@selector(topLayoutGuide)]) { 70 | [excludedActivityTypes addObject:UIActivityTypePostToFlickr]; 71 | [excludedActivityTypes addObject:UIActivityTypePostToVimeo]; 72 | [excludedActivityTypes addObject:UIActivityTypeAirDrop]; 73 | } 74 | [activityController setExcludedActivityTypes:excludedActivityTypes]; 75 | 76 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 77 | UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:activityController]; 78 | 79 | if (item != nil) { 80 | [popover presentPopoverFromBarButtonItemInWindow:item permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 81 | } else if (view != nil) { 82 | [popover presentPopoverFromRect:rect inView:[view superview] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 83 | } else { 84 | NSAssert(NO, @"You must provide a view or a bar button item to a sharing controller."); 85 | } 86 | 87 | [activityController setCompletionHandler:^(NSString *activityType, BOOL completed) { 88 | [popover dismissPopoverAnimated:YES]; 89 | [popover release]; 90 | }]; 91 | } else { 92 | [controller presentViewController:activityController animated:YES completion:NULL]; 93 | } 94 | } 95 | 96 | - (void)showFromView:(UIView *)view { 97 | [self showFromView:view barButtonItem:nil atRect:CGRectNull]; 98 | } 99 | 100 | - (void)showFromView:(UIView *)view atRect:(CGRect)rect { 101 | [self showFromView:view barButtonItem:nil atRect:rect]; 102 | } 103 | 104 | - (void)showFromBarButtonItem:(BarButtonItem *)item { 105 | [self showFromView:nil barButtonItem:item atRect:CGRectNull]; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /Classes/Controllers/SplitViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SplitViewController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/21/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SplitViewController : UISplitViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/Controllers/SplitViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SplitViewController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/21/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "SplitViewController.h" 10 | 11 | @implementation SplitViewController 12 | 13 | - (UIViewController *)childViewControllerForStatusBarStyle { 14 | return [[self viewControllers] firstObject]; 15 | } 16 | 17 | AUTOROTATION_FOR_PAD_ONLY; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Controllers/SubmissionListController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SubmissionListController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 2/24/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "EntryListController.h" 10 | 11 | @interface SubmissionListController : EntryListController { 12 | UISwipeGestureRecognizer *swipeRecognizer; 13 | } 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/Controllers/SubmissionListController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SubmissionListController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 2/24/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "SubmissionListController.h" 10 | 11 | #import "SubmissionTableCell.h" 12 | #import "CommentListController.h" 13 | #import "BrowserController.h" 14 | 15 | #import "AppDelegate.h" 16 | 17 | @implementation SubmissionListController 18 | 19 | + (Class)cellClass { 20 | return [SubmissionTableCell class]; 21 | } 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | 26 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 27 | swipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRecognized:)]; 28 | swipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft; 29 | [self.view addGestureRecognizer:swipeRecognizer]; 30 | } 31 | } 32 | 33 | - (void)viewDidUnload { 34 | [super viewDidUnload]; 35 | 36 | [swipeRecognizer release]; 37 | swipeRecognizer = nil; 38 | } 39 | 40 | - (void)dealloc { 41 | [swipeRecognizer release]; 42 | 43 | [super dealloc]; 44 | } 45 | 46 | - (CGFloat)cellHeightForEntry:(HNEntry *)entry { 47 | return [SubmissionTableCell heightForEntry:entry withWidth:[[self view] bounds].size.width]; 48 | } 49 | 50 | - (void)configureCell:(UITableViewCell *)cell forEntry:(HNEntry *)entry { 51 | SubmissionTableCell *cell_ = (SubmissionTableCell *) cell; 52 | [cell_ setSubmission:entry]; 53 | } 54 | 55 | - (void)cellSelected:(UITableViewCell *)cell forEntry:(HNEntry *)entry { 56 | CommentListController *controller = [[CommentListController alloc] initWithSource:entry]; 57 | [[self navigation] pushController:controller animated:YES]; 58 | [controller release]; 59 | } 60 | 61 | - (void)deselectWithAnimation:(BOOL)animated { 62 | if ([[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPad) { 63 | [super deselectWithAnimation:animated]; 64 | } 65 | } 66 | 67 | - (NSString *)sourceTitle { 68 | return [self title]; 69 | } 70 | 71 | - (void)swipeRecognized:(UISwipeGestureRecognizer *)recognizer { 72 | CGPoint location = [recognizer locationInView:tableView]; 73 | NSIndexPath *indexPath = [tableView indexPathForRowAtPoint:location]; 74 | 75 | HNEntry *entry = [self entryAtIndexPath:indexPath]; 76 | 77 | NSArray *viewControllers = [[self navigation] controllers]; 78 | 79 | CommentListController *commentController = [[CommentListController alloc] initWithSource:entry]; 80 | viewControllers = [viewControllers arrayByAddingObject:commentController]; 81 | [commentController release]; 82 | 83 | BrowserController *browserController = [[BrowserController alloc] initWithURL:[entry destination]]; 84 | viewControllers = [viewControllers arrayByAddingObject:browserController]; 85 | [browserController release]; 86 | 87 | // This bypasses the normal navigation flow, so only works for phone idioms. 88 | [[self navigation] setControllers:viewControllers animated:YES]; 89 | } 90 | 91 | AUTOROTATION_FOR_PAD_ONLY 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Classes/Controllers/SubmissionTextComposeController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SubmissionTextComposeController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/31/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "ComposeController.h" 10 | #import 11 | 12 | @interface SubmissionTextComposeController : ComposeController { 13 | __weak UITextField *titleField; 14 | } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Controllers/SubmissionTextComposeController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SubmissionTextComposeController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/31/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "SubmissionTextComposeController.h" 10 | #import "PlaceholderTextView.h" 11 | 12 | @implementation SubmissionTextComposeController 13 | 14 | - (BOOL)includeMultilineEditor { 15 | return YES; 16 | } 17 | 18 | - (NSString *)multilinePlaceholder { 19 | return @"Post Body"; 20 | } 21 | 22 | - (NSString *)title { 23 | return @"Submit Text"; 24 | } 25 | 26 | - (NSArray *)inputEntryCells { 27 | UITableViewCell *cell = [self generateTextFieldCell]; 28 | [[cell textLabel] setText:@"Title:"]; 29 | titleField = [self generateTextFieldForCell:cell]; 30 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:UITextFieldTextDidChangeNotification object:nil]; 31 | [cell addSubview:titleField]; 32 | 33 | return [NSArray arrayWithObject:cell]; 34 | } 35 | 36 | - (UIResponder *)initialFirstResponder { 37 | return titleField; 38 | } 39 | 40 | - (void)submissionSucceededWithNotification:(NSNotification *)notification { 41 | [self sendComplete]; 42 | 43 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNSubmissionFailureNotification object:[notification object]]; 44 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNSubmissionSuccessNotification object:[notification object]]; 45 | } 46 | 47 | - (void)submissionFailedWithNotification:(NSNotification *)notification { 48 | [self sendFailed]; 49 | 50 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNSubmissionFailureNotification object:[notification object]]; 51 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNSubmissionSuccessNotification object:[notification object]]; 52 | } 53 | 54 | - (void)performSubmission { 55 | if (![self ableToSubmit]) { 56 | [self sendFailed]; 57 | } else { 58 | HNSubmission *submission = [[HNSubmission alloc] initWithSubmissionType:kHNSubmissionTypeSubmission]; 59 | [submission setTitle:[titleField text]]; 60 | [submission setBody:[textView text]]; 61 | [session performSubmission:submission]; 62 | 63 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(submissionSucceededWithNotification:) name:kHNSubmissionSuccessNotification object:submission]; 64 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(submissionFailedWithNotification:) name:kHNSubmissionFailureNotification object:submission]; 65 | 66 | [submission release]; 67 | } 68 | } 69 | 70 | - (BOOL)ableToSubmit { 71 | return !([[titleField text] length] == 0 || [[textView text] length] == 0); 72 | } 73 | 74 | - (void)viewDidUnload { 75 | [super viewDidUnload]; 76 | 77 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil]; 78 | 79 | titleField = nil; 80 | } 81 | 82 | - (void)dealloc { 83 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil]; 84 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNSubmissionFailureNotification object:nil]; 85 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNSubmissionSuccessNotification object:nil]; 86 | 87 | [super dealloc]; 88 | } 89 | 90 | AUTOROTATION_FOR_PAD_ONLY 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /Classes/Controllers/SubmissionURLComposeController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SubmissionURLComposeController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/31/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "ComposeController.h" 10 | #import 11 | 12 | @interface SubmissionURLComposeController : ComposeController { 13 | __weak UITextField *titleField; 14 | } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Controllers/SubmissionURLComposeController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SubmissionURLComposeController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/31/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "SubmissionURLComposeController.h" 10 | #import "PlaceholderTextView.h" 11 | 12 | @implementation SubmissionURLComposeController 13 | 14 | - (void)viewDidLoad { 15 | [super viewDidLoad]; 16 | 17 | UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; 18 | if (nil != pasteboard.string) { 19 | NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil]; 20 | NSArray *matches = [detector matchesInString:pasteboard.string options:0 range:NSMakeRange(0, [pasteboard.string length])]; 21 | if ([matches count] > 0) { 22 | textView.text = [[[matches objectAtIndex:0] URL] absoluteString]; 23 | } 24 | } 25 | 26 | textView.autocapitalizationType = UITextAutocapitalizationTypeNone; 27 | } 28 | 29 | - (BOOL)includeMultilineEditor { 30 | return YES; 31 | } 32 | 33 | - (NSString *)multilinePlaceholder { 34 | return @"URL"; 35 | } 36 | 37 | - (NSString *)title { 38 | return @"Submit URL"; 39 | } 40 | 41 | - (NSArray *)inputEntryCells { 42 | UITableViewCell *cell = [self generateTextFieldCell]; 43 | [[cell textLabel] setText:@"Title:"]; 44 | titleField = [self generateTextFieldForCell:cell]; 45 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:UITextFieldTextDidChangeNotification object:nil]; 46 | [cell addSubview:titleField]; 47 | 48 | return [NSArray arrayWithObject:cell]; 49 | } 50 | 51 | - (UIResponder *)initialFirstResponder { 52 | return titleField; 53 | } 54 | 55 | - (void)submissionSucceededWithNotification:(NSNotification *)notification { 56 | [self sendComplete]; 57 | } 58 | 59 | - (void)submissionFailedWithNotification:(NSNotification *)notification { 60 | [self sendFailed]; 61 | } 62 | 63 | - (void)performSubmission { 64 | if (![self ableToSubmit]) { 65 | [self sendFailed]; 66 | } else { 67 | HNSubmission *submission = [[HNSubmission alloc] initWithSubmissionType:kHNSubmissionTypeSubmission]; 68 | [submission setTitle:[titleField text]]; 69 | [submission setDestination:[NSURL URLWithString:[textView text]]]; 70 | [session performSubmission:submission]; 71 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(submissionSucceededWithNotification:) name:kHNSubmissionSuccessNotification object:submission]; 72 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(submissionFailedWithNotification:) name:kHNSubmissionFailureNotification object:submission]; 73 | [submission release]; 74 | } 75 | } 76 | 77 | - (BOOL)ableToSubmit { 78 | NSURL *url = [NSURL URLWithString:[textView text]]; 79 | return !([[titleField text] length] == 0 || [[textView text] length] == 0 || url == nil); 80 | } 81 | 82 | - (void)dealloc { 83 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNSubmissionSuccessNotification object:nil]; 84 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNSubmissionFailureNotification object:nil]; 85 | 86 | [super dealloc]; 87 | } 88 | 89 | AUTOROTATION_FOR_PAD_ONLY 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /Classes/Controllers/TabBarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TabBarController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 10/7/13. 6 | // 7 | // 8 | 9 | @interface TabBarController : UIViewController { 10 | UITabBar *tabBar; 11 | NSArray *viewControllers; 12 | UIViewController *selectedViewController; 13 | } 14 | 15 | @property (nonatomic, readonly) UITabBar *tabBar; 16 | 17 | @property (nonatomic, copy) NSArray *viewControllers; 18 | @property (nonatomic, assign) UIViewController *selectedViewController; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Classes/Controllers/TabBarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TabBarController.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 10/7/13. 6 | // 7 | // 8 | 9 | #import "TabBarController.h" 10 | 11 | @implementation TabBarController 12 | @synthesize tabBar, viewControllers, selectedViewController; 13 | 14 | - (void)loadView { 15 | [super loadView]; 16 | 17 | tabBar = [[UITabBar alloc] init]; 18 | [tabBar setDelegate:self]; 19 | [[self view] addSubview:tabBar]; 20 | } 21 | 22 | - (void)viewDidLayoutSubviews { 23 | [super viewDidLayoutSubviews]; 24 | 25 | [tabBar sizeToFit]; 26 | [tabBar setFrame:CGRectMake(0, [[self view] bounds].size.height - [tabBar bounds].size.height, [[self view] bounds].size.width, [tabBar bounds].size.height)]; 27 | 28 | CGRect controllerFrame = CGRectMake(0, [[self topLayoutGuide] length], [[self view] bounds].size.width, [[self view] bounds].size.height - [[self topLayoutGuide] length] - [[self bottomLayoutGuide] length] - [tabBar bounds].size.height); 29 | [[selectedViewController view] setFrame:controllerFrame]; 30 | } 31 | 32 | - (void)setViewControllers:(NSArray *)viewControllers_ { 33 | if (viewControllers != viewControllers_) { 34 | [self setSelectedViewController:nil]; 35 | 36 | for (UIViewController *viewController in viewControllers) { 37 | [viewController willMoveToParentViewController:nil]; 38 | [viewController removeFromParentViewController]; 39 | } 40 | 41 | [viewControllers release]; 42 | viewControllers = [viewControllers_ copy]; 43 | 44 | NSMutableArray *tabBarItems = [NSMutableArray array]; 45 | 46 | for (UIViewController *viewController in viewControllers) { 47 | [self addChildViewController:viewController]; 48 | [viewController didMoveToParentViewController:self]; 49 | 50 | [tabBarItems addObject:[viewController tabBarItem]]; 51 | } 52 | 53 | [self view]; 54 | [tabBar setItems:tabBarItems]; 55 | 56 | if ([viewControllers count] > 0) { 57 | [self setSelectedViewController:[viewControllers objectAtIndex:0]]; 58 | } 59 | } 60 | } 61 | 62 | - (void)setSelectedViewController:(UIViewController *)selectedViewController_ { 63 | if (selectedViewController != selectedViewController_) { 64 | [[selectedViewController view] removeFromSuperview]; 65 | 66 | selectedViewController = selectedViewController_; 67 | [tabBar setSelectedItem:[selectedViewController tabBarItem]]; 68 | 69 | [[self view] addSubview:[selectedViewController view]]; 70 | [[self view] bringSubviewToFront:tabBar]; 71 | } 72 | } 73 | 74 | - (void)tabBar:(UITabBar *)tabBar_ didSelectItem:(UITabBarItem *)item { 75 | NSInteger index = [[tabBar items] indexOfObject:item]; 76 | [self setSelectedViewController:[viewControllers objectAtIndex:index]]; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /Classes/Follow Model/HNSession+Following.h: -------------------------------------------------------------------------------- 1 | // 2 | // HNSession+Following.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 8/21/11. 6 | // Copyright (c) 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #ifdef ENABLE_TIMELINE 12 | 13 | #define kHNSessionUserFollowedUsersChangedNotification @"HNSessionUserFollowedUsersChanged" 14 | 15 | @interface HNSession (Following) 16 | 17 | @property (nonatomic, readonly) NSSet *usersFollowed; 18 | 19 | - (void)followUser:(HNUser *)user; 20 | - (void)unfollowUser:(HNUser *)user; 21 | 22 | @end 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Classes/Follow Model/HNSession+Following.m: -------------------------------------------------------------------------------- 1 | // 2 | // HNSession+Following.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 8/21/11. 6 | // Copyright (c) 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "HNSession+Following.h" 10 | #import 11 | 12 | #import 13 | 14 | #ifdef ENABLE_TIMELINE 15 | 16 | @implementation HNSession (Following) 17 | 18 | static NSString *HNSessionFollowingUsersFollowedKey = @"HNSessionFollowingUsersFollowed"; 19 | 20 | - (NSMutableSet *)_usersFollowed { 21 | NSMutableSet *users = objc_getAssociatedObject(self, &HNSessionFollowingUsersFollowedKey); 22 | 23 | if (users == nil) { 24 | users = [NSMutableSet set]; 25 | NSSet *userIdentifiers = [[NSUserDefaults standardUserDefaults] objectForKey:@"HNSession(Following):UsersFollowed"]; 26 | userIdentifiers = [NSSet setWithObjects:@"saurik", @"comex", @"tptacek", @"daeken", nil]; 27 | 28 | for (NSString *identifier in userIdentifiers) { 29 | HNUser *user_ = [HNUser userWithIdentifier:identifier]; 30 | [users addObject:user_]; 31 | } 32 | 33 | objc_setAssociatedObject(self, &HNSessionFollowingUsersFollowedKey, users, OBJC_ASSOCIATION_COPY_NONATOMIC); 34 | } 35 | 36 | return users; 37 | } 38 | 39 | - (NSSet *)usersFollowed { 40 | return [self _usersFollowed]; 41 | } 42 | 43 | - (void)saveUsersFollowed { 44 | [[NSUserDefaults standardUserDefaults] setObject:[self usersFollowed] forKey:@"HNSession(Following):UsersFollowed"]; 45 | } 46 | 47 | - (void)followUser:(HNUser *)user_ { 48 | [[self _usersFollowed] removeObject:user_]; 49 | [self saveUsersFollowed]; 50 | 51 | [[NSNotificationCenter defaultCenter] postNotificationName:kHNSessionUserFollowedUsersChangedNotification object:self]; 52 | } 53 | 54 | - (void)unfollowUser:(HNUser *)user_ { 55 | [[self _usersFollowed] addObject:user_]; 56 | [self saveUsersFollowed]; 57 | 58 | [[NSNotificationCenter defaultCenter] postNotificationName:kHNSessionUserFollowedUsersChangedNotification object:self]; 59 | } 60 | 61 | @end 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /Classes/Follow Model/HNTimeline.h: -------------------------------------------------------------------------------- 1 | // 2 | // HNTimeline.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 8/21/11. 6 | // Copyright (c) 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #ifdef ENABLE_TIMELINE 12 | 13 | #define kHNEntryListIdentifierTimeline @"timeline" 14 | 15 | @class HNSession; 16 | 17 | @interface HNTimeline : HNEntryList { 18 | HNSession *session; 19 | NSMutableSet *loadingUsers; 20 | NSMutableSet *loadedUsers; 21 | } 22 | 23 | + (HNTimeline *)timelineForSession:(HNSession *)session; 24 | 25 | @end 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /Classes/Follow Model/HNTimeline.m: -------------------------------------------------------------------------------- 1 | // 2 | // HNTimeline.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 8/21/11. 6 | // Copyright (c) 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "HNTimeline.h" 10 | #import "HNSession+Following.h" 11 | 12 | #ifdef ENABLE_TIMELINE 13 | 14 | @interface HNTimeline () 15 | 16 | @property (nonatomic, retain) HNSession *session; 17 | 18 | @end 19 | 20 | @implementation HNTimeline 21 | @synthesize session; 22 | 23 | + (HNTimeline *)timelineForSession:(HNSession *)session { 24 | HNTimeline *timeline = [self entryListWithIdentifier:kHNEntryListIdentifierTimeline]; 25 | [timeline setSession:session]; 26 | return timeline; 27 | } 28 | 29 | - (NSURL *)URL { 30 | return nil; 31 | } 32 | 33 | - (id)init { 34 | if ((self = [super init])) { 35 | loadingUsers = [[NSMutableSet alloc] init]; 36 | loadedUsers = [[NSMutableSet alloc] init]; 37 | } 38 | 39 | return self; 40 | } 41 | 42 | - (void)dealloc { 43 | [loadingUsers release]; 44 | [loadedUsers release]; 45 | [session release]; 46 | 47 | [super dealloc]; 48 | } 49 | 50 | - (void)userFinishedLoadingWithNotification:(NSNotification *)notification { 51 | HNEntryList *list = (HNEntryList *) [notification object]; 52 | [loadingUsers removeObject:list]; 53 | [loadedUsers addObject:list]; 54 | 55 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNObjectFinishedLoadingNotification object:list]; 56 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNObjectFailedLoadingNotification object:list]; 57 | 58 | if ([loadingUsers count] == 0) { 59 | NSMutableArray *comments = [NSMutableArray array]; 60 | 61 | for (HNEntryList *list in loadedUsers) { 62 | [comments addObjectsFromArray:[list entries]]; 63 | } 64 | 65 | [self setEntries:[comments sortedArrayUsingSelector:@selector(posted)]]; 66 | 67 | [loadingUsers removeAllObjects]; 68 | [loadedUsers removeAllObjects]; 69 | 70 | [self setIsLoaded:YES]; 71 | } 72 | } 73 | 74 | - (void)userFailedLoadingWithNotification:(NSNotification *)notification { 75 | HNEntryList *list = (HNEntryList *) [notification object]; 76 | [loadingUsers removeObject:list]; 77 | 78 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNObjectFinishedLoadingNotification object:list]; 79 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNObjectFailedLoadingNotification object:list]; 80 | 81 | [self cancelLoading]; 82 | 83 | [[NSNotificationCenter defaultCenter] postNotificationName:kHNObjectFailedLoadingNotification object:self]; 84 | } 85 | 86 | - (void)cancelLoading { 87 | for (HNEntryList *list in loadingUsers) { 88 | [list cancelLoading]; 89 | 90 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNObjectFinishedLoadingNotification object:list]; 91 | [[NSNotificationCenter defaultCenter] removeObserver:self name:kHNObjectFailedLoadingNotification object:list]; 92 | } 93 | 94 | [loadingUsers removeAllObjects]; 95 | [loadedUsers removeAllObjects]; 96 | } 97 | 98 | - (void)beginLoadingWithState:(HNObjectLoadingState)state_ { 99 | [self addLoadingState:state_]; 100 | 101 | if ([[session usersFollowed] count] == 0) { 102 | [self setIsLoaded:YES]; 103 | 104 | return; 105 | } 106 | 107 | for (HNUser *user_ in [session usersFollowed]) { 108 | HNEntryList *list = [HNEntryList entryListWithIdentifier:kHNEntryListIdentifierUserComments user:user_]; 109 | [loadingUsers addObject:list]; 110 | 111 | // In case this ends loading before this method finishes executing, have 112 | // this run on the next iteration of the runloop, just to be safe. 113 | [list beginLoading]; 114 | 115 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userFinishedLoadingWithNotification:) name:kHNObjectFinishedLoadingNotification object:list]; 116 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userFailedLoadingWithNotification:) name:kHNObjectFailedLoadingNotification object:list]; 117 | } 118 | } 119 | 120 | - (void)setSession:(HNSession *)session_ { 121 | [session autorelease]; 122 | session = [session_ retain]; 123 | } 124 | 125 | @end 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /Classes/HNKit/HNKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // HNKit.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/4/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | // This is the main header file for the HNKit "framework", 10 | // which has the singular purpose of scraping Startup News. 11 | // 12 | // HNKit depends on the files in the "XML" directory, as 13 | // well as few files in the "Categories" folder. 14 | 15 | #import "HNShared.h" 16 | 17 | // data 18 | #import "HNObject.h" 19 | #import "HNUser.h" 20 | #import "HNContainer.h" 21 | #import "HNEntry.h" 22 | #import "HNEntryList.h" 23 | 24 | // sessions 25 | #import "HNSession.h" 26 | #import "HNAnonymousSession.h" 27 | #import "HNSessionController.h" 28 | #import "HNSessionAuthenticator.h" 29 | #import "HNSubmission.h" 30 | 31 | // internal 32 | #import "HNAPIRequest.h" 33 | #import "HNAPIRequestParser.h" 34 | #import "HNAPISubmission.h" 35 | 36 | #ifdef HNKIT_RENDERING_ENABLED 37 | // rendering 38 | #import "HNObjectBodyRenderer.h" 39 | #endif 40 | -------------------------------------------------------------------------------- /Classes/HNKit/HNShared.h: -------------------------------------------------------------------------------- 1 | 2 | #import "NSURL+Parameters.h" 3 | #import "NSObject+PerformSelector.h" 4 | #import "NSString+RemoveSuffix.h" 5 | 6 | 7 | #define HNKIT_RENDERING_ENABLED 8 | 9 | 10 | #define kHNWebsiteHost @"news.dbanotes.net" 11 | #define kHNFAQURL [NSURL URLWithString:@"http://ycombinator.com/newsfaq.html"] 12 | #define kHNWebsiteURL [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/", kHNWebsiteHost]] 13 | 14 | 15 | #define kHNSearchBaseURL @"http://api.thriftdb.com/api.hnsearch.com/items/_search?%@" 16 | #define kHNSearchParamsInteresting @"limit=100&filter[fields][type][]=submission&weights[title]=8&weights[text]=2&weights[domain]=3&weights[username]=3&weights[type]=0&boosts[fields][points]=3&boosts[fields][num_comments]=3&boosts[functions][recip(ms(NOW,create_ts),3.16e-11,1,1)]=2.0&q=%@" 17 | #define kHNSearchParamsRecent @"sortby=create_ts%%20desc&limit=100&filter[fields][type][]=submission&weights[title]=8&weights[text]=2&weights[domain]=3&weights[username]=3&weights[type]=0&boosts[fields][points]=3&boosts[fields][num_comments]=3&boosts[functions][recip(ms(NOW,create_ts),3.16e-11,1,1)]=2.0&q=%@" 18 | typedef enum { 19 | kHNSearchTypeInteresting, 20 | kHNSearchTypeRecent 21 | } HNSearchType; 22 | 23 | 24 | typedef enum { 25 | kHNVoteDirectionDown, 26 | kHNVoteDirectionUp 27 | } HNVoteDirection; 28 | 29 | 30 | typedef NSString *HNSessionToken; 31 | 32 | typedef NSString *HNMoreToken; 33 | -------------------------------------------------------------------------------- /Classes/Instapaper/InstapaperAPI.h: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperAPI.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/10/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define kInstapaperAPIRootURL [NSURL URLWithString:@"https://www.instapaper.com/api/"] 12 | #define kInstapaperAPIAuthenticationURL [NSURL URLWithString:[[kInstapaperAPIRootURL absoluteString] stringByAppendingString:@"authenticate"]] 13 | #define kInstapaperAPIAddItemURL [NSURL URLWithString:[[kInstapaperAPIRootURL absoluteString] stringByAppendingString:@"add"]] 14 | -------------------------------------------------------------------------------- /Classes/Instapaper/InstapaperAuthenticator.h: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperAuthenticator.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/7/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "InstapaperAPI.h" 10 | 11 | @protocol InstapaperAuthenticatorDelegate; 12 | @interface InstapaperAuthenticator : NSObject { 13 | NSString *username; 14 | NSString *password; 15 | 16 | __weak id delegate; 17 | } 18 | 19 | @property (nonatomic, assign) id delegate; 20 | 21 | - (id)initWithUsername:(NSString *)username_ password:(NSString *)password_; 22 | - (void)beginAuthentication; 23 | 24 | @end 25 | 26 | @protocol InstapaperAuthenticatorDelegate 27 | @optional 28 | 29 | - (void)instapaperAuthenticatorDidSucceed:(InstapaperAuthenticator *)auth; 30 | - (void)instapaperAuthenticator:(InstapaperAuthenticator *)auth didFailWithError:(NSError *)error; 31 | 32 | @end -------------------------------------------------------------------------------- /Classes/Instapaper/InstapaperAuthenticator.m: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperAuthenticator.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/7/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "InstapaperAuthenticator.h" 10 | 11 | #import "UIApplication+ActivityIndicator.h" 12 | 13 | @implementation InstapaperAuthenticator 14 | @synthesize delegate; 15 | 16 | - (void)dealloc { 17 | [username release]; 18 | [password release]; 19 | [super dealloc]; 20 | } 21 | 22 | - (id)initWithUsername:(NSString *)username_ password:(NSString *)password_ { 23 | if ((self = [super init])) { 24 | username = [username_ copy]; 25 | password = [password_ copy]; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (void)succeed { 32 | if ([delegate respondsToSelector:@selector(instapaperAuthenticatorDidSucceed:)]) 33 | [delegate instapaperAuthenticatorDidSucceed:self]; 34 | } 35 | 36 | - (void)failWithError:(NSError *)error { 37 | if ([delegate respondsToSelector:@selector(instapaperAuthenticator:didFailWithError:)]) 38 | [delegate instapaperAuthenticator:self didFailWithError:error]; 39 | } 40 | 41 | - (void)failWithErrorText:(NSString *)text { 42 | NSError *error = [NSError errorWithDomain:@"instapaper" code:0 userInfo:[NSDictionary dictionaryWithObject:text forKey:NSLocalizedDescriptionKey]]; 43 | 44 | [self failWithError:error]; 45 | } 46 | 47 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 48 | [[UIApplication sharedApplication] releaseNetworkActivityIndicator]; 49 | 50 | [self failWithError:error]; 51 | } 52 | 53 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 54 | [[UIApplication sharedApplication] releaseNetworkActivityIndicator]; 55 | 56 | if ([response isKindOfClass:[NSHTTPURLResponse class]]) { 57 | NSInteger status = [(NSHTTPURLResponse *) response statusCode]; 58 | 59 | if (status == 201 || status == 200) { 60 | [self succeed]; 61 | } else if (status == 403) { 62 | [self failWithErrorText:@"Invalid username or password."]; 63 | } else if (status == 500) { 64 | [self failWithErrorText:@"Internal error, try again later."]; 65 | } else { 66 | [self failWithErrorText:@"Unknown error."]; 67 | } 68 | } else { 69 | [self failWithErrorText:@"Unknown error."]; 70 | } 71 | } 72 | 73 | - (void)beginAuthentication { 74 | NSString *query = @""; 75 | query = [query stringByAppendingFormat:@"username=%@&", [username stringByURLEncodingString]]; 76 | if (password != nil && [password length] > 0) query = [query stringByAppendingFormat:@"password=%@&", [password stringByURLEncodingString]]; 77 | 78 | NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:kInstapaperAPIAuthenticationURL] autorelease]; 79 | NSData *data = [query dataUsingEncoding:NSUTF8StringEncoding]; 80 | [request setHTTPMethod: @"POST"]; 81 | [request setHTTPBody:data]; 82 | [request setValue:[NSString stringWithFormat:@"%u", [data length]] forHTTPHeaderField:@"Content-Length"]; 83 | [request setValue:@"application/x-www-form-urlencoded; charset=UTF-8" forHTTPHeaderField: @"Content-Type"]; 84 | 85 | NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 86 | [connection start]; 87 | [connection autorelease]; 88 | 89 | [[UIApplication sharedApplication] retainNetworkActivityIndicator]; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /Classes/Instapaper/InstapaperRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperRequest.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/7/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "InstapaperAPI.h" 10 | 11 | @class InstapaperSession; 12 | @interface InstapaperRequest : NSObject { 13 | InstapaperSession *session; 14 | } 15 | 16 | @property (nonatomic, readonly) InstapaperSession *session; 17 | 18 | - (void)addItemWithURL:(NSURL *)url title:(NSString *)title selection:(NSString *)selection; 19 | - (void)addItemWithURL:(NSURL *)url title:(NSString *)title; 20 | - (void)addItemWithURL:(NSURL *)url; 21 | 22 | - (id)initWithSession:(InstapaperSession *)session_; 23 | 24 | @end 25 | 26 | #define kInstapaperRequestSucceededNotification @"instapaper-request-completed" 27 | #define kInstapaperRequestFailedNotification @"instapaper-request-failed" 28 | 29 | -------------------------------------------------------------------------------- /Classes/Instapaper/InstapaperRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperRequest.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/7/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "InstapaperRequest.h" 10 | #import "InstapaperSession.h" 11 | 12 | #import "UIApplication+ActivityIndicator.h" 13 | 14 | @implementation InstapaperRequest 15 | @synthesize session; 16 | 17 | - (void)dealloc { 18 | [session release]; 19 | 20 | [super dealloc]; 21 | } 22 | 23 | - (id)initWithSession:(InstapaperSession *)session_ { 24 | if ((self = [super init])) { 25 | session = [session_ retain]; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (void)succeed { 32 | [[NSNotificationCenter defaultCenter] postNotificationName:kInstapaperRequestSucceededNotification object:self]; 33 | } 34 | 35 | - (void)failWithError:(NSError *)error { 36 | [[NSNotificationCenter defaultCenter] postNotificationName:kInstapaperRequestFailedNotification object:self userInfo:[NSDictionary dictionaryWithObject:error forKey:@"error"]]; 37 | } 38 | 39 | - (void)failWithErrorText:(NSString *)text { 40 | NSError *error = [NSError errorWithDomain:@"instapaper" code:0 userInfo:[NSDictionary dictionaryWithObject:text forKey:NSLocalizedDescriptionKey]]; 41 | 42 | [self failWithError:error]; 43 | } 44 | 45 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 46 | [[UIApplication sharedApplication] releaseNetworkActivityIndicator]; 47 | 48 | [self failWithError:error]; 49 | } 50 | 51 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection { 52 | [[UIApplication sharedApplication] releaseNetworkActivityIndicator]; 53 | } 54 | 55 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 56 | if ([response isKindOfClass:[NSHTTPURLResponse class]]) { 57 | NSInteger status = [(NSHTTPURLResponse *) response statusCode]; 58 | if (status == 403) [self failWithErrorText:@"Invalid username or password."]; 59 | if (status == 500) [self failWithErrorText:@"Internal error, try again later."]; 60 | if (status == 201) [self succeed]; 61 | } else { 62 | [self failWithErrorText:@"Unknown error."]; 63 | } 64 | } 65 | 66 | - (void)addItemWithURL:(NSURL *)url title:(NSString *)title selection:(NSString *)selection { 67 | if (session == nil || ![session canAddItems]) { 68 | [self failWithErrorText:@"You are not signed into Instapaper."]; 69 | return; 70 | } 71 | 72 | NSString *password = [session password]; 73 | NSString *username = [session username]; 74 | 75 | NSString *query = @""; 76 | query = [query stringByAppendingFormat:@"username=%@&", [username stringByURLEncodingString]]; 77 | if (password != nil && [password length] > 0) query = [query stringByAppendingFormat:@"password=%@&", [password stringByURLEncodingString]]; 78 | if (title != nil && [title length] > 0) query = [query stringByAppendingFormat:@"title=%@&", [title stringByURLEncodingString]]; 79 | if (selection != nil && [selection length] > 0) query = [query stringByAppendingFormat:@"&title=%@&", [selection stringByURLEncodingString]]; 80 | query = [query stringByAppendingFormat:@"url=%@&", [[url absoluteString] stringByURLEncodingString]]; 81 | 82 | NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:kInstapaperAPIAddItemURL] autorelease]; 83 | NSData *data = [query dataUsingEncoding:NSUTF8StringEncoding]; 84 | [request setHTTPMethod: @"POST"]; 85 | [request setHTTPBody:data]; 86 | [request setValue:[NSString stringWithFormat:@"%u", [data length]] forHTTPHeaderField:@"Content-Length"]; 87 | [request setValue:@"application/x-www-form-urlencoded; charset=UTF-8" forHTTPHeaderField: @"Content-Type"]; 88 | 89 | NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 90 | [connection start]; 91 | [connection autorelease]; 92 | 93 | [[UIApplication sharedApplication] retainNetworkActivityIndicator]; 94 | } 95 | 96 | - (void)addItemWithURL:(NSURL *)url title:(NSString *)title { 97 | [self addItemWithURL:url title:title selection:nil]; 98 | } 99 | 100 | - (void)addItemWithURL:(NSURL *)url { 101 | [self addItemWithURL:url title:nil selection:nil]; 102 | } 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /Classes/Instapaper/InstapaperSession.h: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperSession.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/10/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "InstapaperAPI.h" 10 | 11 | @interface InstapaperSession : NSObject { 12 | NSString *username; 13 | NSString *password; 14 | } 15 | 16 | + (id)currentSession; 17 | + (void)setCurrentSession:(id)session; 18 | + (void)logoutIfNecessary; 19 | 20 | @property (nonatomic, copy) NSString *username; 21 | @property (nonatomic, copy) NSString *password; 22 | 23 | - (BOOL)canAddItems; 24 | 25 | @end 26 | 27 | -------------------------------------------------------------------------------- /Classes/Instapaper/InstapaperSession.m: -------------------------------------------------------------------------------- 1 | // 2 | // InstapaperSession.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/10/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "InstapaperSession.h" 10 | 11 | @implementation InstapaperSession 12 | @synthesize username, password; 13 | 14 | static id currentSession = nil; 15 | 16 | + (id)currentSession { 17 | return currentSession; 18 | } 19 | 20 | + (void)setCurrentSession:(id)session { 21 | [currentSession autorelease]; 22 | currentSession = [session retain]; 23 | 24 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 25 | if (session != nil) { 26 | [defaults setObject:[session username] forKey:@"instapaper-username"]; 27 | [defaults setObject:[session password] forKey:@"instapaper-password"]; 28 | } else { 29 | [defaults removeObjectForKey:@"instapaper-username"]; 30 | [defaults removeObjectForKey:@"instapaper-password"]; 31 | } 32 | } 33 | 34 | + (void)logoutIfNecessary { 35 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 36 | BOOL logout = [[defaults objectForKey:@"instapaper-logout"] boolValue]; 37 | 38 | if (logout) { 39 | [defaults setObject:[NSNumber numberWithBool:NO] forKey:@"instapaper-logout"]; 40 | [self setCurrentSession:nil]; 41 | } 42 | } 43 | 44 | + (void)initialize { 45 | // XXX: use the keychain! 46 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 47 | NSString *username = [defaults objectForKey:@"instapaper-username"]; 48 | NSString *password = [defaults objectForKey:@"instapaper-password"]; 49 | 50 | if (username != nil && password != nil && [username length] > 0) { 51 | InstapaperSession *session = [[InstapaperSession alloc] init]; 52 | [session setUsername:username]; 53 | [session setPassword:password]; 54 | [self setCurrentSession:[session autorelease]]; 55 | } 56 | 57 | [self logoutIfNecessary]; 58 | } 59 | 60 | - (BOOL)canAddItems { 61 | return (username != nil && [username length] > 0); 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Classes/PingController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PingController.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 1/19/13. 6 | // 7 | // 8 | 9 | @protocol PingControllerDelegate; 10 | 11 | @interface PingController : NSObject { 12 | NSMutableData *received; 13 | NSURL *moreInfoURL; 14 | BOOL locked; 15 | 16 | id delegate; 17 | } 18 | 19 | @property (nonatomic, assign) id delegate; 20 | @property (nonatomic, assign) BOOL locked; 21 | 22 | - (void)ping; 23 | 24 | @end 25 | 26 | @protocol PingControllerDelegate 27 | @optional 28 | 29 | - (void)pingController:(PingController *)pingController failedWithError:(NSError *)error; 30 | - (void)pingControllerCompletedWithoutAction:(PingController *)pingController; 31 | - (void)pingController:(PingController *)pingController completedAcceptingURL:(NSURL *)url; 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'newsyc' target in the 'newsyc' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This is probably not going to go well. Might want to try iOS 5.0 or later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #import 15 | 16 | // Use -shouldAutorotateToInterfaceOrientation: for iOS 5 and -supportedInterfaceOrientations for iOS 6 17 | #define AUTOROTATION_FOR_PAD_ONLY \ 18 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { \ 19 | return ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); \ 20 | } \ 21 | - (NSUInteger)supportedInterfaceOrientations { \ 22 | return ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad ? UIInterfaceOrientationMaskAll : UIInterfaceOrientationMaskPortrait); \ 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /Classes/UMAnalytics_Sdk_3.1.9/MobClickSocialAnalytics.h: -------------------------------------------------------------------------------- 1 | // 2 | // MobClickSocialAnalytics.h 3 | // SocialSDK 4 | // 5 | // Created by yeahugo on 13-3-4. 6 | // Copyright (c) 2013年 Umeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NSString * MobClickSocialTypeString; 12 | 13 | extern MobClickSocialTypeString const MobClickSocialTypeSina; //新浪微博 14 | extern MobClickSocialTypeString const MobClickSocialTypeTencent; //腾讯微博 15 | extern MobClickSocialTypeString const MobClickSocialTypeRenren; //人人网 16 | extern MobClickSocialTypeString const MobClickSocialTypeQzone; //Qzone 17 | extern MobClickSocialTypeString const MobClickSocialTypeRenren; //人人网 18 | extern MobClickSocialTypeString const MobClickSocialTypeDouban; //douban 19 | extern MobClickSocialTypeString const MobClickSocialTypeWxsesion; //微信好友分享 20 | extern MobClickSocialTypeString const MobClickSocialTypeWxtimeline; //微信朋友圈 21 | extern MobClickSocialTypeString const MobClickSocialTypeHuaban; //花瓣 22 | extern MobClickSocialTypeString const MobClickSocialTypeKaixin; //开心 23 | extern MobClickSocialTypeString const MobClickSocialTypeFacebook; //facebook 24 | extern MobClickSocialTypeString const MobClickSocialTypeTwitter; //twitter 25 | extern MobClickSocialTypeString const MobClickSocialTypeInstagram; //instagram 26 | extern MobClickSocialTypeString const MobClickSocialTypeFlickr; //flickr 27 | extern MobClickSocialTypeString const MobClickSocialTypeQQ; //qq 28 | extern MobClickSocialTypeString const MobClickSocialTypeWxfavorite; //微信收藏 29 | extern MobClickSocialTypeString const MobClickSocialTypeLwsession; //来往 30 | extern MobClickSocialTypeString const MobClickSocialTypeLwtimeline; //来往动态 31 | extern MobClickSocialTypeString const MobClickSocialTypeYxsession; //易信 32 | extern MobClickSocialTypeString const MobClickSocialTypeYxtimeline; //易信朋友圈 33 | 34 | 35 | /** 36 | 微博类,发送微博之后在回调方法初始化此对象 37 | 38 | */ 39 | @interface MobClickSocialWeibo : NSObject 40 | 41 | 42 | /** 43 | 微博平台类型,使用上面定义的几种常量字符串 44 | */ 45 | @property (nonatomic, copy) NSString *platformType; 46 | 47 | /** 48 | 微博id 49 | */ 50 | @property (nonatomic, copy) NSString *weiboId; 51 | 52 | /** 53 | 用户在微博平台的id 54 | */ 55 | @property (nonatomic, copy) NSString *userId; 56 | 57 | /** 58 | 微博平台的自定义字段,例如定义{‘gender’:0,’name’:’xxx’} 59 | */ 60 | @property (nonatomic, strong) NSDictionary *param; 61 | 62 | 63 | /** 64 | 初始化方法,在发送微博结束的回调方法使用此初始化方法 65 | 66 | @param platformType 微博平台类型 67 | @param weiboId 微博id,可以设置为nil 68 | @param userId 用户id 69 | @param param 微博平台自定义字段,可以设置为nil 70 | 71 | @return 微博对象 72 | */ 73 | -(id)initWithPlatformType:(MobClickSocialTypeString)platformType weiboId:(NSString *)weiboId usid:(NSString *)usid param:(NSDictionary *)param; 74 | 75 | @end 76 | 77 | /** 78 | 发送统计完成的block对象 79 | */ 80 | typedef void (^MobClickSocialAnalyticsCompletion)(NSDictionary * response, NSError *error); 81 | 82 | 83 | /** 84 | 负责统计微博类。 85 | 分享微博完成之后需要先构造`MobClickSocialWeibo`组成微博数组,然后再用类方法发送微博数组 86 | 87 | ``` 88 | +(void)postWeiboCounts:(NSArray *)weibos appKey:(NSString *)appKey topic:(NSString *)topic completion:(MobClickSocialAnalyticsCompletion)completion; 89 | ``` 90 | 91 | 例如 92 | 93 | 94 | MobClickSocialWeibo *tencentWeibo = [[MobClickSocialWeibo alloc] initWithPlatformType:UMSocialTypeTencent weiboId:nil userId:@"tencent123" param:@{@"gender":@"1"}]; 95 | [MobClickSocialAnalytics postWeibos:@[tencentWeibo] appKey:@"507fcab25270157b37000010" topic:@"test" completion:^(NSDictionary *result, NSError *error) { 96 | NSLog(@"result is %@", result); 97 | }]; 98 | 99 | */ 100 | 101 | @interface MobClickSocialAnalytics : NSObject 102 | /** 103 | 发送统计微博 104 | 105 | @param weibos UMSocialWeibo对象组成的数组 106 | @param appKey 友盟appkey 107 | @param topic 话题,可选,可以设置为nil 108 | @parma completion 发送完成的事件处理block 109 | 110 | */ 111 | +(void)postWeiboCounts:(NSArray *)weibos appKey:(NSString *)appKey topic:(NSString *)topic completion:(MobClickSocialAnalyticsCompletion)completion; 112 | @end 113 | -------------------------------------------------------------------------------- /Classes/Views/ActivityIndicatorItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // ActivityIndicatorItem.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/16/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "BarButtonItem.h" 10 | 11 | #define kActivityIndicatorItemStandardSize CGSizeMake(20, 20) 12 | 13 | @interface ActivityIndicatorItem : BarButtonItem { 14 | UIActivityIndicatorView *spinner; 15 | UIView *container; 16 | } 17 | 18 | @property (nonatomic, readonly) UIActivityIndicatorView *spinner; 19 | 20 | - (id)initWithSize:(CGSize)size; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Classes/Views/ActivityIndicatorItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // ActivityIndicatorItem.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/16/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "ActivityIndicatorItem.h" 10 | 11 | @implementation ActivityIndicatorItem 12 | @synthesize spinner; 13 | 14 | // XXX: this cannot be named -init because -init is called by UIKit itself inside -initWithCustomView: 15 | - (id)initWithSize:(CGSize)size { 16 | UIView *container_ = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)] autorelease]; 17 | 18 | if ((self = [super initWithCustomView:container_])) { 19 | spinner = [[UIActivityIndicatorView alloc] init]; 20 | [spinner setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhite]; 21 | [spinner setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin]; 22 | [spinner startAnimating]; 23 | [spinner sizeToFit]; 24 | 25 | container = [container_ retain]; 26 | [container addSubview:spinner]; 27 | } 28 | 29 | return self; 30 | } 31 | 32 | - (void)dealloc { 33 | [container release]; 34 | [spinner release]; 35 | 36 | [super dealloc]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Classes/Views/BarButtonItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // BarButtonItem.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/24/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | @interface BarButtonItem : UIBarButtonItem { 10 | UIView *buttonView; 11 | 12 | id realTarget; 13 | SEL realAction; 14 | } 15 | 16 | @property (nonatomic, readonly) UIView *buttonView; 17 | 18 | @end 19 | 20 | @interface UIPopoverController (BarButtonItem) 21 | 22 | - (void)presentPopoverFromBarButtonItemInWindow:(BarButtonItem *)item permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated; 23 | 24 | @end 25 | 26 | @interface UIActionSheet (BarButtonItem) 27 | 28 | - (void)showFromBarButtonItemInWindow:(BarButtonItem *)item animated:(BOOL)animated; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Classes/Views/BarButtonItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // BarButtonItem.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/24/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "BarButtonItem.h" 10 | 11 | @implementation BarButtonItem 12 | @synthesize buttonView; 13 | 14 | - (void)saveRealTarget:(id)target realAction:(SEL)action { 15 | realAction = action; 16 | realTarget = target; 17 | } 18 | 19 | - (id)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(id)target action:(SEL)action { 20 | if ((self = [super initWithBarButtonSystemItem:systemItem target:self action:@selector(itemSelected:event:)])) { 21 | [self saveRealTarget:target realAction:action]; 22 | } 23 | 24 | return self; 25 | } 26 | 27 | - (id)initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action { 28 | if ((self = [super initWithImage:image style:style target:self action:@selector(itemSelected:event:)])) { 29 | [self saveRealTarget:target realAction:action]; 30 | } 31 | 32 | return self; 33 | } 34 | 35 | - (id)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action { 36 | if ((self = [super initWithTitle:title style:style target:self action:@selector(itemSelected:event:)])) { 37 | [self saveRealTarget:target realAction:action]; 38 | } 39 | 40 | return self; 41 | } 42 | 43 | - (id)initWithImage:(UIImage *)image landscapeImagePhone:(UIImage *)landscapeImagePhone style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action { 44 | if ((self = [super initWithImage:image landscapeImagePhone:landscapeImagePhone style:style target:self action:@selector(itemSelected:event:)])) { 45 | [self saveRealTarget:target realAction:action]; 46 | } 47 | 48 | return self; 49 | } 50 | 51 | - (void)itemSelected:(UIBarButtonItem *)item event:(UIEvent *)event { 52 | buttonView = [[[[event allTouches] anyObject] view] retain]; 53 | 54 | if ([realTarget respondsToSelector:realAction]) { 55 | NSMethodSignature *signature = [realTarget methodSignatureForSelector:realAction]; 56 | NSInteger args = [signature numberOfArguments] - 2; // remove self, _cmd 57 | 58 | if (args == 0) { 59 | [realTarget performSelector:realAction]; 60 | } else if (args == 1) { 61 | [realTarget performSelector:realAction withObject:item]; 62 | } else if (args == 2) { 63 | [realTarget performSelector:realAction withObject:item withObject:event]; 64 | } 65 | } 66 | } 67 | 68 | - (void)dealloc { 69 | [buttonView release]; 70 | 71 | [super dealloc]; 72 | } 73 | 74 | @end 75 | 76 | @implementation UIPopoverController (BarButtonItem) 77 | 78 | - (void)presentPopoverFromBarButtonItemInWindow:(BarButtonItem *)item permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated { 79 | UIView *itemView = [item buttonView]; 80 | UIWindow *window = [itemView window]; 81 | 82 | UIView *superview = [itemView superview]; 83 | CGRect windowRect = [superview convertRect:[itemView frame] toView:nil]; 84 | 85 | [self presentPopoverFromRect:windowRect inView:window permittedArrowDirections:arrowDirections animated:animated]; 86 | } 87 | 88 | @end 89 | 90 | 91 | @implementation UIActionSheet (BarButtonItem) 92 | 93 | - (void)showFromBarButtonItemInWindow:(BarButtonItem *)item animated:(BOOL)animated { 94 | UIView *itemView = [item buttonView]; 95 | UIWindow *window = [itemView window]; 96 | 97 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 98 | UIView *superview = [itemView superview]; 99 | 100 | CGRect windowRect = [superview convertRect:[itemView frame] toView:nil]; 101 | 102 | // Pretend to be wider, so the arrow is always pointing up or down 103 | if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) { 104 | windowRect = CGRectInset(windowRect, -[[UIScreen mainScreen] bounds].size.width, 0); 105 | } else { 106 | windowRect = CGRectInset(windowRect, 0, -[[UIScreen mainScreen] bounds].size.height); 107 | } 108 | 109 | [self showFromRect:windowRect inView:window animated:YES]; 110 | } else { 111 | [self showInView:window]; 112 | } 113 | } 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /Classes/Views/BodyTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BodyTextView.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 1/15/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @protocol BodyTextViewDelegate; 12 | 13 | @interface BodyTextView : UIView { 14 | HNObjectBodyRenderer *renderer; 15 | __weak id delegate; 16 | 17 | UILongPressGestureRecognizer *linkLongPressRecognizer; 18 | 19 | UIView *bodyTextRenderView; 20 | NSSet *highlightedRects; 21 | } 22 | 23 | @property (nonatomic, retain) HNObjectBodyRenderer *renderer; 24 | @property (nonatomic, assign) id delegate; 25 | 26 | - (BOOL)linkHighlighted; 27 | 28 | - (void)drawContentView:(CGRect)rect; 29 | 30 | @end 31 | 32 | @protocol BodyTextViewDelegate 33 | @optional 34 | 35 | - (void)bodyTextView:(BodyTextView *)header selectedURL:(NSURL *)url; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Classes/Views/DetailsHeaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailsHeaderView.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/6/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "BodyTextView.h" 10 | 11 | @protocol DetailsHeaderViewDelegate; 12 | 13 | @class HNEntry; 14 | @interface DetailsHeaderView : UIView { 15 | HNEntry *entry; 16 | __weak id delegate; 17 | 18 | UIView *detailsHeaderContainer; 19 | UIView *containerContainer; 20 | BodyTextView *bodyTextView; 21 | 22 | BOOL highlighted; 23 | BOOL navigationCancelled; 24 | } 25 | 26 | @property (nonatomic, assign) id delegate; 27 | @property (nonatomic, retain) HNEntry *entry; 28 | @property (nonatomic, assign, getter = isHighlighted) BOOL highlighted; 29 | 30 | - (id)initWithEntry:(HNEntry *)entry_ widthWidth:(CGFloat)width; 31 | - (CGFloat)suggestedHeightWithWidth:(CGFloat)width; 32 | + (CGSize)offsets; 33 | 34 | @end 35 | 36 | @protocol DetailsHeaderViewDelegate 37 | @optional 38 | 39 | - (void)detailsHeaderView:(DetailsHeaderView *)header selectedURL:(NSURL *)url; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Classes/Views/EmptyView.h: -------------------------------------------------------------------------------- 1 | // 2 | // EmptyView.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 9/28/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface EmptyView : UIView { 12 | UILabel *emptyLabel; 13 | } 14 | 15 | @property (nonatomic, copy) NSString *text; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Views/EmptyView.m: -------------------------------------------------------------------------------- 1 | // 2 | // EmptyView.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 9/28/13. 6 | // 7 | // 8 | 9 | #import "EmptyView.h" 10 | 11 | @implementation EmptyView 12 | 13 | - (id)initWithFrame:(CGRect)frame { 14 | if ((self = [super initWithFrame:frame])) { 15 | emptyLabel = [[UILabel alloc] initWithFrame:[self bounds]]; 16 | [emptyLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 17 | [emptyLabel setBackgroundColor:[UIColor clearColor]]; 18 | [emptyLabel setTextAlignment:NSTextAlignmentCenter]; 19 | 20 | if ([emptyLabel respondsToSelector:@selector(tintColor)]) { 21 | [emptyLabel setFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:22.0]]; 22 | [emptyLabel setTextColor:[UIColor lightGrayColor]]; 23 | } else { 24 | [emptyLabel setFont:[UIFont systemFontOfSize:17.0f]]; 25 | [emptyLabel setTextColor:[UIColor grayColor]]; 26 | } 27 | 28 | [self addSubview:emptyLabel]; 29 | } 30 | 31 | return self; 32 | } 33 | 34 | - (void)setText:(NSString *)text { 35 | emptyLabel.text = text; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Classes/Views/EntryActionsView.h: -------------------------------------------------------------------------------- 1 | // 2 | // EntryActionsView.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/6/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "ActivityIndicatorItem.h" 10 | #import "BarButtonItem.h" 11 | #import "OrangeToolbar.h" 12 | 13 | typedef enum { 14 | kEntryActionsViewItemUpvote, 15 | kEntryActionsViewItemReply, 16 | kEntryActionsViewItemFlag, 17 | kEntryActionsViewItemDownvote, 18 | kEntryActionsViewItemActions 19 | } EntryActionsViewItem; 20 | 21 | typedef enum { 22 | kEntryActionsViewStyleDefault, 23 | kEntryActionsViewStyleOrange, 24 | kEntryActionsViewStyleTransparentLight, 25 | kEntryActionsViewStyleTransparentDark, 26 | kEntryActionsViewStyleLight 27 | } EntryActionsViewStyle; 28 | 29 | @protocol EntryActionsViewDelegate; 30 | @class HNEntry; 31 | @interface EntryActionsView : OrangeToolbar { 32 | HNEntry *entry; 33 | __weak id delegate; 34 | 35 | NSInteger upvoteLoading; 36 | BOOL upvoteDisabled; 37 | NSInteger replyLoading; 38 | BOOL replyDisabled; 39 | NSInteger flagLoading; 40 | BOOL flagDisabled; 41 | NSInteger downvoteLoading; 42 | BOOL downvoteDisabled; 43 | NSInteger actionsLoading; 44 | BOOL actionsDisabled; 45 | 46 | EntryActionsViewStyle style; 47 | UIActivityIndicatorViewStyle indicatorStyle; 48 | } 49 | 50 | @property (nonatomic, retain) HNEntry *entry; 51 | @property (nonatomic, assign) id delegate; 52 | @property (nonatomic, assign) EntryActionsViewStyle style; 53 | 54 | - (void)setEnabled:(BOOL)enabled forItem:(EntryActionsViewItem)item; 55 | - (BOOL)itemIsEnabled:(EntryActionsViewItem)item; 56 | - (void)beginLoadingItem:(EntryActionsViewItem)item; 57 | - (void)stopLoadingItem:(EntryActionsViewItem)item; 58 | - (BOOL)itemIsLoading:(EntryActionsViewItem)item; 59 | - (BarButtonItem *)barButtonItemForItem:(EntryActionsViewItem)item; 60 | 61 | @end 62 | 63 | @protocol EntryActionsViewDelegate 64 | 65 | - (void)entryActionsView:(EntryActionsView *)eav didSelectItem:(EntryActionsViewItem)item; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Classes/Views/ForceClearNavigationBar.h: -------------------------------------------------------------------------------- 1 | // 2 | // ForceClearNavigationBar.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 11/9/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface ForceClearNavigationBar : UINavigationBar 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/Views/ForceClearNavigationBar.m: -------------------------------------------------------------------------------- 1 | // 2 | // ForceClearNavigationBar.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 11/9/13. 6 | // 7 | // 8 | 9 | #import "ForceClearNavigationBar.h" 10 | 11 | @implementation ForceClearNavigationBar 12 | 13 | - (id)initWithFrame:(CGRect)frame 14 | { 15 | if ((self = [super initWithFrame:frame])) { 16 | // Have to use 0.001 or UINavigationController thinks its hidden. 17 | [self setAlpha:0.001]; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | - (void)setAlpha:(CGFloat)alpha 24 | { 25 | // Have to use 0.001 or UINavigationController thinks its hidden. 26 | [super setAlpha:0.001]; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Classes/Views/LoadMoreButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoadMoreView.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 9/5/11. 6 | // Copyright (c) 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "LoadingIndicatorView.h" 10 | 11 | @interface LoadMoreButton : UIButton { 12 | LoadingIndicatorView *indicatorView; 13 | UILabel *moreLabel; 14 | } 15 | 16 | - (void)startLoading; 17 | - (void)stopLoading; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Views/LoadMoreButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoadMoreView.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 9/5/11. 6 | // Copyright (c) 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "LoadMoreButton.h" 10 | 11 | @implementation LoadMoreButton 12 | 13 | - (id)initWithFrame:(CGRect)frame { 14 | if ((self = [super initWithFrame:frame])) { 15 | indicatorView = [[LoadingIndicatorView alloc] initWithFrame:[self bounds]]; 16 | [indicatorView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 17 | [indicatorView setHidden:YES]; 18 | [indicatorView setBackgroundColor:[UIColor whiteColor]]; 19 | [self addSubview:indicatorView]; 20 | 21 | moreLabel = [[UILabel alloc] initWithFrame:[self bounds]]; 22 | [moreLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 23 | [moreLabel setText:@"Load More..."]; 24 | [moreLabel setTextAlignment:NSTextAlignmentCenter]; 25 | [moreLabel setTextColor:[UIColor grayColor]]; 26 | [moreLabel setFont:[UIFont systemFontOfSize:17.0f]]; 27 | [moreLabel setBackgroundColor:[UIColor whiteColor]]; 28 | [self addSubview:moreLabel]; 29 | } 30 | 31 | return self; 32 | } 33 | 34 | - (void)startLoading { 35 | [indicatorView setHidden:NO]; 36 | [moreLabel setHidden:YES]; 37 | } 38 | 39 | - (void)stopLoading { 40 | [indicatorView setHidden:YES]; 41 | [moreLabel setHidden:NO]; 42 | } 43 | 44 | - (void)dealloc { 45 | [indicatorView release]; 46 | [moreLabel release]; 47 | 48 | [super dealloc]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Classes/Views/LoadingIndicatorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoadingIndicatorView.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/4/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | @interface LoadingIndicatorView : UIView { 10 | UIActivityIndicatorView *spinner_; 11 | UILabel *label_; 12 | UIView *container_; 13 | } 14 | 15 | @property (readonly, nonatomic) UILabel *label; 16 | @property (readonly, nonatomic) UIActivityIndicatorView *activityIndicatorView; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Views/LoadingIndicatorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoadingIndicatorView.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/4/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "LoadingIndicatorView.h" 10 | 11 | @implementation LoadingIndicatorView 12 | 13 | - (id)initWithFrame:(CGRect)frame { 14 | if ((self = [super initWithFrame:frame]) != nil) { 15 | container_ = [[UIView alloc] init]; 16 | [container_ setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin]; 17 | 18 | spinner_ = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 19 | [spinner_ startAnimating]; 20 | [container_ addSubview:spinner_]; 21 | 22 | label_ = [[UILabel alloc] init]; 23 | [label_ setFont:[UIFont systemFontOfSize:17.0f]]; 24 | [label_ setBackgroundColor:[UIColor clearColor]]; 25 | [label_ setTextColor:[UIColor grayColor]]; 26 | // [label_ setShadowColor:[UIColor whiteColor]]; 27 | // [label_ setShadowOffset:CGSizeMake(0, 1)]; 28 | [label_ setText:@"Loading..."]; 29 | [container_ addSubview:label_]; 30 | 31 | CGSize viewsize = frame.size; 32 | CGSize spinnersize = [spinner_ bounds].size; 33 | CGSize textsize = [[label_ text] sizeWithFont:[label_ font]]; 34 | float bothwidth = spinnersize.width + textsize.width + 5.0f; 35 | 36 | CGRect containrect = { 37 | CGPointMake(floorf((viewsize.width / 2) - (bothwidth / 2)), floorf((viewsize.height / 2) - (spinnersize.height / 2))), 38 | CGSizeMake(bothwidth, spinnersize.height) 39 | }; 40 | CGRect textrect = { 41 | CGPointMake(spinnersize.width + 5.0f, floorf((spinnersize.height / 2) - (textsize.height / 2))), 42 | textsize 43 | }; 44 | CGRect spinrect = { 45 | CGPointZero, 46 | spinnersize 47 | }; 48 | 49 | [container_ setFrame:containrect]; 50 | [spinner_ setFrame:spinrect]; 51 | [label_ setFrame:textrect]; 52 | [self addSubview:container_]; 53 | } return self; 54 | } 55 | 56 | - (void)dealloc { 57 | [spinner_ release]; 58 | [label_ release]; 59 | [container_ release]; 60 | 61 | [super dealloc]; 62 | } 63 | 64 | - (UILabel *)label { 65 | return label_; 66 | } 67 | 68 | - (UIActivityIndicatorView *)activityIndicatorView { 69 | return spinner_; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /Classes/Views/OrangeBarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // OrangeBarView.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 9/28/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface OrangeBarView : UIView 12 | 13 | + (UIColor *)barOrangeColor; 14 | 15 | - (void)layoutInsideBar:(UIView *)barView; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Views/OrangeBarView.m: -------------------------------------------------------------------------------- 1 | // 2 | // OrangeBarView.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 9/28/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | #import "OrangeBarView.h" 12 | #import "UIColor+Orange.h" 13 | 14 | 15 | 16 | @implementation OrangeBarView 17 | 18 | + (void)load { 19 | // Revert iOS 7.0.3+ back to the blurring style from iOS 7.0.2 and below. 20 | Class _UIBackdropViewSettingsColored = NSClassFromString(@"_UIBackdropViewSettingsColored"); 21 | Class _UIBackdropViewSettingsUltraColored = NSClassFromString(@"_UIBackdropViewSettingsUltraColored"); 22 | 23 | if (_UIBackdropViewSettingsColored != nil && _UIBackdropViewSettingsUltraColored != nil) { 24 | SEL setDefaultValues = @selector(setDefaultValues); 25 | 26 | Method coloredMethod = class_getInstanceMethod(_UIBackdropViewSettingsColored, setDefaultValues); 27 | Method ultraColoredMethod = class_getInstanceMethod(_UIBackdropViewSettingsUltraColored, setDefaultValues); 28 | 29 | if (coloredMethod != NULL && ultraColoredMethod != NULL) { 30 | method_setImplementation(ultraColoredMethod, method_getImplementation(coloredMethod)); 31 | } 32 | } 33 | } 34 | 35 | + (UIColor *)barOrangeColor { 36 | return [UIColor mainOrangeColor]; 37 | } 38 | 39 | - (id)initWithFrame:(CGRect)frame { 40 | if ((self = [super initWithFrame:frame])) { 41 | [self setUserInteractionEnabled:NO]; 42 | 43 | [self setAlpha:0.3]; 44 | [self setBackgroundColor:[UIColor mainOrangeColor]]; 45 | } 46 | 47 | return self; 48 | } 49 | 50 | - (void)layoutInsideBar:(UIView *)barView { 51 | // Hack to deepen the bar's color. 52 | self.frame = [[[[barView layer] sublayers] objectAtIndex:0] frame]; 53 | [[barView layer] insertSublayer:[self layer] atIndex:1]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Classes/Views/OrangeNavigationBar.h: -------------------------------------------------------------------------------- 1 | // 2 | // OrangeNavigationBar.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 9/28/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @class OrangeBarView; 12 | 13 | @interface OrangeNavigationBar : UINavigationBar { 14 | OrangeBarView *barView; 15 | 16 | NSTimer *_partyTimer; 17 | float partyHue; 18 | } 19 | 20 | @property (nonatomic, assign) BOOL orange; 21 | 22 | @property (nonatomic, assign) BOOL shouldParty; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/Views/OrangeNavigationBar.m: -------------------------------------------------------------------------------- 1 | // 2 | // OrangeNavigationBar.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 9/28/13. 6 | // 7 | // 8 | 9 | #import "UIColor+Orange.h" 10 | #import "OrangeBarView.h" 11 | #import "OrangeNavigationBar.h" 12 | 13 | @implementation OrangeNavigationBar 14 | @synthesize orange; 15 | 16 | - (id)initWithFrame:(CGRect)frame { 17 | if ((self = [super initWithFrame:frame])) { 18 | if ([self respondsToSelector:@selector(barTintColor)]) { 19 | barView = [[OrangeBarView alloc] init]; 20 | [barView setHidden:YES]; 21 | 22 | UITapGestureRecognizer *tripleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self 23 | action:@selector(startTheParty:)]; 24 | tripleTapGestureRecognizer.numberOfTapsRequired = 3; 25 | [self addGestureRecognizer:tripleTapGestureRecognizer]; 26 | 27 | self.shouldParty = [[NSUserDefaults standardUserDefaults] boolForKey:@"PartyStarted"]; 28 | } 29 | } 30 | 31 | return self; 32 | } 33 | 34 | - (void)layoutSubviews { 35 | [super layoutSubviews]; 36 | 37 | [barView layoutInsideBar:self]; 38 | } 39 | 40 | - (void)dealloc { 41 | [barView release]; 42 | 43 | [super dealloc]; 44 | } 45 | 46 | - (void)setOrange:(BOOL)orange_ { 47 | orange = orange_; 48 | 49 | if (orange) { 50 | if ([self respondsToSelector:@selector(setBarTintColor:)]) { 51 | [self setBarTintColor:[OrangeBarView barOrangeColor]]; 52 | [self setTintColor:[UIColor whiteColor]]; 53 | 54 | NSDictionary *titleTextAttributes = [NSDictionary dictionaryWithObject:[UIColor whiteColor] forKey:NSForegroundColorAttributeName]; 55 | [self setTitleTextAttributes:titleTextAttributes]; 56 | } else { 57 | [self setTintColor:[UIColor mainOrangeColor]]; 58 | } 59 | } else { 60 | if ([self respondsToSelector:@selector(setBarTintColor:)]) { 61 | [self setBarTintColor:nil]; 62 | } 63 | 64 | [self setTintColor:nil]; 65 | [self setTitleTextAttributes:nil]; 66 | } 67 | 68 | [barView setHidden:!orange]; 69 | } 70 | 71 | #pragma mark - 72 | #pragma mark Party Mode 73 | 74 | - (void)setPartyTimer:(NSTimer *)partyTimer { 75 | if (partyTimer == _partyTimer) 76 | return; 77 | 78 | [_partyTimer invalidate]; 79 | _partyTimer = partyTimer; 80 | } 81 | 82 | - (void)startTheParty:(UIGestureRecognizer *)sender { 83 | BOOL isPartying = self.shouldParty; 84 | self.shouldParty = !isPartying; 85 | 86 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 87 | [userDefaults setBool:!isPartying forKey:@"PartyStarted"]; 88 | [userDefaults synchronize]; 89 | } 90 | 91 | - (void)setShouldParty:(BOOL)shouldParty { 92 | _shouldParty = shouldParty; 93 | 94 | if (shouldParty) { 95 | NSTimer *partyTimer = [NSTimer timerWithTimeInterval:1.0 / 30.0 96 | target:self 97 | selector:@selector(keepThePartyGoing:) 98 | userInfo:nil 99 | repeats:YES]; 100 | [[NSRunLoop mainRunLoop] addTimer:partyTimer forMode:NSRunLoopCommonModes]; 101 | self.partyTimer = partyTimer; 102 | } else { 103 | self.partyTimer = nil; 104 | self.orange = orange; 105 | } 106 | } 107 | 108 | - (void)keepThePartyGoing:(NSTimer *)timer { 109 | partyHue += 1.0f / 360.0f; 110 | if (partyHue > 1.0f) 111 | partyHue = 0.0f; 112 | 113 | UIColor *partyColor = [UIColor colorWithHue:partyHue 114 | saturation:1.0f 115 | brightness:1.0f 116 | alpha:1.0f]; 117 | 118 | if ([self respondsToSelector:@selector(setBarTintColor:)]) { 119 | [self setBarTintColor:partyColor]; 120 | [self setTintColor:[UIColor whiteColor]]; 121 | 122 | NSDictionary *titleTextAttributes = [NSDictionary dictionaryWithObject:[UIColor whiteColor] forKey:NSForegroundColorAttributeName]; 123 | [self setTitleTextAttributes:titleTextAttributes]; 124 | } else { 125 | [self setTintColor:partyColor ]; 126 | } 127 | } 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /Classes/Views/OrangeTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // OrangeTableView.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/26/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OrangeTableView : UITableView { 12 | UIView *tableBackgroundView; 13 | UIView *orangeBackgroundView; 14 | BOOL orange; 15 | } 16 | 17 | @property (nonatomic, assign) BOOL orange; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Views/OrangeTableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // OrangeTableView.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/26/12. 6 | // Copyright (c) 2012 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "OrangeTableView.h" 10 | #import "UIColor+Orange.h" 11 | 12 | @implementation OrangeTableView 13 | @synthesize orange; 14 | 15 | - (id)initWithFrame:(CGRect)frame { 16 | if ((self = [super initWithFrame:frame style:UITableViewStyleGrouped])) { 17 | if (![self respondsToSelector:@selector(separatorInset)]) { 18 | [self setBackgroundColor:[UIColor clearColor]]; 19 | 20 | orangeBackgroundView = [[UIView alloc] initWithFrame:[self bounds]]; 21 | [orangeBackgroundView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 22 | 23 | [orangeBackgroundView setBackgroundColor:[UIColor paleOrangeColor]]; 24 | 25 | tableBackgroundView = [[UITableView alloc] initWithFrame:[self bounds] style:UITableViewStyleGrouped]; 26 | [tableBackgroundView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 27 | } 28 | } 29 | 30 | return self; 31 | } 32 | 33 | - (void)setOrange:(BOOL)orange_ { 34 | orange = orange_; 35 | 36 | if (orange) { 37 | [self setBackgroundView:orangeBackgroundView]; 38 | } else { 39 | [self setBackgroundView:tableBackgroundView]; 40 | } 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Classes/Views/OrangeToolbar.h: -------------------------------------------------------------------------------- 1 | // 2 | // OrangeToolbar.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 9/28/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @class OrangeBarView; 12 | 13 | @interface OrangeToolbar : UIToolbar { 14 | OrangeBarView *barView; 15 | 16 | NSTimer *_partyTimer; 17 | float partyHue; 18 | } 19 | 20 | @property (nonatomic, assign) BOOL orange; 21 | 22 | @property (nonatomic, assign) BOOL shouldParty; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/Views/OrangeToolbar.m: -------------------------------------------------------------------------------- 1 | // 2 | // OrangeToolbar.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 9/28/13. 6 | // 7 | // 8 | 9 | #import "UIColor+Orange.h" 10 | #import "OrangeBarView.h" 11 | #import "OrangeToolbar.h" 12 | 13 | @implementation OrangeToolbar 14 | @synthesize orange; 15 | 16 | - (id)initWithFrame:(CGRect)frame { 17 | if ((self = [super initWithFrame:frame])) { 18 | if ([self respondsToSelector:@selector(barTintColor)]) { 19 | barView = [[OrangeBarView alloc] init]; 20 | [barView setHidden:YES]; 21 | 22 | UITapGestureRecognizer *tripleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self 23 | action:@selector(startTheParty:)]; 24 | tripleTapGestureRecognizer.numberOfTapsRequired = 3; 25 | [self addGestureRecognizer:tripleTapGestureRecognizer]; 26 | 27 | self.shouldParty = [[NSUserDefaults standardUserDefaults] boolForKey:@"PartyStarted"]; 28 | } 29 | } 30 | 31 | return self; 32 | } 33 | 34 | - (void)layoutSubviews { 35 | [super layoutSubviews]; 36 | 37 | [barView layoutInsideBar:self]; 38 | } 39 | 40 | - (void)dealloc { 41 | [barView release]; 42 | 43 | [super dealloc]; 44 | } 45 | 46 | - (void)setOrange:(BOOL)orange_ { 47 | orange = orange_; 48 | 49 | if (orange) { 50 | if ([self respondsToSelector:@selector(setBarTintColor:)]) { 51 | [self setBarTintColor:[OrangeBarView barOrangeColor]]; 52 | [self setTintColor:[UIColor whiteColor]]; 53 | } else { 54 | [self setTintColor:[UIColor mainOrangeColor]]; 55 | } 56 | } else { 57 | if ([self respondsToSelector:@selector(setBarTintColor:)]) { 58 | [self setBarTintColor:nil]; 59 | } 60 | 61 | [self setTintColor:nil]; 62 | } 63 | 64 | [barView setHidden:!orange]; 65 | } 66 | 67 | #pragma mark - 68 | #pragma mark Party Mode 69 | 70 | - (void)setPartyTimer:(NSTimer *)partyTimer { 71 | if (partyTimer == _partyTimer) 72 | return; 73 | 74 | [_partyTimer invalidate]; 75 | _partyTimer = partyTimer; 76 | } 77 | 78 | - (void)startTheParty:(UIGestureRecognizer *)sender { 79 | BOOL isPartying = self.shouldParty; 80 | self.shouldParty = !isPartying; 81 | 82 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 83 | [userDefaults setBool:!isPartying forKey:@"PartyStarted"]; 84 | [userDefaults synchronize]; 85 | } 86 | 87 | - (void)setShouldParty:(BOOL)shouldParty { 88 | _shouldParty = shouldParty; 89 | 90 | if (shouldParty) { 91 | NSTimer *partyTimer = [NSTimer timerWithTimeInterval:1.0 / 30.0 92 | target:self 93 | selector:@selector(keepThePartyGoing:) 94 | userInfo:nil 95 | repeats:YES]; 96 | [[NSRunLoop mainRunLoop] addTimer:partyTimer forMode:NSRunLoopCommonModes]; 97 | self.partyTimer = partyTimer; 98 | } else { 99 | self.partyTimer = nil; 100 | self.orange = orange; 101 | } 102 | } 103 | 104 | - (void)keepThePartyGoing:(NSTimer *)timer { 105 | partyHue += 1.0f / 360.0f; 106 | if (partyHue > 1.0f) 107 | partyHue = 0.0f; 108 | 109 | UIColor *partyColor = [UIColor colorWithHue:partyHue 110 | saturation:1.0f 111 | brightness:1.0f 112 | alpha:1.0f]; 113 | 114 | if ([self respondsToSelector:@selector(setBarTintColor:)]) { 115 | [self setBarTintColor:partyColor]; 116 | [self setTintColor:[UIColor whiteColor]]; 117 | } else { 118 | [self setTintColor:partyColor]; 119 | } 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /Classes/Views/PlacardButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlacardButton.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/29/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | // The "UIPlacardButton" class is a private class used in 10 | // some of Apple's first-part App Store apps: notably the 11 | // "Remote" app. It might also be in some private framework, 12 | // not sure. Anyway, this class emulates that button using 13 | // the .png files I stole from the Remote app. If you want 14 | // to know what it actually, you know, looks like, I'd suggest 15 | // looking at the "Connect" button in the Remote app or the 16 | // "Get Started" button in the FaceTime app on the iPod touch. 17 | 18 | @interface PlacardButton : UIButton { 19 | 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Classes/Views/PlacardButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlacardButton.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/29/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "PlacardButton.h" 10 | 11 | @implementation PlacardButton 12 | 13 | + (UIImage *)_normalImage { 14 | UIImage *image = [UIImage imageNamed:@"UIPlacardButtonBkgnd.png"]; 15 | return [image stretchableImageWithLeftCapWidth:8 topCapHeight:22]; 16 | } 17 | 18 | + (UIImage *)_pressedImage { 19 | UIImage *image = [UIImage imageNamed:@"UIPlacardButtonPressedBkgnd.png"]; 20 | return [image stretchableImageWithLeftCapWidth:8 topCapHeight:22]; 21 | } 22 | 23 | - (id)initWithFrame:(CGRect)frame { 24 | if ((self = [super initWithFrame:frame])) { 25 | if (![UIView instancesRespondToSelector:@selector(tintColor)]) { 26 | [self setBackgroundImage:[[self class] _normalImage] forState:UIControlStateNormal]; 27 | [self setBackgroundImage:[[self class] _pressedImage] forState:UIControlStateHighlighted]; 28 | [self setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal]; 29 | [self setTitleColor:[UIColor darkGrayColor] forState:UIControlStateHighlighted]; 30 | [[self titleLabel] setFont:[UIFont boldSystemFontOfSize:14.0f]]; 31 | } else { 32 | [self setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 33 | [self setTitleColor:[UIColor blueColor] forState:UIControlStateHighlighted]; 34 | [[self titleLabel] setFont:[UIFont systemFontOfSize:22.0f]]; 35 | } 36 | } 37 | 38 | return self; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Classes/Views/PlaceholderTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlaceholderTextView.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/1/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | // For some unknown reason, UITextView doesn't have a "placeholder" 10 | // property like UITextField does. I have no idea why Apple didn't 11 | // include that, but this adds it using UILabel and a bunch of 12 | // probably-broken logic. 13 | 14 | @interface PlaceholderTextView : UITextView { 15 | UILabel *placeholderLabel; 16 | NSString *placeholder; 17 | } 18 | 19 | @property (nonatomic, copy) NSString *placeholder; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Classes/Views/PlaceholderTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlaceholderTextView.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/1/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "PlaceholderTextView.h" 10 | 11 | @implementation PlaceholderTextView 12 | @synthesize placeholder; 13 | 14 | - (void)setText:(NSString *)text_ { 15 | [super setText:text_]; 16 | 17 | [placeholderLabel setHidden:[[self text] length] != 0]; 18 | } 19 | 20 | - (void)setPlaceholder:(NSString *)placeholder_ { 21 | [placeholder_ autorelease]; 22 | placeholder = [placeholder_ copy]; 23 | 24 | [placeholderLabel setText:placeholder]; 25 | } 26 | 27 | - (void)setFont:(UIFont *)font { 28 | [super setFont:font]; 29 | 30 | [placeholderLabel setFont:font]; 31 | } 32 | 33 | - (void)dealloc { 34 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 35 | [placeholderLabel release]; 36 | [placeholder release]; 37 | 38 | [super dealloc]; 39 | } 40 | 41 | - (UIEdgeInsets)effectiveTextInset { 42 | UIEdgeInsets textContainerInset = UIEdgeInsetsZero; 43 | 44 | if ([self respondsToSelector:@selector(textContainerInset)]) { 45 | textContainerInset = [self textContainerInset]; 46 | 47 | // The default padding added to text views. 48 | textContainerInset.left += 4.0; 49 | textContainerInset.right += 4.0; 50 | } else { 51 | // The default padding added to text views. 52 | textContainerInset.top += 8.0; 53 | textContainerInset.left += 8.0; 54 | textContainerInset.bottom += 8.0; 55 | textContainerInset.right += 8.0; 56 | } 57 | 58 | return textContainerInset; 59 | } 60 | 61 | - (void)setContentSize:(CGSize)contentSize { 62 | [super setContentSize:contentSize]; 63 | 64 | [placeholderLabel setFrame:UIEdgeInsetsInsetRect(CGRectMake(0, 0, contentSize.width, contentSize.height), [self effectiveTextInset])]; 65 | } 66 | 67 | - (void)textChanged:(NSNotification *)notification { 68 | if ([notification object] == self) { 69 | [placeholderLabel setHidden:[[self text] length] != 0]; 70 | } 71 | } 72 | 73 | - (id)initWithFrame:(CGRect)frame { 74 | if ((self = [super initWithFrame:frame])) { 75 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil]; 76 | 77 | placeholderLabel = [[UILabel alloc] init]; 78 | [placeholderLabel setLineBreakMode:NSLineBreakByWordWrapping]; 79 | [placeholderLabel setNumberOfLines:0]; 80 | [placeholderLabel setClipsToBounds:NO]; 81 | [placeholderLabel setFont:[self font]]; 82 | [placeholderLabel setBackgroundColor:[UIColor clearColor]]; 83 | [placeholderLabel setTextColor:[UIColor lightGrayColor]]; 84 | [self insertSubview:placeholderLabel atIndex:0]; 85 | 86 | // Force placeholderLabel to resize. 87 | [self setContentSize:[self contentSize]]; 88 | } 89 | 90 | return self; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Classes/Views/ProfileHeaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileHeaderView.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/5/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | @class HNUser; 10 | @interface ProfileHeaderView : UIView { 11 | HNUser *user; 12 | UILabel *titleLabel; 13 | UILabel *subtitleLabel; 14 | 15 | CGFloat padding; 16 | } 17 | 18 | + (CGFloat)defaultHeight; 19 | 20 | @property (nonatomic, retain) HNUser *user; 21 | @property (nonatomic, copy) NSString *title; 22 | @property (nonatomic, copy) NSString *subtitle; 23 | 24 | @property (nonatomic, assign) CGFloat padding; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/Views/ProfileHeaderView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileHeaderView.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/5/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import "ProfileHeaderView.h" 10 | 11 | @implementation ProfileHeaderView 12 | @synthesize user, padding; 13 | 14 | + (CGFloat)defaultHeight { 15 | CGFloat height = 65.0; 16 | 17 | if ([UIView instancesRespondToSelector:@selector(tintColor)]) { 18 | height += 12.0; 19 | } 20 | 21 | return height; 22 | } 23 | 24 | - (id)initWithFrame:(CGRect)frame { 25 | if ((self = [super initWithFrame:frame])) { 26 | titleLabel = [[UILabel alloc] init]; 27 | [titleLabel setTextAlignment:NSTextAlignmentLeft]; 28 | [titleLabel setTextColor:[UIColor blackColor]]; 29 | [titleLabel setBackgroundColor:[UIColor clearColor]]; 30 | [titleLabel setFont:[UIFont boldSystemFontOfSize:19.0f]]; 31 | [self addSubview:titleLabel]; 32 | 33 | subtitleLabel = [[UILabel alloc] init]; 34 | [subtitleLabel setTextAlignment:NSTextAlignmentLeft]; 35 | [subtitleLabel setTextColor:[UIColor darkGrayColor]]; 36 | [subtitleLabel setBackgroundColor:[UIColor clearColor]]; 37 | [subtitleLabel setFont:[UIFont systemFontOfSize:14.0f]]; 38 | [self addSubview:subtitleLabel]; 39 | 40 | if (![UIView instancesRespondToSelector:@selector(tintColor)]) { 41 | [titleLabel setShadowColor:[UIColor whiteColor]]; 42 | [titleLabel setShadowOffset:CGSizeMake(0.0f, 1.0f)]; 43 | 44 | [subtitleLabel setShadowColor:[UIColor whiteColor]]; 45 | [subtitleLabel setShadowOffset:CGSizeMake(0.0f, 1.0f)]; 46 | } 47 | } 48 | 49 | return self; 50 | } 51 | 52 | - (void)layoutSubviews { 53 | [super layoutSubviews]; 54 | 55 | CGFloat width = [self bounds].size.width; 56 | [titleLabel setFrame:CGRectMake(padding, 20.0f, width - (padding * 2), 20.0f)]; 57 | [subtitleLabel setFrame:CGRectMake(padding, 42.0f, width - (padding * 2), 20.0f)]; 58 | } 59 | 60 | - (void)setPadding:(CGFloat)padding_ { 61 | padding = padding_; 62 | 63 | [self setNeedsLayout]; 64 | } 65 | 66 | - (NSString *)title { 67 | return [titleLabel text]; 68 | } 69 | 70 | - (void)setTitle:(NSString *)title { 71 | [titleLabel setText:title]; 72 | } 73 | 74 | - (NSString *)subtitle { 75 | return [subtitleLabel text]; 76 | } 77 | 78 | - (void)setSubtitle:(NSString *)subtitle { 79 | [subtitleLabel setText:subtitle]; 80 | } 81 | 82 | - (void)dealloc { 83 | [user release]; 84 | [subtitleLabel release]; 85 | [titleLabel release]; 86 | 87 | [super dealloc]; 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /Classes/Views/ProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // ProgressHUD.h 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 4/12/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #define kProgressHUDStateLoading @"loading" 10 | #define kProgressHUDStateCompleted @"completed" 11 | #define kProgressHUDStateError @"error" 12 | typedef NSString *ProgressHUDState; 13 | 14 | @interface ProgressHUD : UIView { 15 | UIActivityIndicatorView *spinner; 16 | UIImageView *image; 17 | UILabel *label; 18 | NSString *text; 19 | UIView *overlay; 20 | ProgressHUDState state; 21 | } 22 | 23 | @property (nonatomic, copy) NSString *text; 24 | @property (nonatomic, readonly) UILabel *label; 25 | @property (nonatomic, copy) ProgressHUDState state; 26 | 27 | - (void)showInWindow:(UIWindow *)window; 28 | - (void)dismiss; 29 | - (void)dismissWithAnimation:(BOOL)animated; 30 | - (void)dismissAfterDelay:(NSTimeInterval)delay; 31 | - (void)dismissAfterDelay:(NSTimeInterval)delay animated:(BOOL)animated; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Classes/Views/PullToRefreshView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PullToRefreshView.h 3 | // Grant Paul (chpwn) 4 | // 5 | // (based on EGORefreshTableHeaderView) 6 | // 7 | // Created by Devin Doty on 10/14/09October14. 8 | // Copyright 2009 enormego. All rights reserved. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | // 28 | 29 | #import 30 | #import 31 | 32 | typedef enum { 33 | PullToRefreshViewStateNormal = 0, 34 | PullToRefreshViewStateReady, 35 | PullToRefreshViewStateLoading 36 | } PullToRefreshViewState; 37 | 38 | @protocol PullToRefreshViewDelegate; 39 | 40 | @interface PullToRefreshView : UIView { 41 | id delegate; 42 | UIScrollView *scrollView; 43 | PullToRefreshViewState state; 44 | 45 | UILabel *lastUpdatedLabel; 46 | UILabel *statusLabel; 47 | CALayer *arrowImage; 48 | UIActivityIndicatorView *activityView; 49 | } 50 | 51 | @property (nonatomic, readonly) UIScrollView *scrollView; 52 | @property (nonatomic, assign) id delegate; 53 | @property (nonatomic, assign) PullToRefreshViewState state; 54 | 55 | @property (nonatomic, copy) UIColor *textShadowColor; 56 | 57 | - (void)refreshLastUpdatedDate; 58 | - (void)finishedLoading; 59 | 60 | - (id)initWithScrollView:(UIScrollView *)scrollView; 61 | 62 | @end 63 | 64 | @protocol PullToRefreshViewDelegate 65 | 66 | @optional 67 | - (void)pullToRefreshViewShouldRefresh:(PullToRefreshView *)view; 68 | - (NSDate *)pullToRefreshViewLastUpdated:(PullToRefreshView *)view; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /Classes/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // newsyc 4 | // 5 | // Created by Grant Paul on 3/3/11. 6 | // Copyright 2011 Xuzz Productions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | int main(int argc, char **argv) { 13 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 14 | int ret = UIApplicationMain(argc, argv, nil, @"AppDelegate"); 15 | [pool release]; 16 | return ret; 17 | } 18 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Startup News 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIcons 12 | 13 | CFBundlePrimaryIcon 14 | 15 | CFBundleIconFiles 16 | 17 | Modern-Icon 18 | Modern-Icon-Pad 19 | Modern-Icon-Settings 20 | Modern-Icon-Spotlight 21 | Legacy-Icon 22 | Legacy-Icon-Pad 23 | Legacy-Icon-Settings 24 | Legacy-Icon-Spotlight 25 | 26 | UIPrerenderedIcon 27 | 28 | 29 | 30 | CFBundleIdentifier 31 | com.maozexi.starupnews 32 | CFBundleInfoDictionaryVersion 33 | 6.0 34 | CFBundleName 35 | ${PRODUCT_NAME} 36 | CFBundlePackageType 37 | APPL 38 | CFBundleShortVersionString 39 | 2.0.1 40 | CFBundleSignature 41 | ???? 42 | CFBundleVersion 43 | 101 44 | LSRequiresIPhoneOS 45 | 46 | NSHighResolutionCapable 47 | 48 | UILaunchImages 49 | 50 | 51 | UILaunchImageMinimumOSVersion 52 | 7.0 53 | UILaunchImageName 54 | Modern-Default-736h 55 | UILaunchImageOrientation 56 | Portrait 57 | UILaunchImageSize 58 | {414, 736} 59 | 60 | 61 | UILaunchImageMinimumOSVersion 62 | 7.0 63 | UILaunchImageName 64 | Modern-Default-667h 65 | UILaunchImageOrientation 66 | Portrait 67 | UILaunchImageSize 68 | {375, 667} 69 | 70 | 71 | UILaunchImageMinimumOSVersion 72 | 7.0 73 | UILaunchImageName 74 | Modern-Default 75 | UILaunchImageOrientation 76 | Portrait 77 | UILaunchImageSize 78 | {320, 480} 79 | 80 | 81 | UILaunchImageMinimumOSVersion 82 | 7.0 83 | UILaunchImageName 84 | Modern-Default-568h 85 | UILaunchImageOrientation 86 | Portrait 87 | UILaunchImageSize 88 | {320, 568} 89 | 90 | 91 | UILaunchImages~ipad 92 | 93 | 94 | UILaunchImageMinimumOSVersion 95 | 7.0 96 | UILaunchImageName 97 | Modern-Default-Portrait 98 | UILaunchImageOrientation 99 | Portrait 100 | UILaunchImageSize 101 | {768, 1024} 102 | 103 | 104 | UILaunchImageMinimumOSVersion 105 | 7.0 106 | UILaunchImageName 107 | Modern-Default-Landscape 108 | UILaunchImageOrientation 109 | Landscape 110 | UILaunchImageSize 111 | {768, 1024} 112 | 113 | 114 | UIRequiresPersistentWiFi 115 | 116 | UIStatusBarStyle 117 | UIStatusBarStyleLightContent 118 | UIStatusBarTintParameters 119 | 120 | UINavigationBar 121 | 122 | Style 123 | UIBarStyleDefault 124 | TintColor 125 | 126 | Blue 127 | 0.0 128 | Green 129 | 0.40000000000000002 130 | Red 131 | 1 132 | 133 | Translucent 134 | 135 | 136 | 137 | UISupportedInterfaceOrientations~ipad 138 | 139 | UIInterfaceOrientationPortrait 140 | UIInterfaceOrientationPortraitUpsideDown 141 | UIInterfaceOrientationLandscapeLeft 142 | UIInterfaceOrientationLandscapeRight 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, Xuzz Productions, LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | Neither the name of the Xuzz Productions, LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Welcome ## 2 | 3 | 这是 @fenng 的[Startup News](http://news.dbanotes.net/news)平台的iOS客户端。 4 | 基于 Hacker News 的开源客户端更改。 5 | 6 | -------------------------------------------------------------------------------- /Resources/Icons/Legacy-Icon-Pad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Legacy-Icon-Pad.png -------------------------------------------------------------------------------- /Resources/Icons/Legacy-Icon-Pad@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Legacy-Icon-Pad@2x.png -------------------------------------------------------------------------------- /Resources/Icons/Legacy-Icon-Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Legacy-Icon-Settings.png -------------------------------------------------------------------------------- /Resources/Icons/Legacy-Icon-Settings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Legacy-Icon-Settings@2x.png -------------------------------------------------------------------------------- /Resources/Icons/Legacy-Icon-Spotlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Legacy-Icon-Spotlight.png -------------------------------------------------------------------------------- /Resources/Icons/Legacy-Icon-Spotlight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Legacy-Icon-Spotlight@2x.png -------------------------------------------------------------------------------- /Resources/Icons/Legacy-Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Legacy-Icon.png -------------------------------------------------------------------------------- /Resources/Icons/Legacy-Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Legacy-Icon@2x.png -------------------------------------------------------------------------------- /Resources/Icons/Legacy-iTunesArtwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Legacy-iTunesArtwork.png -------------------------------------------------------------------------------- /Resources/Icons/Legacy-iTunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Legacy-iTunesArtwork@2x.png -------------------------------------------------------------------------------- /Resources/Icons/Modern-Icon-Pad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Modern-Icon-Pad.png -------------------------------------------------------------------------------- /Resources/Icons/Modern-Icon-Pad@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Modern-Icon-Pad@2x.png -------------------------------------------------------------------------------- /Resources/Icons/Modern-Icon-Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Modern-Icon-Settings.png -------------------------------------------------------------------------------- /Resources/Icons/Modern-Icon-Settings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Modern-Icon-Settings@2x.png -------------------------------------------------------------------------------- /Resources/Icons/Modern-Icon-Spotlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Modern-Icon-Spotlight.png -------------------------------------------------------------------------------- /Resources/Icons/Modern-Icon-Spotlight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Modern-Icon-Spotlight@2x.png -------------------------------------------------------------------------------- /Resources/Icons/Modern-Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Modern-Icon.png -------------------------------------------------------------------------------- /Resources/Icons/Modern-Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Modern-Icon@2x.png -------------------------------------------------------------------------------- /Resources/Icons/Modern-iTunesArtwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Modern-iTunesArtwork.png -------------------------------------------------------------------------------- /Resources/Icons/Modern-iTunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Icons/Modern-iTunesArtwork@2x.png -------------------------------------------------------------------------------- /Resources/Images/UIPlacardButtonBkgnd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/UIPlacardButtonBkgnd.png -------------------------------------------------------------------------------- /Resources/Images/UIPlacardButtonBkgnd@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/UIPlacardButtonBkgnd@2x.png -------------------------------------------------------------------------------- /Resources/Images/UIPlacardButtonPressedBkgnd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/UIPlacardButtonPressedBkgnd.png -------------------------------------------------------------------------------- /Resources/Images/UIPlacardButtonPressedBkgnd@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/UIPlacardButtonPressedBkgnd@2x.png -------------------------------------------------------------------------------- /Resources/Images/action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/action.png -------------------------------------------------------------------------------- /Resources/Images/action7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/action7@2x.png -------------------------------------------------------------------------------- /Resources/Images/action@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/action@2x.png -------------------------------------------------------------------------------- /Resources/Images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/arrow.png -------------------------------------------------------------------------------- /Resources/Images/arrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/arrow@2x.png -------------------------------------------------------------------------------- /Resources/Images/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/back.png -------------------------------------------------------------------------------- /Resources/Images/back7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/back7@2x.png -------------------------------------------------------------------------------- /Resources/Images/back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/back@2x.png -------------------------------------------------------------------------------- /Resources/Images/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/check.png -------------------------------------------------------------------------------- /Resources/Images/check@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/check@2x.png -------------------------------------------------------------------------------- /Resources/Images/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/clear.png -------------------------------------------------------------------------------- /Resources/Images/disclosure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/disclosure.png -------------------------------------------------------------------------------- /Resources/Images/disclosure@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/disclosure@2x.png -------------------------------------------------------------------------------- /Resources/Images/downvote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/downvote.png -------------------------------------------------------------------------------- /Resources/Images/downvote7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/downvote7@2x.png -------------------------------------------------------------------------------- /Resources/Images/downvote@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/downvote@2x.png -------------------------------------------------------------------------------- /Resources/Images/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/flag.png -------------------------------------------------------------------------------- /Resources/Images/flag7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/flag7@2x.png -------------------------------------------------------------------------------- /Resources/Images/flag@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/flag@2x.png -------------------------------------------------------------------------------- /Resources/Images/forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/forward.png -------------------------------------------------------------------------------- /Resources/Images/forward7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/forward7@2x.png -------------------------------------------------------------------------------- /Resources/Images/forward@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/forward@2x.png -------------------------------------------------------------------------------- /Resources/Images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/home.png -------------------------------------------------------------------------------- /Resources/Images/home7-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/home7-selected@2x.png -------------------------------------------------------------------------------- /Resources/Images/home7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/home7@2x.png -------------------------------------------------------------------------------- /Resources/Images/home@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/home@2x.png -------------------------------------------------------------------------------- /Resources/Images/instapaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/instapaper.png -------------------------------------------------------------------------------- /Resources/Images/instapaper@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/instapaper@2x.png -------------------------------------------------------------------------------- /Resources/Images/instapaper@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/instapaper@2x~ipad.png -------------------------------------------------------------------------------- /Resources/Images/instapaper~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/instapaper~ipad.png -------------------------------------------------------------------------------- /Resources/Images/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/new.png -------------------------------------------------------------------------------- /Resources/Images/new7-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/new7-selected@2x.png -------------------------------------------------------------------------------- /Resources/Images/new7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/new7@2x.png -------------------------------------------------------------------------------- /Resources/Images/new@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/new@2x.png -------------------------------------------------------------------------------- /Resources/Images/openinsafari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/openinsafari.png -------------------------------------------------------------------------------- /Resources/Images/openinsafari7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/openinsafari7@2x.png -------------------------------------------------------------------------------- /Resources/Images/openinsafari7@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/openinsafari7@2x~ipad.png -------------------------------------------------------------------------------- /Resources/Images/openinsafari7~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/openinsafari7~ipad.png -------------------------------------------------------------------------------- /Resources/Images/openinsafari@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/openinsafari@2x.png -------------------------------------------------------------------------------- /Resources/Images/openinsafari@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/openinsafari@2x~ipad.png -------------------------------------------------------------------------------- /Resources/Images/openinsafari~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/openinsafari~ipad.png -------------------------------------------------------------------------------- /Resources/Images/person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/person.png -------------------------------------------------------------------------------- /Resources/Images/person7-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/person7-selected@2x.png -------------------------------------------------------------------------------- /Resources/Images/person7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/person7@2x.png -------------------------------------------------------------------------------- /Resources/Images/person@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/person@2x.png -------------------------------------------------------------------------------- /Resources/Images/readability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/readability.png -------------------------------------------------------------------------------- /Resources/Images/readability@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/readability@2x.png -------------------------------------------------------------------------------- /Resources/Images/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/refresh.png -------------------------------------------------------------------------------- /Resources/Images/refresh7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/refresh7@2x.png -------------------------------------------------------------------------------- /Resources/Images/refresh@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/refresh@2x.png -------------------------------------------------------------------------------- /Resources/Images/reply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/reply.png -------------------------------------------------------------------------------- /Resources/Images/reply7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/reply7@2x.png -------------------------------------------------------------------------------- /Resources/Images/reply@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/reply@2x.png -------------------------------------------------------------------------------- /Resources/Images/toolbar-expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/toolbar-expanded.png -------------------------------------------------------------------------------- /Resources/Images/upvote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/upvote.png -------------------------------------------------------------------------------- /Resources/Images/upvote7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/upvote7@2x.png -------------------------------------------------------------------------------- /Resources/Images/upvote@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/upvote@2x.png -------------------------------------------------------------------------------- /Resources/Images/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/x.png -------------------------------------------------------------------------------- /Resources/Images/x@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Images/x@2x.png -------------------------------------------------------------------------------- /Resources/Launch Images/Modern-Default-568h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Launch Images/Modern-Default-568h.png -------------------------------------------------------------------------------- /Resources/Launch Images/Modern-Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Launch Images/Modern-Default-568h@2x.png -------------------------------------------------------------------------------- /Resources/Launch Images/Modern-Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Launch Images/Modern-Default-667h@2x.png -------------------------------------------------------------------------------- /Resources/Launch Images/Modern-Default-736h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Launch Images/Modern-Default-736h@2x.png -------------------------------------------------------------------------------- /Resources/Launch Images/Modern-Default-Landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Launch Images/Modern-Default-Landscape.png -------------------------------------------------------------------------------- /Resources/Launch Images/Modern-Default-Landscape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Launch Images/Modern-Default-Landscape@2x.png -------------------------------------------------------------------------------- /Resources/Launch Images/Modern-Default-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Launch Images/Modern-Default-Portrait.png -------------------------------------------------------------------------------- /Resources/Launch Images/Modern-Default-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Launch Images/Modern-Default-Portrait@2x.png -------------------------------------------------------------------------------- /Resources/Launch Images/Modern-Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Launch Images/Modern-Default.png -------------------------------------------------------------------------------- /Resources/Launch Images/Modern-Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Launch Images/Modern-Default@2x.png -------------------------------------------------------------------------------- /Resources/Settings.bundle/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | Type 9 | PSGroupSpecifier 10 | Title 11 | Interface 12 | 13 | 14 | DefaultValue 15 | 16 | Key 17 | interface-confirm-votes 18 | Title 19 | Confirm Votes 20 | Type 21 | PSToggleSwitchSpecifier 22 | 23 | 24 | DefaultValue 25 | 26 | Key 27 | disable-orange 28 | Title 29 | Less Orange 30 | Type 31 | PSToggleSwitchSpecifier 32 | 33 | 34 | FooterText 35 | Enable this option to log out of Instapaper next time you launch news:yc. 36 | Title 37 | Instapaper 38 | Type 39 | PSGroupSpecifier 40 | 41 | 42 | DefaultValue 43 | 44 | Key 45 | instapaper-logout 46 | Title 47 | Logout on Launch 48 | Type 49 | PSToggleSwitchSpecifier 50 | 51 | 52 | FooterText 53 | news:yc © 2013 Xuzz Productions, LLC 54 | Source code is on GitHub. BSD licensed. 55 | 56 | Title 57 | 58 | Type 59 | PSGroupSpecifier 60 | 61 | 62 | StringsTable 63 | Root 64 | 65 | 66 | -------------------------------------------------------------------------------- /Resources/Settings.bundle/en.lproj/Root.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Settings.bundle/en.lproj/Root.strings -------------------------------------------------------------------------------- /Resources/Source/icon-6.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Source/icon-6.psd -------------------------------------------------------------------------------- /Resources/Source/icon-old.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Source/icon-old.psd -------------------------------------------------------------------------------- /Resources/Source/icon.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Source/icon.pxm -------------------------------------------------------------------------------- /Resources/Source/instapaper7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Source/instapaper7.pdf -------------------------------------------------------------------------------- /Resources/Source/instapaper7.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Source/instapaper7.pxm -------------------------------------------------------------------------------- /Resources/Source/openinsafari.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Source/openinsafari.pxm -------------------------------------------------------------------------------- /Resources/Source/openinsafari7.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangqiaoboy/newsyc/3ea349b76ada9a1a8911f29728c9e8dcc4b6a0d1/Resources/Source/openinsafari7.pxm -------------------------------------------------------------------------------- /newsyc.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /newsyc.xcodeproj/xcuserdata/Mark.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /newsyc.xcodeproj/xcuserdata/Mark.xcuserdatad/xcschemes/newsyc.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /newsyc.xcodeproj/xcuserdata/Mark.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | newsyc.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 7D1F988C1320CF720059EBBB 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /newsyc.xcodeproj/xcuserdata/Xuzz.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /newsyc.xcodeproj/xcuserdata/Xuzz.xcuserdatad/xcschemes/newsyc.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 53 | 54 | 60 | 61 | 62 | 63 | 67 | 68 | 69 | 70 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /newsyc.xcodeproj/xcuserdata/Xuzz.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | newsyc.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 7D1F988C1320CF720059EBBB 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | --------------------------------------------------------------------------------