diff --git a/5by5Browser.xcodeproj/project.pbxproj b/5by5Browser.xcodeproj/project.pbxproj index 5b1aea5..8f6b285 100644 --- a/5by5Browser.xcodeproj/project.pbxproj +++ b/5by5Browser.xcodeproj/project.pbxproj @@ -27,6 +27,11 @@ 7B1A6EF1149D140600FC5105 /* SSDetailViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B1A6EEF149D140600FC5105 /* SSDetailViewController_iPad.xib */; }; 7B1A6EF9149D148800FC5105 /* FiveByFive.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B1A6EF8149D148800FC5105 /* FiveByFive.m */; }; 7B1A6EFC149D14C500FC5105 /* Show.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B1A6EFB149D14C500FC5105 /* Show.m */; }; + 7B4CADE9149FE797007E7941 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B4CADE8149FE797007E7941 /* Security.framework */; }; + 7B4CADF0149FE944007E7941 /* UIAlertView+marshmallows.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4CADEE149FE944007E7941 /* UIAlertView+marshmallows.h */; }; + 7B4CADF1149FE944007E7941 /* UIAlertView+marshmallows.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B4CADEF149FE944007E7941 /* UIAlertView+marshmallows.m */; }; + 7B4CADF5149FEAE5007E7941 /* UIAlertViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4CADF3149FEAE5007E7941 /* UIAlertViewDelegate.h */; }; + 7B4CADF6149FEAE5007E7941 /* UIAlertViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B4CADF4149FEAE5007E7941 /* UIAlertViewDelegate.m */; }; 7B7302F2149D670A003547E5 /* GTMNSString+HTML.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B7302EA149D670A003547E5 /* GTMNSString+HTML.h */; }; 7B7302F3149D670A003547E5 /* GTMNSString+HTML.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B7302EB149D670A003547E5 /* GTMNSString+HTML.m */; }; 7B7302F4149D670A003547E5 /* NSDate+InternetDateTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B7302EC149D670A003547E5 /* NSDate+InternetDateTime.h */; }; @@ -46,6 +51,12 @@ 7B86894B149D5C1000F3A2C6 /* ShowViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B868949149D5C0F00F3A2C6 /* ShowViewController.m */; }; 7B868951149D5C6F00F3A2C6 /* ShowViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B86894D149D5C6F00F3A2C6 /* ShowViewController_iPad.xib */; }; 7B868952149D5C6F00F3A2C6 /* ShowViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B86894F149D5C6F00F3A2C6 /* ShowViewController_iPhone.xib */; }; + 7BDCFA03149E695E00DDF1B3 /* MMHTTPRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDCFA01149E695E00DDF1B3 /* MMHTTPRequest.h */; }; + 7BDCFA04149E695E00DDF1B3 /* MMHTTPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BDCFA02149E695E00DDF1B3 /* MMHTTPRequest.m */; }; + 7BDCFA07149E69E700DDF1B3 /* MMHTTPClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDCFA05149E69E700DDF1B3 /* MMHTTPClient.h */; }; + 7BDCFA08149E69E700DDF1B3 /* MMHTTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BDCFA06149E69E700DDF1B3 /* MMHTTPClient.m */; }; + 7BDCFA0B149E6A2B00DDF1B3 /* NSString+marshmallows.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDCFA09149E6A2A00DDF1B3 /* NSString+marshmallows.h */; }; + 7BDCFA0C149E6A2B00DDF1B3 /* NSString+marshmallows.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BDCFA0A149E6A2B00DDF1B3 /* NSString+marshmallows.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -77,6 +88,11 @@ 7B1A6EF8149D148800FC5105 /* FiveByFive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FiveByFive.m; sourceTree = ""; }; 7B1A6EFA149D14C500FC5105 /* Show.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Show.h; sourceTree = ""; }; 7B1A6EFB149D14C500FC5105 /* Show.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Show.m; sourceTree = ""; }; + 7B4CADE8149FE797007E7941 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 7B4CADEE149FE944007E7941 /* UIAlertView+marshmallows.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIAlertView+marshmallows.h"; sourceTree = ""; }; + 7B4CADEF149FE944007E7941 /* UIAlertView+marshmallows.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIAlertView+marshmallows.m"; sourceTree = ""; }; + 7B4CADF3149FEAE5007E7941 /* UIAlertViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIAlertViewDelegate.h; sourceTree = ""; }; + 7B4CADF4149FEAE5007E7941 /* UIAlertViewDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIAlertViewDelegate.m; sourceTree = ""; }; 7B7302EA149D670A003547E5 /* GTMNSString+HTML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSString+HTML.h"; sourceTree = ""; }; 7B7302EB149D670A003547E5 /* GTMNSString+HTML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSString+HTML.m"; sourceTree = ""; }; 7B7302EC149D670A003547E5 /* NSDate+InternetDateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+InternetDateTime.h"; sourceTree = ""; }; @@ -98,6 +114,13 @@ 7B868949149D5C0F00F3A2C6 /* ShowViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShowViewController.m; sourceTree = ""; }; 7B86894E149D5C6F00F3A2C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ShowViewController_iPad.xib; sourceTree = ""; }; 7B868950149D5C6F00F3A2C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ShowViewController_iPhone.xib; sourceTree = ""; }; + 7BDCFA00149E688600DDF1B3 /* InstapaperCredentials.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InstapaperCredentials.h; sourceTree = ""; }; + 7BDCFA01149E695E00DDF1B3 /* MMHTTPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMHTTPRequest.h; sourceTree = ""; }; + 7BDCFA02149E695E00DDF1B3 /* MMHTTPRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMHTTPRequest.m; sourceTree = ""; }; + 7BDCFA05149E69E700DDF1B3 /* MMHTTPClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMHTTPClient.h; sourceTree = ""; }; + 7BDCFA06149E69E700DDF1B3 /* MMHTTPClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMHTTPClient.m; sourceTree = ""; }; + 7BDCFA09149E6A2A00DDF1B3 /* NSString+marshmallows.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+marshmallows.h"; sourceTree = ""; }; + 7BDCFA0A149E6A2B00DDF1B3 /* NSString+marshmallows.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+marshmallows.m"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -105,6 +128,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 7B4CADE9149FE797007E7941 /* Security.framework in Frameworks */, 7B1A6ECF149D140600FC5105 /* UIKit.framework in Frameworks */, 7B1A6ED1149D140600FC5105 /* Foundation.framework in Frameworks */, 7B1A6ED3149D140600FC5105 /* CoreGraphics.framework in Frameworks */, @@ -118,6 +142,7 @@ isa = PBXGroup; children = ( 7B7302E9149D66ED003547E5 /* MWFeedParser */, + 7B4CADF2149FE954007E7941 /* Marshmallows */, 7B1A6ED4149D140600FC5105 /* 5by5Browser */, 7B1A6ECD149D140600FC5105 /* Frameworks */, 7B1A6ECB149D140600FC5105 /* Products */, @@ -135,6 +160,7 @@ 7B1A6ECD149D140600FC5105 /* Frameworks */ = { isa = PBXGroup; children = ( + 7B4CADE8149FE797007E7941 /* Security.framework */, 7B1A6ECE149D140600FC5105 /* UIKit.framework */, 7B1A6ED0149D140600FC5105 /* Foundation.framework */, 7B1A6ED2149D140600FC5105 /* CoreGraphics.framework */, @@ -145,6 +171,7 @@ 7B1A6ED4149D140600FC5105 /* 5by5Browser */ = { isa = PBXGroup; children = ( + 7BDCFA00149E688600DDF1B3 /* InstapaperCredentials.h */, 7B1A6EDD149D140600FC5105 /* SSAppDelegate.h */, 7B1A6EDE149D140600FC5105 /* SSAppDelegate.m */, 7B868948149D5C0F00F3A2C6 /* ShowViewController.h */, @@ -187,6 +214,24 @@ name = "Supporting Files"; sourceTree = ""; }; + 7B4CADF2149FE954007E7941 /* Marshmallows */ = { + isa = PBXGroup; + children = ( + 7BDCFA05149E69E700DDF1B3 /* MMHTTPClient.h */, + 7BDCFA06149E69E700DDF1B3 /* MMHTTPClient.m */, + 7BDCFA01149E695E00DDF1B3 /* MMHTTPRequest.h */, + 7BDCFA02149E695E00DDF1B3 /* MMHTTPRequest.m */, + 7BDCFA09149E6A2A00DDF1B3 /* NSString+marshmallows.h */, + 7BDCFA0A149E6A2B00DDF1B3 /* NSString+marshmallows.m */, + 7B4CADF3149FEAE5007E7941 /* UIAlertViewDelegate.h */, + 7B4CADF4149FEAE5007E7941 /* UIAlertViewDelegate.m */, + 7B4CADEE149FE944007E7941 /* UIAlertView+marshmallows.h */, + 7B4CADEF149FE944007E7941 /* UIAlertView+marshmallows.m */, + ); + name = Marshmallows; + path = 5by5Browser; + sourceTree = ""; + }; 7B7302E7149D66EA003547E5 /* Categories */ = { isa = PBXGroup; children = ( @@ -232,6 +277,11 @@ 7B730303149D6714003547E5 /* MWFeedItem.h in Headers */, 7B730305149D6714003547E5 /* MWFeedParser_Private.h in Headers */, 7B730306149D6714003547E5 /* MWFeedParser.h in Headers */, + 7BDCFA03149E695E00DDF1B3 /* MMHTTPRequest.h in Headers */, + 7BDCFA07149E69E700DDF1B3 /* MMHTTPClient.h in Headers */, + 7BDCFA0B149E6A2B00DDF1B3 /* NSString+marshmallows.h in Headers */, + 7B4CADF0149FE944007E7941 /* UIAlertView+marshmallows.h in Headers */, + 7B4CADF5149FEAE5007E7941 /* UIAlertViewDelegate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -326,6 +376,11 @@ 7B730302149D6714003547E5 /* MWFeedInfo.m in Sources */, 7B730304149D6714003547E5 /* MWFeedItem.m in Sources */, 7B730307149D6714003547E5 /* MWFeedParser.m in Sources */, + 7BDCFA04149E695E00DDF1B3 /* MMHTTPRequest.m in Sources */, + 7BDCFA08149E69E700DDF1B3 /* MMHTTPClient.m in Sources */, + 7BDCFA0C149E6A2B00DDF1B3 /* NSString+marshmallows.m in Sources */, + 7B4CADF1149FE944007E7941 /* UIAlertView+marshmallows.m in Sources */, + 7B4CADF6149FEAE5007E7941 /* UIAlertViewDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/5by5Browser.xcodeproj/project.xcworkspace/xcuserdata/sjs.xcuserdatad/UserInterfaceState.xcuserstate b/5by5Browser.xcodeproj/project.xcworkspace/xcuserdata/sjs.xcuserdatad/UserInterfaceState.xcuserstate index 1261e91..686b48d 100644 Binary files a/5by5Browser.xcodeproj/project.xcworkspace/xcuserdata/sjs.xcuserdatad/UserInterfaceState.xcuserstate and b/5by5Browser.xcodeproj/project.xcworkspace/xcuserdata/sjs.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/5by5Browser/5by5Browser-Info.plist b/5by5Browser/5by5Browser-Info.plist index 99bc68a..e42e693 100644 --- a/5by5Browser/5by5Browser-Info.plist +++ b/5by5Browser/5by5Browser-Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - ${PRODUCT_NAME} + 5by5 Browser CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier @@ -24,6 +24,8 @@ 1.0 LSRequiresIPhoneOS + UIStatusBarStyle + UIStatusBarStyleBlackTranslucent UIRequiredDeviceCapabilities armv7 diff --git a/5by5Browser/Episode.h b/5by5Browser/Episode.h index 84b4ab6..c6d96f2 100644 --- a/5by5Browser/Episode.h +++ b/5by5Browser/Episode.h @@ -7,14 +7,18 @@ // #import +#import "Show.h" + +@class Show; @interface Episode : NSObject @property (nonatomic, retain) NSString *name; @property (nonatomic, retain) NSString *number; +@property (nonatomic, retain) Show *show; @property (nonatomic, retain) NSURL *url; -+ (id) episodeWithName: (NSString *)name number: (NSString *)number url: (NSURL *)url; -- (id) initWithName: (NSString *)name number: (NSString *)number url: (NSURL *)url; ++ (id) episodeWithShow: (Show *)show name: (NSString *)name number: (NSString *)number url: (NSURL *)url; +- (id) initWithShow: (Show *)show name: (NSString *)name number: (NSString *)number url: (NSURL *)url; @end diff --git a/5by5Browser/Episode.m b/5by5Browser/Episode.m index 0b076ef..7f046d2 100644 --- a/5by5Browser/Episode.m +++ b/5by5Browser/Episode.m @@ -12,17 +12,19 @@ @synthesize name = _name; @synthesize number = _number; +@synthesize show = _show; @synthesize url = _url; -+ (id) episodeWithName: (NSString *)name number: (NSString *)number url: (NSURL *)url ++ (id) episodeWithShow: (Show *)show name: (NSString *)name number: (NSString *)number url: (NSURL *)url { - return [[self alloc] initWithName: name number: number url: url]; + return [[self alloc] initWithShow: show name: name number: number url: url]; } -- (id) initWithName: (NSString *)name number: (NSString *)number url: (NSURL *)url +- (id) initWithShow: (Show *)show name: (NSString *)name number: (NSString *)number url: (NSURL *)url { self = [super init]; if (self) { + self.show = show; self.name = name; self.number = number; self.url = url; @@ -30,4 +32,13 @@ return self; } +- (void) setName: (NSString *)name +{ + if (self.show && [name hasPrefix: self.show.name]) { + NSString *showName = [self.show.name stringByAppendingString: @" "]; + name = [name stringByReplacingOccurrencesOfString: showName withString: @""]; + } + _name = name; +} + @end diff --git a/5by5Browser/MMHTTPClient.h b/5by5Browser/MMHTTPClient.h new file mode 100644 index 0000000..9afd176 --- /dev/null +++ b/5by5Browser/MMHTTPClient.h @@ -0,0 +1,54 @@ +// +// MMHTTPClient.h +// Marshmallows +// +// Created by Sami Samhuri on 11-09-03. +// Copyright 2011 Guru Logic. All rights reserved. +// + +#import +#import "MMHTTPRequest.h" + +@interface MMHTTPClient : NSObject +{ + NSString *_baseURL; + NSUInteger _timeout; +} + ++ (MMHTTPClient *) sharedClient; ++ (id) client; ++ (id) clientWithBaseURL: (NSString *)baseURL; ++ (id) clientWithBaseURL: (NSString *)baseURL timeout: (NSUInteger)timeout; + ++ (NSString *) pathFor: (NSString *)first, ... NS_REQUIRES_NIL_TERMINATION; ++ (NSString *) urlFor: (NSString *)first, ... NS_REQUIRES_NIL_TERMINATION; ++ (NSString *) urlWithPath: (NSString *)path; ++ (MMHTTPRequest *) request: (NSDictionary *)options then: (MMHTTPCallback)callback; ++ (MMHTTPRequest *) get: (NSString *)url then: (MMHTTPCallback)callback; ++ (MMHTTPRequest *) getImage: (NSString *)url then: (MMHTTPImageCallback)callback; ++ (MMHTTPRequest *) getText: (NSString *)url then: (MMHTTPTextCallback)callback; ++ (MMHTTPRequest *) post: (NSString *)url then: (MMHTTPCallback)callback; ++ (MMHTTPRequest *) post: (NSString *)url fields: (NSDictionary *)fields then: (MMHTTPCallback)callback; ++ (MMHTTPRequest *) post: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback; ++ (MMHTTPRequest *) put: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback; ++ (MMHTTPRequest *) delete: (NSString *)url then: (MMHTTPCallback)callback; + +@property (nonatomic, retain) NSString *baseURL; +@property NSUInteger timeout; + +- (id) initWithBaseURL: (NSString *)baseURl; +- (id) initWithBaseURL: (NSString *)baseURl timeout: (NSUInteger)timeout; +- (NSString *) pathFor: (NSString *)first, ... NS_REQUIRES_NIL_TERMINATION; +- (NSString *) urlFor: (NSString *)first, ... NS_REQUIRES_NIL_TERMINATION; +- (NSString *) urlWithPath: (NSString *)path; +- (MMHTTPRequest *) request: (NSDictionary *)options then: (MMHTTPCallback)callback; +- (MMHTTPRequest *) get: (NSString *)url then: (MMHTTPCallback)callback; +- (MMHTTPRequest *) getImage: (NSString *)url then: (MMHTTPImageCallback)callback; +- (MMHTTPRequest *) getText: (NSString *)url then: (MMHTTPTextCallback)callback; +- (MMHTTPRequest *) post: (NSString *)url then: (MMHTTPCallback)callback; +- (MMHTTPRequest *) post: (NSString *)url fields: (NSDictionary *)fields then: (MMHTTPCallback)callback; +- (MMHTTPRequest *) post: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback; +- (MMHTTPRequest *) put: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback; +- (MMHTTPRequest *) delete: (NSString *)url then: (MMHTTPCallback)callback; + +@end diff --git a/5by5Browser/MMHTTPClient.m b/5by5Browser/MMHTTPClient.m new file mode 100644 index 0000000..9f03308 --- /dev/null +++ b/5by5Browser/MMHTTPClient.m @@ -0,0 +1,252 @@ +// +// MMHTTPClient.m +// Marshmallows +// +// Created by Sami Samhuri on 11-09-03. +// Copyright 2011 Guru Logic. All rights reserved. +// + +#import "MMHTTPClient.h" +#import "NSString+marshmallows.h" + +MMHTTPClient *_client; + +NSString *JoinURLComponents(NSString *first, va_list args) +{ + NSMutableString *url = [NSMutableString string]; + NSString *slash = @""; + for (NSString *arg = first; arg != nil; arg = va_arg(args, NSString *)) { + [url appendFormat: @"%@%@", slash, [arg stringByURLEncoding]]; + slash = @"/"; + } + return [NSString stringWithString: url]; +} + +@implementation MMHTTPClient + +@synthesize baseURL = _baseURL; +@synthesize timeout = _timeout; + ++ (MMHTTPClient *) sharedClient +{ + if (!_client) { + _client = [[self alloc] init]; + } + return _client; +} + ++ (id) client +{ + return [[self alloc] init]; +} + ++ (id) clientWithBaseURL: (NSString *)baseURL +{ + return [[self alloc] initWithBaseURL: baseURL]; +} + ++ (id) clientWithBaseURL: (NSString *)baseURL timeout: (NSUInteger)timeout +{ + return [[self alloc] initWithBaseURL: baseURL timeout: timeout]; +} + ++ (NSString *) pathFor: (NSString *)first, ... +{ + va_list args; + va_start(args, first); + NSString *url = JoinURLComponents(first, args); + va_end(args); + return url; +} + ++ (NSString *) urlFor: (NSString *)first, ... +{ + va_list args; + va_start(args, first); + NSString *url = [[[self sharedClient] baseURL] stringByAppendingString: JoinURLComponents(first, args)]; + va_end(args); + return url; +} + ++ (NSString *) urlWithPath: (NSString *)path +{ + return [[[self sharedClient] baseURL] stringByAppendingPathComponent: path]; +} + ++ (MMHTTPRequest *) request: (NSDictionary *)options then: (MMHTTPCallback)callback +{ + return [[self sharedClient] request: options then: callback]; +} + ++ (MMHTTPRequest *) get: (NSString *)url then: (MMHTTPCallback)callback +{ + return [[self sharedClient] get: url then: callback]; +} + ++ (MMHTTPRequest *) getImage: (NSString *)url then: (MMHTTPImageCallback)callback +{ + return [[self sharedClient] getImage: url then: callback]; +} + ++ (MMHTTPRequest *) getText: (NSString *)url then: (MMHTTPTextCallback)callback +{ + return [[self sharedClient] getText: url then: callback]; +} + ++ (MMHTTPRequest *) post: (NSString *)url then: (MMHTTPCallback)callback +{ + return [[self sharedClient] post: url then: callback]; +} + ++ (MMHTTPRequest *) post: (NSString *)url fields: (NSDictionary *)fields then: (MMHTTPCallback)callback +{ + return [[self sharedClient] post: url fields: fields then: callback]; +} + ++ (MMHTTPRequest *) post: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback +{ + return [[self sharedClient] post: url data: data then: callback]; +} + ++ (MMHTTPRequest *) put: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback +{ + return [[self sharedClient] put: url data: data then: callback]; +} + ++ (MMHTTPRequest *) delete: (NSString *)url then: (MMHTTPCallback)callback +{ + return [[self sharedClient] delete: url then: callback]; +} + +- (id) init +{ + return [self initWithBaseURL: nil timeout: MMHTTPRequestDefaultTimeout]; +} + +- (id) initWithBaseURL: (NSString *)baseURL +{ + return [self initWithBaseURL: baseURL timeout: MMHTTPRequestDefaultTimeout]; +} + +- (id) initWithBaseURL: (NSString *)baseURL timeout: (NSUInteger)timeout +{ + self = [super init]; + if (self) { + _baseURL = [baseURL copy]; + _timeout = timeout; + } + return self; +} + +- (NSString *) pathFor: (NSString *)first, ... +{ + va_list args; + va_start(args, first); + NSString *url = JoinURLComponents(first, args); + va_end(args); + return url; +} + +- (NSString *) urlFor: (NSString *)first, ... +{ + va_list args; + va_start(args, first); + NSString *url = [_baseURL stringByAppendingString: JoinURLComponents(first, args)]; + va_end(args); + return url; +} + +- (NSString *) urlWithPath: (NSString *)path +{ + return [_baseURL stringByAppendingPathComponent: path]; +} + +- (MMHTTPRequest *) getImage: (NSString *)url then: (MMHTTPImageCallback)callback +{ + return [self request: [NSDictionary dictionary] then: (MMHTTPCallback)callback]; +} + +- (MMHTTPRequest *) getText: (NSString *)url then: (MMHTTPTextCallback)callback +{ + NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: + url, @"url", + @"text", @"type", + nil]; + return [self request: options then: (MMHTTPCallback)callback]; +} + +- (MMHTTPRequest *) get: (NSString *)url then: (MMHTTPCallback)callback +{ + NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: + url, @"url", + @"image", @"type", + nil]; + return [self request: options then: (MMHTTPCallback)callback]; +} + +- (MMHTTPRequest *) post: (NSString *)url then: (MMHTTPCallback)callback +{ + NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: + @"POST", @"method", + url, @"url", + nil]; + return [self request: options then: callback]; +} + +- (MMHTTPRequest *) post: (NSString *)url fields: (NSDictionary *)fields then: (MMHTTPCallback)callback +{ + NSMutableArray *parts = [NSMutableArray array]; + NSString *value; + for (NSString *key in [fields keyEnumerator]) { + value = [fields objectForKey: key]; + [parts addObject: [NSString stringWithFormat: @"%@=%@", [key stringByURLEncoding], [value stringByURLEncoding]]]; + } + NSString *body = [parts componentsJoinedByString: @"&"]; + return [self post: url data: [body dataUsingEncoding: NSUTF8StringEncoding] then: callback]; +} + +- (MMHTTPRequest *) post: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback +{ + NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: + @"POST", @"method", + url, @"url", + data, @"data", + nil]; + return [self request: options then: callback]; +} + +- (MMHTTPRequest *) put: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback +{ + NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: + @"PUT", @"method", + url, @"url", + data, @"data", + nil]; + return [self request: options then: callback]; +} + +- (MMHTTPRequest *) delete: (NSString *)url then: (MMHTTPCallback)callback +{ + NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: + @"DELETE", @"method", + url, @"url", + nil]; + return [self request: options then: callback]; +} + +- (MMHTTPRequest *) request: (NSDictionary *)options then: (MMHTTPCallback)callback +{ + NSString *url = [options objectForKey: @"url"]; + NSMutableDictionary *mutableOptions = [options mutableCopy]; + if (_baseURL && !([url hasPrefix: @"http:"] || [url hasPrefix: @"https:"])) { + [mutableOptions setObject: [self urlWithPath: url] forKey: @"url"]; + } + NSUInteger timeout = [[options objectForKey: @"timeout"] unsignedIntValue]; + if (timeout == 0) { + [mutableOptions setValue: [NSNumber numberWithUnsignedInt: self.timeout] forKey: @"timeout"]; + } + options = [NSDictionary dictionaryWithDictionary: mutableOptions]; + return [MMHTTPRequest requestWithOptions: options callback: callback]; +} + +@end diff --git a/5by5Browser/MMHTTPRequest.h b/5by5Browser/MMHTTPRequest.h new file mode 100644 index 0000000..7448024 --- /dev/null +++ b/5by5Browser/MMHTTPRequest.h @@ -0,0 +1,43 @@ +// +// MMHTTPRequest.h +// Marshmallows +// +// Created by Sami Samhuri on 11-09-03. +// Copyright 2011 Guru Logic. All rights reserved. +// + +#import +#import + +#define MMHTTPRequestStatusError -1 +#define MMHTTPRequestDefaultTimeout 120 + +typedef void (^MMHTTPCallback)(NSInteger status, id data); +typedef void (^MMHTTPTextCallback)(NSInteger status, NSString *text); +typedef void (^MMHTTPImageCallback)(NSInteger status, UIImage *image); + +@interface MMHTTPRequest : NSObject +{ + NSMutableData *_responseData; +} + +@property (nonatomic, retain) NSURLConnection *connection; +@property (nonatomic, retain) NSMutableURLRequest *request; +@property (nonatomic, retain) NSString *method; +@property (nonatomic, retain) NSString *url; +@property (nonatomic, retain) NSMutableDictionary *headers; +@property (nonatomic, retain) NSData *data; +@property (nonatomic, retain) NSString *type; +@property (nonatomic, copy) MMHTTPCallback callback; +@property NSUInteger timeout; +@property (readonly) NSInteger statusCode; +@property (readonly) NSDictionary *responseHeaders; +@property (readonly) NSData *responseData; +@property (readonly) NSString *responseText; +@property (readonly) UIImage *responseImage; + ++ (id) requestWithOptions: (NSDictionary *)options callback: (MMHTTPCallback)callback; +- (id) initWithOptions: (NSDictionary *)options callback: (MMHTTPCallback)callback; +- (void) cancel; + +@end diff --git a/5by5Browser/MMHTTPRequest.m b/5by5Browser/MMHTTPRequest.m new file mode 100644 index 0000000..d79b9c6 --- /dev/null +++ b/5by5Browser/MMHTTPRequest.m @@ -0,0 +1,147 @@ +// +// MMHTTPRequest.m +// Marshmallows +// +// Created by Sami Samhuri on 11-09-03. +// Copyright 2011 Guru Logic. All rights reserved. +// + +#import "MMHTTPRequest.h" + +@interface MMHTTPRequest () +- (void) _start; +@end + + +@implementation MMHTTPRequest + +@synthesize connection = _connection; +@synthesize request = _request; +@synthesize method = _method; +@synthesize url = _url; +@synthesize headers = _headers; +@synthesize data = _data; +@synthesize type = _type; +@synthesize callback = _callback; +@synthesize timeout = _timeout; +@synthesize statusCode = _statusCode; +@synthesize responseHeaders = _responseHeaders; + ++ (id) requestWithOptions: (NSDictionary *)options callback: (MMHTTPCallback)callback +{ + return [[self alloc] initWithOptions: options callback: callback]; +} + +- (id) initWithOptions: (NSDictionary *)options callback: (MMHTTPCallback)callback +{ + self = [super init]; + if (self) { + self.callback = [callback copy]; + self.timeout = MMHTTPRequestDefaultTimeout; + self.method = [options objectForKey: @"method"]; + self.url = [options objectForKey: @"url"]; + self.headers = [options objectForKey: @"headers"]; + self.data = [options objectForKey: @"data"]; + self.type = [options objectForKey: @"type"]; + if (!self.method) self.method = @"GET"; + [self _start]; + } + return self; +} + +- (void) cancel +{ + [_connection cancel]; +} + +- (NSData *) responseData +{ + return [NSData dataWithData: _responseData]; +} + +- (NSString *) responseText +{ + return [[NSString alloc] initWithBytes: _responseData.bytes + length: _responseData.length + encoding: NSUTF8StringEncoding]; +} + +- (UIImage *) responseImage +{ + return [UIImage imageWithData: _responseData]; +} + +- (void) _start +{ + self.request = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: self.url] + cachePolicy: NSURLRequestUseProtocolCachePolicy + timeoutInterval: self.timeout]; + [self.request setHTTPMethod: self.method]; + + if (self.data && ([self.method isEqualToString: @"POST"] || [self.method isEqualToString: @"PUT"])) { + [self.request setHTTPBody: self.data]; + } + + if (self.headers) { + for (NSString *key in self.headers) { + [self.request setValue: [self.headers objectForKey: key] forHTTPHeaderField: key]; + } + } + + self.connection = [NSURLConnection connectionWithRequest: self.request delegate: self]; + [self.connection start]; +} + +#pragma mark - NSURLConnection delegate methods + +- (void) connection: (NSURLConnection *)connection didReceiveResponse: (NSURLResponse *)response +{ +// NSLog(@"didReceiveResponse: %@",response); + if ([response respondsToSelector: @selector(statusCode)]) + { + _statusCode = [(NSHTTPURLResponse *)response statusCode]; + _responseHeaders = [(NSHTTPURLResponse *)response allHeaderFields]; + } + else { + NSLog(@"Not an HTTP response? connection: %@ response: %@", connection, response); + _statusCode = 500; + _responseHeaders = [[NSDictionary alloc] init]; + } + + _responseData = [[NSMutableData alloc] init]; +} + +- (void) connection: (NSURLConnection *)connection didReceiveData: (NSData *)data +{ +// NSLog(@"didReceiveData: %@", data); + [_responseData appendData: data]; +} + +- (void) connection: (NSURLConnection *)connection didFailWithError: (NSError *)error +{ + NSLog(@"didFailWithError: %@", error); + _responseData = nil; + _statusCode = MMHTTPRequestStatusError; + self.callback(self.statusCode, error); +} + +- (void) connectionDidFinishLoading: (NSURLConnection *)connection +{ +// NSLog(@"didFinishLoading: %d", self.statusCode); + id data = nil; + if (self.statusCode == 200) { + if ([self.type isEqualToString: @"text"]) { + data = self.responseText; + } + else if ([self.type isEqualToString: @"image"]) { + data = self.responseImage; + } + else { + data = self.responseData; + } + } + + self.callback(self.statusCode, data); +} + +@end diff --git a/5by5Browser/NSString+marshmallows.h b/5by5Browser/NSString+marshmallows.h new file mode 100644 index 0000000..57b2f10 --- /dev/null +++ b/5by5Browser/NSString+marshmallows.h @@ -0,0 +1,19 @@ +// +// NSString+marshmallows.h +// Marshmallows +// +// Created by Sami Samhuri on 11-09-03. +// Copyright 2011 Guru Logic. All rights reserved. +// + +#import + +@interface NSString (NSString_marshmallows) + +- (NSString *) firstMatch: (NSString *)pattern; +- (NSString *) stringByReplacing: (NSString *)pattern with: (NSString *)replacement; +- (NSString *) stringByReplacingFirst: (NSString *)pattern with: (NSString *)replacement; +- (NSString *) stringByTrimmingWhitespace; +- (NSString *) stringByURLEncoding; + +@end diff --git a/5by5Browser/NSString+marshmallows.m b/5by5Browser/NSString+marshmallows.m new file mode 100644 index 0000000..5267c83 --- /dev/null +++ b/5by5Browser/NSString+marshmallows.m @@ -0,0 +1,76 @@ +// +// NSString+marshmallows.m +// Marshmallows +// +// Created by Sami Samhuri on 11-09-03. +// Copyright 2011 Guru Logic. All rights reserved. +// + +#import "NSString+marshmallows.h" + +// Encode a string to embed in an URL. +NSString* URLEncode(NSString *string) { + return (__bridge NSString *) + CFURLCreateStringByAddingPercentEscapes(NULL, + (__bridge CFStringRef) string, + NULL, + (CFStringRef) @"!*'();:@&=+$,/?%#[]", + kCFStringEncodingUTF8); +} + + +@implementation NSString (NSString_marshmallows) + +- (NSString *) stringByTrimmingWhitespace +{ + return [self stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; +} + +- (NSString *) firstMatch: (NSString *)pattern +{ + NSRegularExpression *regex = [NSRegularExpression + regularExpressionWithPattern: pattern + options: 0 + error: NULL]; + NSRange match = [regex rangeOfFirstMatchInString: self + options: NSMatchingCompleted + range: NSMakeRange(0, self.length)]; + return match.location == NSNotFound ? nil : [self substringWithRange: match]; +} + +- (NSString *) stringByReplacing: (NSString *)pattern with: (NSString *)replacement +{ + NSRegularExpression *regex = [NSRegularExpression + regularExpressionWithPattern: pattern + options: NSRegularExpressionCaseInsensitive + error: NULL]; + return [regex stringByReplacingMatchesInString: self + options: NSMatchingCompleted + range: NSMakeRange(0, [self length]) + withTemplate: @""]; +} + +- (NSString *) stringByReplacingFirst: (NSString *)pattern with: (NSString *)replacement +{ + NSRegularExpression *regex = [NSRegularExpression + regularExpressionWithPattern: pattern + options: 0 + error: NULL]; + NSRange match = [regex rangeOfFirstMatchInString: self + options: NSMatchingCompleted + range: NSMakeRange(0, self.length)]; + if (match.location != NSNotFound) { + NSString *rest = [self substringFromIndex: match.location + match.length]; + return [[[self substringToIndex: match.location] + stringByAppendingString: replacement] + stringByAppendingString: rest]; + } + return [self copy]; +} + +- (NSString *) stringByURLEncoding +{ + return URLEncode(self); +} + +@end diff --git a/5by5Browser/SSAppDelegate.m b/5by5Browser/SSAppDelegate.m index 8105000..bec0a9d 100644 --- a/5by5Browser/SSAppDelegate.m +++ b/5by5Browser/SSAppDelegate.m @@ -25,7 +25,7 @@ FiveByFive *fiveByFive = [[FiveByFive alloc] initWithBaseURL: @"http:/feeds.feedburner.com/"]; [fiveByFive addShow: [Show showWithName: @"Back to Work" path: @"back2work"]]; [fiveByFive addShow: [Show showWithName: @"Build and Analyze" path: @"buildanalyze"]]; - [fiveByFive addShow: [Show showWithName: @"Critical Path" path: @"criticalpath"]]; + [fiveByFive addShow: [Show showWithName: @"The Critical Path" path: @"criticalpath"]]; [fiveByFive addShow: [Show showWithName: @"Geek Friday" path: @"GeekFriday"]]; [fiveByFive addShow: [Show showWithName: @"Hypercritical" path: @"hypercritical"]]; [fiveByFive addShow: [Show showWithName: @"The Talk Show" path: @"thetalkshow"]]; @@ -35,13 +35,16 @@ SSMasterViewController *masterViewController = [[SSMasterViewController alloc] initWithNibName:@"SSMasterViewController_iPhone" bundle:nil]; masterViewController.fiveByFive = fiveByFive; self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController]; + [self.navigationController.navigationBar setTintColor: [UIColor colorWithWhite: 0.3 alpha: 1.0]]; self.window.rootViewController = self.navigationController; } else { SSMasterViewController *masterViewController = [[SSMasterViewController alloc] initWithNibName:@"SSMasterViewController_iPad" bundle:nil]; UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController]; + [masterNavigationController.navigationBar setTintColor: [UIColor colorWithWhite: 0.3 alpha: 1.0]]; SSDetailViewController *detailViewController = [[SSDetailViewController alloc] initWithNibName:@"SSDetailViewController_iPad" bundle:nil]; UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController]; + [detailNavigationController.navigationBar setTintColor: [UIColor colorWithWhite: 0.3 alpha: 1.0]]; masterViewController.fiveByFive = fiveByFive; diff --git a/5by5Browser/SSDetailViewController.h b/5by5Browser/SSDetailViewController.h index 4bdc17c..2464b0b 100644 --- a/5by5Browser/SSDetailViewController.h +++ b/5by5Browser/SSDetailViewController.h @@ -14,9 +14,13 @@ @property (strong, nonatomic) Episode *episode; @property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel; @property (strong, nonatomic) IBOutlet UIWebView *webView; +@property (strong, nonatomic) IBOutlet UIToolbar *toolbar; @property (strong, nonatomic) IBOutlet UIBarButtonItem *backButton; @property (strong, nonatomic) IBOutlet UIBarButtonItem *forwardButton; +@property (strong, nonatomic) IBOutlet UIBarButtonItem *instapaperButton; +@property (strong, nonatomic) IBOutlet UIView *loadingView; -- (IBAction) goHome; +- (IBAction) goHome: (id)sender; +- (IBAction)sendToInstapaper: (id)sender; @end diff --git a/5by5Browser/SSDetailViewController.m b/5by5Browser/SSDetailViewController.m index cc3bdbe..233afc4 100644 --- a/5by5Browser/SSDetailViewController.m +++ b/5by5Browser/SSDetailViewController.m @@ -7,6 +7,9 @@ // #import "SSDetailViewController.h" +#import "MMHTTPClient.h" +#import "InstapaperCredentials.h" +#import "UIAlertView+marshmallows.h" @interface SSDetailViewController () @property (strong, nonatomic) UIPopoverController *masterPopoverController; @@ -18,8 +21,11 @@ @synthesize episode = _episode; @synthesize detailDescriptionLabel = _detailDescriptionLabel; @synthesize webView = _webView; +@synthesize toolbar = _toolbar; @synthesize backButton = _backButton; @synthesize forwardButton = _forwardButton; +@synthesize instapaperButton = _instapaperButton; +@synthesize loadingView = _loadingView; @synthesize masterPopoverController = _masterPopoverController; #pragma mark - Managing the detail item @@ -40,19 +46,16 @@ - (void)configureView { - // Update the user interface for the detail item. - if (self.episode) { self.title = self.episode.name; self.detailDescriptionLabel.text = self.episode.name; - [self.webView loadRequest: [NSURLRequest requestWithURL: self.episode.url]]; + [self goHome: nil]; } } - (void)viewDidLoad { [super viewDidLoad]; - // Do any additional setup after loading the view, typically from a nib. [self configureView]; } @@ -61,6 +64,9 @@ [self setWebView:nil]; [self setBackButton:nil]; [self setForwardButton:nil]; + [self setInstapaperButton:nil]; + [self setToolbar:nil]; + [self setLoadingView:nil]; [super viewDidUnload]; // Release any retained subviews of the main view. self.detailDescriptionLabel = nil; @@ -75,17 +81,50 @@ } } +- (void) webViewDidStartLoad: (UIWebView *)webView +{ + [UIView animateWithDuration: 1.0 animations: ^{ + self.loadingView.alpha = 1.0; + }]; +} + - (void) webViewDidFinishLoad: (UIWebView *)webView { + [UIView animateWithDuration: 0.3 animations: ^{ + self.loadingView.alpha = 0.0; + }]; [self.backButton setEnabled: webView.canGoBack]; [self.forwardButton setEnabled: webView.canGoForward]; } -- (IBAction) goHome +- (IBAction) goHome: (id)sender { - while (self.webView.canGoBack) { - [self.webView goBack]; - } + [self.webView loadRequest: [NSURLRequest requestWithURL: self.episode.url]]; +} + +- (IBAction) sendToInstapaper: (id)sender +{ + NSString *url = self.webView.request.URL.absoluteString; + NSDictionary *fields = [NSDictionary dictionaryWithObjectsAndKeys: + kInstapaperUser, @"username", + kInstapaperPassword, @"password", + url, @"url", + nil]; + + UIActivityIndicatorView *indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhite]; + [indicatorView startAnimating]; + UIBarButtonItem *indicatorItem = [[UIBarButtonItem alloc] initWithCustomView: indicatorView]; + NSMutableArray *items = [[self.toolbar items] mutableCopy]; + NSInteger i = [items indexOfObject: self.instapaperButton]; + [items replaceObjectAtIndex: i withObject: indicatorItem]; + [self.toolbar setItems: items]; + [MMHTTPClient post: @"https://www.instapaper.com/api/add" fields: fields then: ^(NSInteger status, id data) { + [items replaceObjectAtIndex: i withObject: self.instapaperButton]; + [self.toolbar setItems: items]; + if (status != 201) { + [UIAlertView showAlertWithTitle: @"Error" message: @"Failed to send to Instapaper. Try again later."]; + } + }]; } #pragma mark - Split view diff --git a/5by5Browser/SSMasterViewController.m b/5by5Browser/SSMasterViewController.m index 823ef6b..6ade02b 100644 --- a/5by5Browser/SSMasterViewController.m +++ b/5by5Browser/SSMasterViewController.m @@ -107,7 +107,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [[self.fiveByFive.shows objectAtIndex: indexPath.row] getEpisodes]; - UIActivityIndicatorView *indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleGray]; + UIActivityIndicatorView *indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhite]; [indicatorView startAnimating]; [tableView cellForRowAtIndexPath: indexPath].accessoryView = indicatorView; } diff --git a/5by5Browser/Show.h b/5by5Browser/Show.h index effdcfc..bcb3381 100644 --- a/5by5Browser/Show.h +++ b/5by5Browser/Show.h @@ -11,6 +11,8 @@ #import "Episode.h" #import "FiveByFive.h" +@class Episode; + @protocol ShowDelegate - (void) gotEpisodesForShow: (Show *)show; @end diff --git a/5by5Browser/Show.m b/5by5Browser/Show.m index 8037b14..0b738c2 100644 --- a/5by5Browser/Show.m +++ b/5by5Browser/Show.m @@ -79,7 +79,8 @@ - (void) feedParser: (MWFeedParser *)parser didParseFeedItem: (MWFeedItem *)item { NSLog(@"feed item: %@", item); - [self addEpisode: [Episode episodeWithName: item.title number: @"" url: [NSURL URLWithString: item.link]]]; + NSLog(@"show name: %@", self.name); + [self addEpisode: [Episode episodeWithShow: self name: item.title number: @"" url: [NSURL URLWithString: item.link]]]; } - (void) feedParserDidFinish: (MWFeedParser *)parser diff --git a/5by5Browser/UIAlertView+marshmallows.h b/5by5Browser/UIAlertView+marshmallows.h new file mode 100644 index 0000000..b24b882 --- /dev/null +++ b/5by5Browser/UIAlertView+marshmallows.h @@ -0,0 +1,17 @@ +// +// UIAlertView+marshmallows.h +// DatingX +// +// Created by Sami Samhuri on 11-08-24. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#import + +typedef void (^UIAlertViewCallback)(BOOL ok); + +@interface UIAlertView (UIAlertView_marshmallows) + ++ (void) showAlertWithTitle: (NSString *)title message: (NSString *)message; + +@end diff --git a/5by5Browser/UIAlertView+marshmallows.m b/5by5Browser/UIAlertView+marshmallows.m new file mode 100644 index 0000000..b2dac01 --- /dev/null +++ b/5by5Browser/UIAlertView+marshmallows.m @@ -0,0 +1,32 @@ +// +// UIAlertView+marshmallows.m +// DatingX +// +// Created by Sami Samhuri on 11-08-24. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#import "UIAlertView+marshmallows.h" +#import "UIAlertViewDelegate.h" + +@implementation UIAlertView (UIAlertView_marshmallows) + ++ (void) showAlertWithTitle: (NSString *)title message: (NSString *)message +{ + [[[self alloc] initWithTitle: title + message: message + delegate: nil + cancelButtonTitle: @"OK" + otherButtonTitles: nil] show]; +} + ++ (void) confirmWithTitle: (NSString *)title message: (NSString *)message then: (UIAlertViewCallback)callback +{ + [[[self alloc] initWithTitle: title + message: message + delegate: [UIAlertViewDelegate alertViewDelegateWithCallback: callback] + cancelButtonTitle: @"Cancel" + otherButtonTitles: @"OK", nil] show]; +} + +@end diff --git a/5by5Browser/UIAlertViewDelegate.h b/5by5Browser/UIAlertViewDelegate.h new file mode 100644 index 0000000..997526a --- /dev/null +++ b/5by5Browser/UIAlertViewDelegate.h @@ -0,0 +1,20 @@ +// +// UIAlertViewDelegate.h +// Marshmallows +// +// Created by Sami Samhuri on 11-09-05. +// Copyright 2011 Guru Logic. All rights reserved. +// + +#import +#import "UIAlertView+marshmallows.h" + +@interface UIAlertViewDelegate : NSObject +{ + UIAlertViewCallback _callback; +} + ++ (id) alertViewDelegateWithCallback: (UIAlertViewCallback)callback; +- (id) initWithCallback: (UIAlertViewCallback)callback; + +@end diff --git a/5by5Browser/UIAlertViewDelegate.m b/5by5Browser/UIAlertViewDelegate.m new file mode 100644 index 0000000..ee77b8b --- /dev/null +++ b/5by5Browser/UIAlertViewDelegate.m @@ -0,0 +1,33 @@ +// +// UIAlertViewDelegate.m +// Marshmallows +// +// Created by Sami Samhuri on 11-09-05. +// Copyright 2011 Guru Logic. All rights reserved. +// + +#import "UIAlertViewDelegate.h" + +@implementation UIAlertViewDelegate + ++ (id) alertViewDelegateWithCallback: (UIAlertViewCallback)callback +{ + return [[self alloc] initWithCallback: callback]; +} + +- (id) initWithCallback: (UIAlertViewCallback)callback +{ + self = [super init]; + if (self) { + _callback = callback; + } + return self; +} + +- (void) alertView: (UIAlertView *)alertView clickedButtonAtIndex: (NSInteger)buttonIndex +{ + BOOL ok = (buttonIndex == 1); + _callback(ok); +} + +@end diff --git a/5by5Browser/en.lproj/SSDetailViewController_iPhone.xib b/5by5Browser/en.lproj/SSDetailViewController_iPhone.xib index bec91ce..716bd44 100644 --- a/5by5Browser/en.lproj/SSDetailViewController_iPhone.xib +++ b/5by5Browser/en.lproj/SSDetailViewController_iPhone.xib @@ -14,6 +14,7 @@ IBUIWebView IBUIBarButtonItem IBUIToolbar + IBUIActivityIndicatorView IBUIView IBProxyObject @@ -43,7 +44,7 @@ {320, 416} - + _NS:693 1 @@ -85,6 +86,20 @@ IBCocoaTouchFramework 1 + + 1 + MC4zMjE1Njg2Mjc1IDAgMAA + + + + Instapaper + IBCocoaTouchFramework + 1 + + + 1 + MC4zMjE1Njg2Mjc1IDAgMAA + IBCocoaTouchFramework @@ -101,6 +116,40 @@ + + 3 + MC4zMzMzMzMzMzMzAA + + + + + 274 + + + + 301 + {{142, 189}, {37, 37}} + + + + _NS:1030 + NO + IBCocoaTouchFramework + NO + YES + 0 + + + {320, 416} + + + + _NS:196 + + 1 + MCAwIDAgMC42AA + + IBCocoaTouchFramework {{0, 20}, {320, 460}} @@ -152,6 +201,30 @@ 19 + + + instapaperButton + + + + 23 + + + + toolbar + + + + 24 + + + + loadingView + + + + 28 + delegate @@ -178,11 +251,19 @@ - goHome + goHome: - 20 + 25 + + + + sendToInstapaper: + + + + 22 @@ -198,6 +279,7 @@ + @@ -227,6 +309,7 @@ + @@ -257,6 +340,24 @@ + + 21 + + + + + 26 + + + + + + + + 27 + + + @@ -271,34 +372,43 @@ com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 20 + 28 SSDetailViewController UIViewController - - goHome - id - - - goHome - - goHome + + id + id + + + + goHome: id - + + sendToInstapaper: + id + + UIBarButtonItem UILabel UIBarButtonItem + UIBarButtonItem + UIView + UIToolbar UIWebView @@ -314,6 +424,18 @@ forwardButton UIBarButtonItem + + instapaperButton + UIBarButtonItem + + + loadingView + UIView + + + toolbar + UIToolbar + webView UIWebView