Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #5 from shazron/view-extraction

Integrate Cleaver into the core
  • Loading branch information...
commit 0f24ec3461298241855fd31bf66e65244f3093fd 2 parents 49a1864 + df67ab5
Jesse MacFadyen authored
View
8 PhoneGap-based Application/Classes/AppDelegate.h
@@ -8,12 +8,14 @@
#import <UIKit/UIKit.h>
#ifdef PHONEGAP_FRAMEWORK
- #import <PhoneGap/PhoneGapDelegate.h>
+ #import <PhoneGap/PGAppDelegate.h>
+ #import <PhoneGap/PGViewController.h>
#else
- #import "PhoneGapDelegate.h"
+ #import "PGAppDelegate.h"
+ #import "PGViewController.h"
#endif
-@interface AppDelegate : PhoneGapDelegate {
+@interface AppDelegate : PGAppDelegate < PGCommandDelegate > {
NSString* invokeString;
}
View
72 PhoneGap-based Application/Classes/AppDelegate.m
@@ -7,11 +7,6 @@
//
#import "AppDelegate.h"
-#ifdef PHONEGAP_FRAMEWORK
- #import <PhoneGap/PhoneGapViewController.h>
-#else
- #import "PhoneGapViewController.h"
-#endif
@implementation AppDelegate
@@ -28,7 +23,7 @@ - (id) init
/**
* This is main kick off after the app inits, the views and Settings are setup here. (preferred - iOS4 and up)
*/
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
NSURL* url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
if (url && [url isKindOfClass:[NSURL class]])
@@ -37,33 +32,39 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
NSLog(@"___PROJECTNAME___ launchOptions = %@",url);
}
- return [super application:application didFinishLaunchingWithOptions:launchOptions];
+ BOOL ok = [super application:application didFinishLaunchingWithOptions:launchOptions];
+ if (ok) {
+ self.viewController.webView.delegate = self;
+ self.viewController.commandDelegate = self;
+ }
+ return ok;
}
// this happens while we are running ( in the background, or from within our own app )
// only valid if ___PROJECTNAME___.plist specifies a protocol to handle
-- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
+- (BOOL) application:(UIApplication*)application handleOpenURL:(NSURL*)url
{
// must call super so all plugins will get the notification, and their handlers will be called
// super also calls into javascript global function 'handleOpenURL'
return [super application:application handleOpenURL:url];
}
--(id) getCommandInstance:(NSString*)className
+- (id) getCommandInstance:(NSString*)className
{
- /** You can catch your own commands here, if you wanted to extend the gap: protocol, or add your
- * own app specific protocol to it. -jm
- **/
- return [super getCommandInstance:className];
+ return [super.viewController getCommandInstance:className];
}
-/**
- Called when the webview finishes loading. This stops the activity view and closes the imageview
- */
-- (void)webViewDidFinishLoad:(UIWebView *)theWebView
+- (BOOL) execute:(InvokedUrlCommand*)command
+{
+ return [super.viewController execute:command];
+}
+
+#pragma UIWebDelegate implementation
+
+- (void) webViewDidFinishLoad:(UIWebView*) theWebView
{
// only valid if ___PROJECTNAME___.plist specifies a protocol to handle
- if(self.invokeString)
+ if (self.invokeString)
{
// this is passed before the deviceready event is fired, so you can access it in js when you receive deviceready
NSString* jsString = [NSString stringWithFormat:@"var invokeString = \"%@\";", self.invokeString];
@@ -73,42 +74,27 @@ - (void)webViewDidFinishLoad:(UIWebView *)theWebView
// Black base color for background matches the native apps
theWebView.backgroundColor = [UIColor blackColor];
- return [ super webViewDidFinishLoad:theWebView ];
+ return [super.viewController webViewDidFinishLoad:theWebView];
}
-- (void)webViewDidStartLoad:(UIWebView *)theWebView
+- (void) webViewDidStartLoad:(UIWebView*)theWebView
{
- return [ super webViewDidStartLoad:theWebView ];
+ return [super.viewController webViewDidStartLoad:theWebView];
}
-/**
- * Fail Loading With Error
- * Error - If the webpage failed to load display an error with the reason.
- */
-- (void)webView:(UIWebView *)theWebView didFailLoadWithError:(NSError *)error
-{
- return [ super webView:theWebView didFailLoadWithError:error ];
-}
-
-/**
- * Start Loading Request
- * This is where most of the magic happens... We take the request(s) and process the response.
- * From here we can redirect links and other protocols to different internal methods.
- */
-- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
+- (void) webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
{
- return [ super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType ];
+ return [super.viewController webView:theWebView didFailLoadWithError:error];
}
-
-- (BOOL) execute:(InvokedUrlCommand*)command
+- (BOOL) webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
- return [ super execute:command];
+ return [super.viewController webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType];
}
-- (void)dealloc
+- (void) dealloc
{
- [ super dealloc ];
+ [super dealloc];
}
-@end
+@end
View
5 PhoneGapLib/Classes/Camera.m
@@ -11,7 +11,7 @@
#import "Camera.h"
#import "NSData+Base64.h"
#import "Categories.h"
-#import "PhonegapDelegate.h"
+#import "PGAppDelegate.h"
#import <MobileCoreServices/UTCoreTypes.h>
@implementation PGCamera
@@ -97,8 +97,7 @@ - (void) getPicture:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)op
}
else
{
- [[super appViewController]
- presentModalViewController:self.pickerController animated:YES];
+ [self.viewController presentModalViewController:self.pickerController animated:YES];
}
}
}
View
38 PhoneGapLib/Classes/Capture.m
@@ -8,7 +8,8 @@
#import "Capture.h"
#import "JSONKit.h"
-#import "PhoneGapDelegate.h"
+#import "PGAppDelegate.h"
+#import "PGViewController.h"
#define kW3CMediaFormatHeight @"height"
#define kW3CMediaFormatWidth @"width"
@@ -84,7 +85,7 @@ - (void) captureAudio:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:audioViewController] autorelease];
self.inUse = YES;
- [self.appViewController presentModalViewController:navController animated: YES];
+ [self.viewController presentModalViewController:navController animated: YES];
}
if (result) {
@@ -129,7 +130,7 @@ - (void) captureImage:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)
pickerController.callbackId = callbackId;
pickerController.mimeType = mode;
- [[super appViewController] presentModalViewController:pickerController animated:YES];
+ [self.viewController presentModalViewController:pickerController animated:YES];
}
}
@@ -244,7 +245,7 @@ - (void) captureVideo:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)
// PGImagePicker specific property
pickerController.callbackId = callbackId;
- [[super appViewController] presentModalViewController:pickerController animated:YES];
+ [self.viewController presentModalViewController:pickerController animated:YES];
}
}
@@ -338,12 +339,17 @@ - (void) getFormatData: (NSMutableArray*)arguments withDict:(NSMutableDictionary
if (!mimeType){
// try to determine mime type if not provided
- PGFile* pgFile = [[self appDelegate] getCommandInstance: @"com.phonegap.file"];
- mimeType = [pgFile getMimeTypeFromPath:fullPath];
- if (!mimeType) {
- // can't do much without mimeType, return error
- bError = YES;
- errorCode = CAPTURE_INVALID_ARGUMENT;
+ PGViewController* vc = (PGViewController*)self.viewController;
+ id command = [vc getCommandInstance: @"com.phonegap.file"];
+ bError = !([command isKindOfClass:[PGFile class]]);
+ if (!bError) {
+ PGFile* pgFile = (PGFile*)command;
+ mimeType = [pgFile getMimeTypeFromPath:fullPath];
+ if (!mimeType) {
+ // can't do much without mimeType, return error
+ bError = YES;
+ errorCode = CAPTURE_INVALID_ARGUMENT;
+ }
}
}
if (!bError) {
@@ -421,9 +427,13 @@ -(NSDictionary*) getMediaDictionaryFromPath: (NSString*) fullPath ofType: (NSStr
[fileDict setObject: fullPath forKey:@"fullPath"];
// determine type
if(!type) {
- PGFile* pgFile = [[self appDelegate] getCommandInstance: @"com.phonegap.file"];
- NSString* mimeType = [pgFile getMimeTypeFromPath:fullPath];
- [fileDict setObject: (mimeType != nil ? (NSObject*)mimeType : [NSNull null]) forKey:@"type"];
+ PGViewController* vc = (PGViewController*)self.viewController;
+ id command = [vc getCommandInstance: @"com.phonegap.file"];
+ if([command isKindOfClass:[PGFile class]]) {
+ PGFile* pgFile = (PGFile*)command;
+ NSString* mimeType = [pgFile getMimeTypeFromPath:fullPath];
+ [fileDict setObject: (mimeType != nil ? (NSObject*)mimeType : [NSNull null]) forKey:@"type"];
+ }
}
NSDictionary* fileAttrs = [fileMgr attributesOfItemAtPath:fullPath error:nil];
[fileDict setObject: [NSNumber numberWithUnsignedLongLong:[fileAttrs fileSize]] forKey:@"size"];
@@ -755,7 +765,7 @@ - (void) stopRecordingCleanup
- (void) dismissAudioView: (id) sender
{
// called when done button pressed or when error condition to do cleanup and remove view
- [self.captureCommand.appViewController.modalViewController dismissModalViewControllerAnimated:YES];
+ [self.captureCommand.viewController.modalViewController dismissModalViewControllerAnimated:YES];
if (!self.resultString) {
// return error
PluginResult* result = [PluginResult resultWithStatus:PGCommandStatus_OK messageToErrorObject:self.errorCode];
View
2  PhoneGapLib/Classes/Contact.m
@@ -9,7 +9,7 @@
#import "Contact.h"
#import "Categories.h"
-#import "PhoneGapDelegate.h"
+#import "PGAppDelegate.h"
#define DATE_OR_NULL(dateObj) ( (aDate != nil) ? (id)([aDate descriptionWithLocale: [NSLocale currentLocale]]) : (id)([NSNull null]) )
#define IS_VALID_VALUE(value) ((value != nil) && (![value isKindOfClass: [NSNull class]]))
View
10 PhoneGapLib/Classes/Contacts.m
@@ -9,7 +9,7 @@
#import "Contacts.h"
#import <UIKit/UIKit.h>
-#import "PhoneGapDelegate.h"
+#import "PGAppDelegate.h"
#import "Categories.h"
#import "Notification.h"
@@ -75,7 +75,7 @@ - (void) newContact:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)op
npController.callbackId = callbackId;
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:npController] autorelease];
- [[super appViewController] presentModalViewController:navController animated: YES];
+ [self.viewController presentModalViewController:navController animated: YES];
}
@@ -122,7 +122,7 @@ - (void) displayContact:(NSMutableArray*)arguments withDict:(NSMutableDictionary
[navController pushViewController:personController animated:YES];
- [self.appViewController presentModalViewController:navController animated: YES];
+ [self.viewController presentModalViewController:navController animated: YES];
if (bEdit) {
// create the editing controller and push it onto the stack
@@ -160,7 +160,7 @@ - (void) chooseContact:(NSMutableArray*)arguments withDict:(NSMutableDictionary*
pickerController.selectedId = kABRecordInvalidID;
pickerController.allowsEditing = (BOOL)[options existsValue:@"true" forKey:@"allowsEditing"];
- [[super appViewController] presentModalViewController:pickerController animated: YES];
+ [self.viewController presentModalViewController:pickerController animated: YES];
}
- (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker
@@ -462,7 +462,7 @@ - (void)viewDidDisappear: (BOOL)animated
[super viewDidDisappear: animated];
// I couldn't find the appViewController in the hierarchy of this UIViewController
// so using the passed ContactPlugin to access it.
- [self.contactsPlugin.appViewController dismissModalViewControllerAnimated:NO];
+ [self.contactsPlugin.viewController dismissModalViewControllerAnimated:NO];
}
-(void) dealloc
View
10 PhoneGapLib/Classes/Location.m
@@ -7,8 +7,8 @@
#import "Location.h"
-#import "PhoneGapViewController.h"
-#import "PhoneGapDelegate.h"
+#import "PGViewController.h"
+#import "PGAppDelegate.h"
#pragma mark Constants
@@ -361,10 +361,10 @@ - (void) startHeadingWithFilter: (CLLocationDegrees) filter
if ([self.locationManager respondsToSelector: @selector(headingOrientation)]) {
UIDeviceOrientation currentOrientation = [[UIDevice currentDevice] orientation];
if (currentOrientation != UIDeviceOrientationUnknown) {
- PhoneGapDelegate* pgDelegate = [self appDelegate];
- PhoneGapViewController* pgViewController = pgDelegate.viewController;
+ PGAppDelegate* pgDelegate = [self appDelegate];
+ PGViewController* pgViewController = pgDelegate.viewController;
- if ([[pgViewController supportedOrientations] containsObject:
+ if ([pgViewController.supportedOrientations containsObject:
[NSNumber numberWithInt:currentOrientation]]) {
self.locationManager.headingOrientation = (CLDeviceOrientation)currentOrientation;
View
27 PhoneGapLib/Classes/PGAppDelegate.h
@@ -0,0 +1,27 @@
+/*
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ *
+ * Copyright (c) 2005-2010, Nitobi Software Inc.
+ * Copyright (c) 2010, IBM Corporation
+ */
+
+#import <UIKit/UIKit.h>
+#import "JSONKit.h"
+
+@class PGViewController;
+
+@interface PGAppDelegate : NSObject <UIApplicationDelegate, UIWebViewDelegate>
+{
+}
+
+@property (nonatomic, readwrite, retain) IBOutlet UIWindow* window;
+@property (nonatomic, readonly, retain) IBOutlet PGViewController* viewController;
+
+- (void)applicationDidEnterBackground:(UIApplication *)application;
+- (void)applicationWillEnterForeground:(UIApplication *)application;
+- (void)applicationWillResignActive:(UIApplication *)application;
+- (void)applicationWillTerminate:(UIApplication *)application;
+
+@end
+
View
211 PhoneGapLib/Classes/PGAppDelegate.m
@@ -0,0 +1,211 @@
+/*
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ *
+ * Copyright (c) 2005-2010, Nitobi Software Inc.
+ * Copyright (c) 2010, IBM Corporation
+ */
+
+#import <UIKit/UIKit.h>
+#import <CoreLocation/CoreLocation.h>
+
+#import "Location.h"
+#import "Sound.h"
+#import "DebugConsole.h"
+#import "Connection.h"
+
+#import "PGURLProtocol.h"
+#import "PGWhitelist.h"
+#import "InvokedUrlCommand.h"
+#import "PGAppDelegate.h"
+#import "PGViewController.h"
+#import "PGPlugin.h"
+
+// class extension
+@interface PGAppDelegate ()
+
+// readwrite access for self
+
+@property (nonatomic, readwrite, retain) IBOutlet PGViewController* viewController;
+
+@end
+
+
+@implementation PGAppDelegate
+
+@synthesize window, viewController;
+
+- (id) init
+{
+ self = [super init];
+ if (self != nil) {
+ // Turn on cookie support ( shared with our app only! )
+ NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
+ [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
+
+ [PGURLProtocol registerPGHttpURLProtocol];
+ }
+ return self;
+}
+
+/**
+ * This is main kick off after the app inits, the views and Settings are setup here.
+ */
+- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
+{
+ CGRect screenBounds = [ [ UIScreen mainScreen ] bounds ];
+ self.window = [ [ [ UIWindow alloc ] initWithFrame:screenBounds ] autorelease ];
+ self.window.autoresizesSubviews = YES;
+
+ CGRect viewBounds = [[UIScreen mainScreen] applicationFrame];
+ viewBounds.origin = screenBounds.origin;
+ self.viewController = [[[PGViewController alloc] init] autorelease];
+ self.viewController.useSplashScreen = YES;
+ self.viewController.view.bounds = viewBounds;
+
+ // check whether the current orientation is supported: if it is, keep it, rather than forcing a rotation
+ BOOL forceStartupRotation = YES;
+ UIDeviceOrientation curDevOrientation = [[UIDevice currentDevice] orientation];
+
+ if (UIDeviceOrientationUnknown == curDevOrientation) {
+ // UIDevice isn't firing orientation notifications yet… go look at the status bar
+ curDevOrientation = (UIDeviceOrientation)[[UIApplication sharedApplication] statusBarOrientation];
+ }
+
+ if (UIDeviceOrientationIsValidInterfaceOrientation(curDevOrientation)) {
+ for (NSNumber *orient in self.viewController.supportedOrientations) {
+ if ([orient intValue] == curDevOrientation) {
+ forceStartupRotation = NO;
+ break;
+ }
+ }
+ }
+
+ if (forceStartupRotation) {
+ NSLog(@"supportedOrientations: %@", self.viewController.supportedOrientations);
+ // The first item in the supportedOrientations array is the start orientation (guaranteed to be at least Portrait)
+ UIInterfaceOrientation newOrient = [[self.viewController.supportedOrientations objectAtIndex:0] intValue];
+ NSLog(@"PhoneGapDelegate forcing status bar to: %d from: %d",newOrient,curDevOrientation);
+ [[UIApplication sharedApplication] setStatusBarOrientation:newOrient];
+ }
+
+ [self.window addSubview:self.viewController.view];
+ [self.window makeKeyAndVisible];
+
+ return YES;
+}
+
+- (NSString*) appURLScheme
+{
+ NSString* URLScheme = nil;
+
+ NSArray *URLTypes = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleURLTypes"];
+ if(URLTypes != nil ) {
+ NSDictionary* dict = [URLTypes objectAtIndex:0];
+ if(dict != nil ) {
+ NSArray* URLSchemes = [dict objectForKey:@"CFBundleURLSchemes"];
+ if( URLSchemes != nil ) {
+ URLScheme = [URLSchemes objectAtIndex:0];
+ }
+ }
+ }
+
+ return URLScheme;
+}
+
+/*
+ This method lets your application know that it is about to be terminated and purged from memory entirely
+*/
+- (void)applicationWillTerminate:(UIApplication *)application
+{
+
+ NSLog(@"applicationWillTerminate");
+
+ // empty the tmp directory
+ NSFileManager* fileMgr = [[NSFileManager alloc] init];
+ NSError* err = nil;
+
+ // clear contents of NSTemporaryDirectory
+ NSString* tempDirectoryPath = NSTemporaryDirectory();
+ NSDirectoryEnumerator* directoryEnumerator = [fileMgr enumeratorAtPath:tempDirectoryPath];
+ NSString* fileName = nil;
+ BOOL result;
+
+ while ((fileName = [directoryEnumerator nextObject])) {
+ NSString* filePath = [tempDirectoryPath stringByAppendingPathComponent:fileName];
+ result = [fileMgr removeItemAtPath:filePath error:&err];
+ if (!result && err) {
+ NSLog(@"Failed to delete: %@ (error: %@)", filePath, err);
+ }
+ }
+ [fileMgr release];
+}
+
+/*
+ This method is called to let your application know that it is about to move from the active to inactive state.
+ You should use this method to pause ongoing tasks, disable timer, ...
+*/
+- (void)applicationWillResignActive:(UIApplication *)application
+{
+ //NSLog(@"%@",@"applicationWillResignActive");
+ [self.viewController.webView stringByEvaluatingJavaScriptFromString:@"PhoneGap.fireDocumentEvent('resign');"];
+}
+
+/*
+ In iOS 4.0 and later, this method is called as part of the transition from the background to the inactive state.
+ You can use this method to undo many of the changes you made to your application upon entering the background.
+ invariably followed by applicationDidBecomeActive
+*/
+- (void)applicationWillEnterForeground:(UIApplication *)application
+{
+ //NSLog(@"%@",@"applicationWillEnterForeground");
+ [self.viewController.webView stringByEvaluatingJavaScriptFromString:@"PhoneGap.fireDocumentEvent('resume');"];
+}
+
+// This method is called to let your application know that it moved from the inactive to active state.
+- (void)applicationDidBecomeActive:(UIApplication *)application
+{
+ //NSLog(@"%@",@"applicationDidBecomeActive");
+ [self.viewController.webView stringByEvaluatingJavaScriptFromString:@"PhoneGap.fireDocumentEvent('active');"];
+}
+
+/*
+ In iOS 4.0 and later, this method is called instead of the applicationWillTerminate: method
+ when the user quits an application that supports background execution.
+ */
+- (void)applicationDidEnterBackground:(UIApplication *)application
+{
+ //NSLog(@"%@",@"applicationDidEnterBackground");
+ [self.viewController.webView stringByEvaluatingJavaScriptFromString:@"PhoneGap.fireDocumentEvent('pause');"];
+}
+
+
+/*
+ Determine the URL passed to this application.
+ Described in http://iphonedevelopertips.com/cocoa/launching-your-own-application-via-a-custom-url-scheme.html
+*/
+- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
+{
+ if (!url) {
+ return NO;
+ }
+
+ // Do something with the url here
+ NSString* jsString = [NSString stringWithFormat:@"handleOpenURL(\"%@\");", url];
+ [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsString];
+
+ [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:PGPluginHandleOpenURLNotification object:url]];
+
+ return YES;
+}
+
+- (void)dealloc
+{
+ [PluginResult releaseStatus];
+ self.viewController = nil;
+ self.window = nil;
+
+ [super dealloc];
+}
+
+@end
View
11 PhoneGapLib/Classes/PGPlugin.h
@@ -19,13 +19,12 @@
callerFileName:__FILE__ callerFunctionName:__PRETTY_FUNCTION__]) { return; }
-@class PhoneGapDelegate;
-
@interface PGPlugin : NSObject {
}
-@property (nonatomic, retain) UIWebView *webView;
-@property (nonatomic, retain) NSDictionary *settings;
+@property (nonatomic, retain) UIWebView* webView;
+@property (nonatomic, retain) NSDictionary* settings;
+@property (nonatomic, retain) UIViewController* viewController;
- (PGPlugin*) initWithWebView:(UIWebView*)theWebView settings:(NSDictionary*)classSettings;
- (PGPlugin*) initWithWebView:(UIWebView*)theWebView;
@@ -42,8 +41,8 @@ callerFileName:__FILE__ callerFunctionName:__PRETTY_FUNCTION__]) { return; }
- (void) onOrientationDidChange {}
*/
-- (PhoneGapDelegate*) appDelegate;
-- (UIViewController*) appViewController;
+- (id) appDelegate;
+- (UIViewController*) appViewController __attribute__((deprecated)); /* just use the .viewController property in the future */
- (NSString*) writeJavascript:(NSString*)javascript;
- (NSString*) success:(PluginResult*)pluginResult callbackId:(NSString*)callbackId;
View
12 PhoneGapLib/Classes/PGPlugin.m
@@ -10,12 +10,11 @@
#import "PGPlugin.h"
-#import "PhoneGapDelegate.h"
+#import "PGAppDelegate.h"
@implementation PGPlugin
-@synthesize webView;
-@synthesize settings;
+@synthesize webView, settings, viewController;
- (PGPlugin*) initWithWebView:(UIWebView*)theWebView settings:(NSDictionary*)classSettings
@@ -125,14 +124,15 @@ - (void) dealloc
[super dealloc];
}
-- (PhoneGapDelegate*) appDelegate
+- (id) appDelegate
{
- return (PhoneGapDelegate*)[[UIApplication sharedApplication] delegate];
+ return [[UIApplication sharedApplication] delegate];
}
+/* deprecated - just use the viewController property */
- (UIViewController*) appViewController
{
- return (UIViewController*)[self appDelegate].viewController;
+ return self.viewController;
}
- (NSString*) writeJavascript:(NSString*)javascript
View
11 PhoneGapLib/Classes/PGSplashScreen.m
@@ -7,20 +7,21 @@
#import "PGSplashScreen.h"
-#import "PhoneGapDelegate.h"
+#import "PGAppDelegate.h"
+#import "PGViewController.h"
@implementation PGSplashScreen
- (void) __show:(BOOL)show
{
- PhoneGapDelegate* delegate = [super appDelegate];
- if (!delegate.imageView) {
+ PGViewController* vc = (PGViewController*)self.viewController;
+ if (vc.imageView) {
return;
}
- delegate.imageView.hidden = !show;
- delegate.activityView.hidden = !show;
+ vc.imageView.hidden = !show;
+ vc.activityView.hidden = !show;
}
- (void) show:(NSArray*)arguments withDict:(NSMutableDictionary*)options
View
7 PhoneGapLib/Classes/PGURLProtocol.m
@@ -8,7 +8,8 @@
#import "PGURLProtocol.h"
#import "PGWhitelist.h"
-#import "PhoneGapDelegate.h"
+#import "PGAppDelegate.h"
+#import "PGViewController.h"
static PGWhitelist* gWhitelist = nil;
@@ -29,8 +30,8 @@ + (BOOL) canInitWithRequest:(NSURLRequest *)theRequest
NSString* theScheme = [theUrl scheme];
if (gWhitelist == nil) {
- PhoneGapDelegate* delegate = (PhoneGapDelegate*)[[UIApplication sharedApplication] delegate];
- gWhitelist = [delegate.whitelist retain];
+ PGAppDelegate* delegate = (PGAppDelegate*)[[UIApplication sharedApplication] delegate];
+ gWhitelist = [delegate.viewController.whitelist retain];
}
// we only care about http and https connections
View
75 PhoneGapLib/Classes/PGViewController.h
@@ -0,0 +1,75 @@
+//
+// PGViewController.h
+//
+// Created by Jesse MacFadyen on 11-12-08.
+// Copyright 2011 Nitobi. All rights reserved.
+//
+
+#import "UIGapView.h"
+
+#import "JSONKit.h"
+#import "InvokedUrlCommand.h"
+
+#import "PGWhitelist.h"
+
+
+/* PGCommandDelegate */
+
+@protocol PGCommandDelegate <NSObject>
+
+- (id) getCommandInstance:(NSString*)pluginName;
+- (BOOL) execute:(InvokedUrlCommand*)command;
+
+@end
+
+/* PGViewController */
+
+@interface PGViewController : UIViewController<UIWebViewDelegate, PGCommandDelegate> {
+
+}
+
+@property (nonatomic, retain) IBOutlet UIGapView* webView;
+
+@property (nonatomic, readonly, retain) NSMutableDictionary* pluginObjects;
+@property (nonatomic, readonly, retain) NSDictionary* pluginsMap;
+@property (nonatomic, readonly, retain) NSDictionary* settings;
+@property (nonatomic, readonly, retain) PGWhitelist* whitelist; // readonly for public
+@property (nonatomic, readonly, retain) NSArray* supportedOrientations;
+@property (nonatomic, readonly, copy) NSString* sessionKey;
+@property (nonatomic, readonly, assign) BOOL loadFromString;
+
+@property (nonatomic, readwrite, assign) BOOL useSplashScreen;
+@property (nonatomic, readonly, retain) IBOutlet UIActivityIndicatorView* activityView;
+@property (nonatomic, readonly, retain) UIImageView *imageView;
+@property (nonatomic, readwrite, assign) id<PGCommandDelegate> commandDelegate;
+
++ (NSDictionary*) getBundlePlist:(NSString*)plistName;
++ (NSString*) wwwFolderName;
++ (NSString*) pathForResource:(NSString*)resourcepath;
++ (NSString*) phoneGapVersion;
++ (NSString*) applicationDocumentsDirectory;
+- (NSString*) startPage;
+
+
+- (void) createGapView;
+
+- (int) executeQueuedCommands;
+- (void) flushCommandQueue;
+
+- (id) getCommandInstance:(NSString*)pluginName;
+- (void) javascriptAlert:(NSString*)text;
+- (BOOL) execute:(InvokedUrlCommand*)command;
+- (NSString*) appURLScheme;
+- (NSDictionary*) deviceProperties;
+
+- (NSArray*) parseInterfaceOrientations:(NSArray*)orientations;
+
+@end
+
+/* Category */
+
+@interface NSDictionary (LowercaseKeys)
+
+- (NSDictionary*) dictionaryWithLowercaseKeys;
+
+@end
View
829 PhoneGapLib/Classes/PGViewController.m
@@ -0,0 +1,829 @@
+//
+// PGViewController.m
+//
+// Created by Jesse MacFadyen on 11-12-08.
+// Copyright 2011 Nitobi. All rights reserved.
+//
+
+#import "PGViewController.h"
+#import "PGPlugin.h"
+#import "Location.h"
+#import "Connection.h"
+
+#define SYMBOL_TO_NSSTRING_HELPER(x) @#x
+#define SYMBOL_TO_NSSTRING(x) SYMBOL_TO_NSSTRING_HELPER(x)
+#define degreesToRadian(x) (M_PI * (x) / 180.0)
+
+@interface PGViewController ()
+
+@property (nonatomic, readwrite, retain) NSDictionary* settings;
+@property (nonatomic, readwrite, retain) PGWhitelist* whitelist;
+@property (nonatomic, readwrite, retain) NSMutableDictionary* pluginObjects;
+@property (nonatomic, readwrite, retain) NSDictionary* pluginsMap;
+@property (nonatomic, readwrite, retain) NSArray* supportedOrientations;
+@property (nonatomic, readwrite, copy) NSString* sessionKey;
+@property (nonatomic, readwrite, assign) BOOL loadFromString;
+
+@property (nonatomic, readwrite, retain) IBOutlet UIActivityIndicatorView* activityView;
+@property (nonatomic, readwrite, retain) UIImageView* imageView;
+
+
+@end
+
+
+@implementation PGViewController
+
+@synthesize webView, supportedOrientations;
+@synthesize pluginObjects, pluginsMap, whitelist;
+@synthesize settings, sessionKey, loadFromString;
+@synthesize imageView, activityView, useSplashScreen, commandDelegate;
+
+- (id) init
+{
+ self = [super init];
+ if (self != nil) {
+ [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedOrientationChange) name:UIDeviceOrientationDidChangeNotification
+ object:nil];
+ }
+ return self;
+}
+
+// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
+- (void) viewDidLoad
+{
+ if (self.sessionKey == nil) {
+ self.sessionKey = [NSString stringWithFormat:@"%d", arc4random()];
+ }
+
+ [super viewDidLoad];
+
+ self.pluginObjects = [[[NSMutableDictionary alloc] initWithCapacity:4] autorelease];
+
+ // read from UISupportedInterfaceOrientations (or UISupportedInterfaceOrientations~iPad, if its iPad) from -Info.plist
+ self.supportedOrientations = [self parseInterfaceOrientations:
+ [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UISupportedInterfaceOrientations"]];
+
+ // read from PhoneGap.plist in the app bundle
+ NSString* appPlistName = @"PhoneGap";
+ NSDictionary* phonegapPlist = [[self class] getBundlePlist:appPlistName];
+ if (phonegapPlist == nil) {
+ NSLog(@"WARNING: %@.plist is missing.", appPlistName);
+ return;
+ }
+ self.settings = [[[NSDictionary alloc] initWithDictionary:phonegapPlist] autorelease];
+
+ // read from Plugins dict in PhoneGap.plist in the app bundle
+ NSString* pluginsKey = @"Plugins";
+ NSDictionary* pluginsDict = [self.settings objectForKey:@"Plugins"];
+ if (pluginsDict == nil) {
+ NSLog(@"WARNING: %@ key in %@.plist is missing! PhoneGap will not work, you need to have this key.", pluginsKey, appPlistName);
+ return;
+ }
+
+ // set the whitelist
+ self.whitelist = [[[PGWhitelist alloc] initWithArray:[self.settings objectForKey:@"ExternalHosts"]] autorelease];
+
+ self.pluginsMap = [pluginsDict dictionaryWithLowercaseKeys];
+
+ ///////////////////
+
+ NSString* startFilePath = [[self class] pathForResource:[self startPage]];
+ NSURL* appURL = nil;
+ NSString* loadErr = nil;
+
+ if (startFilePath == nil) {
+ loadErr = [NSString stringWithFormat:@"ERROR: Start Page at '%@/%@' was not found.", [[self class] wwwFolderName], [self startPage]];
+ NSLog(@"%@", loadErr);
+ self.loadFromString = YES;
+ appURL = nil;
+ } else {
+ appURL = [NSURL fileURLWithPath:startFilePath];
+ }
+
+ ///////////////////
+
+ NSNumber* enableLocation = [settings objectForKey:@"EnableLocation"];
+ NSString* enableViewportScale = [settings objectForKey:@"EnableViewportScale"];
+ NSNumber* allowInlineMediaPlayback = [settings objectForKey:@"AllowInlineMediaPlayback"];
+ NSNumber* mediaPlaybackRequiresUserAction = [settings objectForKey:@"MediaPlaybackRequiresUserAction"];
+
+ self.webView.scalesPageToFit = [enableViewportScale boolValue];
+
+ /*
+ * Fire up the GPS Service right away as it takes a moment for data to come back.
+ */
+ if ([allowInlineMediaPlayback boolValue] && [self.webView respondsToSelector:@selector(allowsInlineMediaPlayback)]) {
+ self.webView.allowsInlineMediaPlayback = YES;
+ }
+ if ([mediaPlaybackRequiresUserAction boolValue] && [self.webView respondsToSelector:@selector(mediaPlaybackRequiresUserAction)]) {
+ self.webView.mediaPlaybackRequiresUserAction = YES;
+ }
+
+ /*
+ * This is for iOS 4.x, where you can allow inline <video> and <audio>, and also autoplay them
+ */
+ if ([enableLocation boolValue]) {
+ [[self.commandDelegate getCommandInstance:@"com.phonegap.geolocation"] startLocation:nil withDict:nil];
+ }
+
+ ///////////////////
+
+ [ self createGapView];
+
+ if (!loadErr) {
+ NSURLRequest *appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
+ [self.webView loadRequest:appReq];
+ } else {
+ NSString* html = [NSString stringWithFormat:@"<html><body> %@ </body></html>", loadErr];
+ [self.webView loadHTMLString:html baseURL:nil];
+ }
+
+ self.commandDelegate = self;
+}
+
+- (NSArray*) parseInterfaceOrientations:(NSArray*)orientations
+{
+ NSMutableArray* result = [[[NSMutableArray alloc] init] autorelease];
+
+ if (orientations != nil)
+ {
+ NSEnumerator* enumerator = [orientations objectEnumerator];
+ NSString* orientationString;
+
+ while (orientationString = [enumerator nextObject])
+ {
+ if ([orientationString isEqualToString:@"UIInterfaceOrientationPortrait"]) {
+ [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortrait]];
+ } else if ([orientationString isEqualToString:@"UIInterfaceOrientationPortraitUpsideDown"]) {
+ [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown]];
+ } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeLeft"]) {
+ [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]];
+ } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeRight"]) {
+ [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight]];
+ }
+ }
+ }
+
+ // default
+ if ([result count] == 0) {
+ [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortrait]];
+ }
+
+ return result;
+}
+
+- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ // First ask the webview via JS if it wants to support the new orientation -jm
+ int i = 0;
+
+ switch (interfaceOrientation){
+
+ case UIInterfaceOrientationPortraitUpsideDown:
+ i = 180;
+ break;
+ case UIInterfaceOrientationLandscapeLeft:
+ i = -90;
+ break;
+ case UIInterfaceOrientationLandscapeRight:
+ i = 90;
+ break;
+ default:
+ case UIInterfaceOrientationPortrait:
+ // noop
+ break;
+ }
+
+ NSString* jsCall = [ NSString stringWithFormat:@"shouldRotateToOrientation(%d);",i];
+ NSString* res = [webView stringByEvaluatingJavaScriptFromString:jsCall];
+
+ if([res length] > 0)
+ {
+ return [res boolValue];
+ }
+
+ // if js did not handle the new orientation ( no return value ) we will look it up in the plist -jm
+
+ BOOL autoRotate = [self.supportedOrientations count] > 0; // autorotate if only more than 1 orientation supported
+ if (autoRotate)
+ {
+ if ([self.supportedOrientations containsObject:
+ [NSNumber numberWithInt:interfaceOrientation]]) {
+ return YES;
+ }
+ }
+
+ // default return value is NO! -jm
+
+ return NO;
+}
+
+
+- (void) createGapView
+{
+ CGRect webViewBounds = self.view.bounds;
+ webViewBounds.origin = self.view.bounds.origin;
+
+ if (!self.webView)
+ {
+ self.webView = [[ [ UIGapView alloc ] initWithFrame:webViewBounds] autorelease];
+ self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+
+ [self.view addSubview:self.webView];
+ [self.view sendSubviewToBack:self.webView];
+
+ self.webView.delegate = self;
+ }
+}
+
+- (void) didReceiveMemoryWarning {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+
+ // Release any cached data, images, etc. that aren't in use.
+}
+
+
+- (void) viewDidUnload {
+ // Release any retained subviews of the main view.
+ // e.g. self.myOutlet = nil;
+}
+
+
+#pragma mark UIWebViewDelegate
+
+/**
+ When web application loads Add stuff to the DOM, mainly the user-defined settings from the Settings.plist file, and
+ the device's data such as device ID, platform version, etc.
+ */
+- (void) webViewDidStartLoad:(UIWebView*)theWebView
+{
+
+}
+
+/**
+ Called when the webview finishes loading. This stops the activity view and closes the imageview
+ */
+- (void) webViewDidFinishLoad:(UIWebView*)theWebView
+{
+ // Share session key with the WebView by setting PhoneGap.sessionKey
+ NSString *sessionKeyScript = [NSString stringWithFormat:@"PhoneGap.sessionKey = \"%@\";", self.sessionKey];
+ [theWebView stringByEvaluatingJavaScriptFromString:sessionKeyScript];
+
+
+ NSDictionary *deviceProperties = [ self deviceProperties];
+ NSMutableString *result = [[NSMutableString alloc] initWithFormat:@"DeviceInfo = %@;", [deviceProperties JSONString]];
+
+ /* Settings.plist
+ * Read the optional Settings.plist file and push these user-defined settings down into the web application.
+ * This can be useful for supplying build-time configuration variables down to the app to change its behaviour,
+ * such as specifying Full / Lite version, or localization (English vs German, for instance).
+ */
+
+ NSDictionary *temp = [[self class] getBundlePlist:@"Settings"];
+ if ([temp respondsToSelector:@selector(JSONString)]) {
+ [result appendFormat:@"\nwindow.Settings = %@;", [temp JSONString]];
+ }
+
+ NSLog(@"Device initialization: %@", result);
+ [theWebView stringByEvaluatingJavaScriptFromString:result];
+ [result release];
+
+ /*
+ * Hide the Top Activity THROBBER in the Battery Bar
+ */
+ [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
+
+ id autoHideSplashScreenValue = [self.settings objectForKey:@"AutoHideSplashScreen"];
+ // if value is missing, default to yes
+ if (autoHideSplashScreenValue == nil || [autoHideSplashScreenValue boolValue]) {
+ self.imageView.hidden = YES;
+ self.activityView.hidden = YES;
+ [self.view.superview bringSubviewToFront:self.webView];
+ }
+
+ [self didRotateFromInterfaceOrientation:(UIInterfaceOrientation)[[UIDevice currentDevice] orientation]];
+}
+
+- (void) webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error
+{
+ NSLog(@"Failed to load webpage with error: %@", [error localizedDescription]);
+ /*
+ if ([error code] != NSURLErrorCancelled)
+ alert([error localizedDescription]);
+ */
+}
+
+- (BOOL) webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+ NSURL* url = [request URL];
+
+ /*
+ * Execute any commands queued with PhoneGap.exec() on the JS side.
+ * The part of the URL after gap:// is irrelevant.
+ */
+ if ([[url scheme] isEqualToString:@"gap"]) {
+ [self flushCommandQueue];
+ return NO;
+ }
+ /*
+ * If a URL is being loaded that's a file/http/https URL, just load it internally
+ */
+ else if ([url isFileURL])
+ {
+ return YES;
+ }
+ else if ([self.whitelist schemeIsAllowed:[url scheme]])
+ {
+ if ([self.whitelist URLIsAllowed:url] == YES)
+ {
+ NSNumber *openAllInWhitelistSetting = [self.settings objectForKey:@"OpenAllWhitelistURLsInWebView"];
+ if ((nil != openAllInWhitelistSetting) && [openAllInWhitelistSetting boolValue]) {
+ NSLog(@"OpenAllWhitelistURLsInWebView set: opening in webview");
+ return YES;
+ }
+
+ // mainDocument will be nil for an iFrame
+ NSString* mainDocument = [theWebView.request.mainDocumentURL absoluteString];
+
+ // anchor target="_blank" - load in Mobile Safari
+ if (navigationType == UIWebViewNavigationTypeOther && mainDocument != nil)
+ {
+ [[UIApplication sharedApplication] openURL:url];
+ return NO;
+ }
+ // other anchor target - load in PhoneGap webView
+ else
+ {
+ return YES;
+ }
+ }
+
+ return NO;
+ }
+ /*
+ * If we loaded the HTML from a string, we let the app handle it
+ */
+ else if (self.loadFromString == YES)
+ {
+ self.loadFromString = NO;
+ return YES;
+ }
+ /*
+ * all tel: scheme urls we let the UIWebview handle it using the default behaviour
+ */
+ else if ([[url scheme] isEqualToString:@"tel"])
+ {
+ return YES;
+ }
+ /*
+ * all about: scheme urls are not handled
+ */
+ else if ([[url scheme] isEqualToString:@"about"])
+ {
+ return NO;
+ }
+ /*
+ * We don't have a PhoneGap or web/local request, load it in the main Safari browser.
+ * pass this to the application to handle. Could be a mailto:dude@duderanch.com or a tel:55555555 or sms:55555555 facetime:55555555
+ */
+ else
+ {
+ NSLog(@"PGAppDelegate::shouldStartLoadWithRequest: Received Unhandled URL %@", url);
+
+ if ([[UIApplication sharedApplication] canOpenURL:url]) {
+ [[UIApplication sharedApplication] openURL:url];
+ } else { // handle any custom schemes to plugins
+ [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:PGPluginHandleOpenURLNotification object:url]];
+ }
+
+ return NO;
+ }
+
+ return YES;
+}
+
+#pragma mark GapHelpers
+
+- (void) javascriptAlert:(NSString*)text
+{
+ NSString* jsString = [NSString stringWithFormat:@"alert('%@');", text];
+ [webView stringByEvaluatingJavaScriptFromString:jsString];
+}
+
++ (NSString*) wwwFolderName
+{
+ return @"www";
+}
+
+- (NSString*) startPage
+{
+ return @"index.html";
+}
+
++ (BOOL) isIPad
+{
+#ifdef UI_USER_INTERFACE_IDIOM
+ return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
+#else
+ return NO;
+#endif
+}
+
++ (NSString*) resolveImageResource:(NSString*)resource
+{
+ NSString* systemVersion = [[UIDevice currentDevice] systemVersion];
+ BOOL isLessThaniOS4 = ([systemVersion compare:@"4.0" options:NSNumericSearch] == NSOrderedAscending);
+
+ // the iPad image (nor retina) differentiation code was not in 3.x, and we have to explicitly set the path
+ if (isLessThaniOS4)
+ {
+ if ([[self class] isIPad]) {
+ return [NSString stringWithFormat:@"%@~ipad.png", resource];
+ } else {
+ return [NSString stringWithFormat:@"%@.png", resource];
+ }
+ }
+
+ return resource;
+}
+
++ (NSString*) pathForResource:(NSString*)resourcepath
+{
+ NSBundle * mainBundle = [NSBundle mainBundle];
+ NSMutableArray *directoryParts = [NSMutableArray arrayWithArray:[resourcepath componentsSeparatedByString:@"/"]];
+ NSString *filename = [directoryParts lastObject];
+ [directoryParts removeLastObject];
+
+ NSString* directoryPartsJoined =[directoryParts componentsJoinedByString:@"/"];
+ NSString* directoryStr = [self wwwFolderName];
+
+ if ([directoryPartsJoined length] > 0) {
+ directoryStr = [NSString stringWithFormat:@"%@/%@", [self wwwFolderName], [directoryParts componentsJoinedByString:@"/"]];
+ }
+
+ return [mainBundle pathForResource:filename ofType:@"" inDirectory:directoryStr];
+}
+
++ (NSString*) applicationDocumentsDirectory
+{
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
+ return basePath;
+}
+
+- (void) showSplashScreen
+{
+ NSString* launchImageFile = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UILaunchImageFile"];
+ if (launchImageFile == nil) { // fallback if no launch image was specified
+ launchImageFile = @"Default";
+ }
+
+ NSString* orientedLaunchImageFile = nil;
+ CGAffineTransform startupImageTransform = CGAffineTransformIdentity;
+ UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
+ CGRect screenBounds = [[UIScreen mainScreen] bounds];
+ UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
+ BOOL isIPad = [[self class] isIPad];
+ UIImage* launchImage = nil;
+
+ if (isIPad)
+ {
+ if (!UIDeviceOrientationIsValidInterfaceOrientation(deviceOrientation)) {
+ deviceOrientation = (UIDeviceOrientation)statusBarOrientation;
+ }
+
+ switch (deviceOrientation)
+ {
+ case UIDeviceOrientationLandscapeLeft: // this is where the home button is on the right (yeah, I know, confusing)
+ {
+ orientedLaunchImageFile = [NSString stringWithFormat:@"%@-Landscape", launchImageFile];
+ startupImageTransform = CGAffineTransformMakeRotation(degreesToRadian(90));
+ }
+ break;
+ case UIDeviceOrientationLandscapeRight: // this is where the home button is on the left (yeah, I know, confusing)
+ {
+ orientedLaunchImageFile = [NSString stringWithFormat:@"%@-Landscape", launchImageFile];
+ startupImageTransform = CGAffineTransformMakeRotation(degreesToRadian(-90));
+ }
+ break;
+ case UIDeviceOrientationPortraitUpsideDown:
+ {
+ orientedLaunchImageFile = [NSString stringWithFormat:@"%@-Portrait", launchImageFile];
+ startupImageTransform = CGAffineTransformMakeRotation(degreesToRadian(180));
+ }
+ break;
+ case UIDeviceOrientationPortrait:
+ default:
+ {
+ orientedLaunchImageFile = [NSString stringWithFormat:@"%@-Portrait", launchImageFile];
+ startupImageTransform = CGAffineTransformIdentity;
+ }
+ break;
+ }
+
+ launchImage = [UIImage imageNamed:[[self class] resolveImageResource:orientedLaunchImageFile]];
+ }
+ else // not iPad
+ {
+ orientedLaunchImageFile = @"Default";
+ launchImage = [UIImage imageNamed:[[self class] resolveImageResource:orientedLaunchImageFile]];
+ }
+
+ if (launchImage == nil) {
+ NSLog(@"WARNING: Splash-screen image '%@' was not found. Orientation: %d, iPad: %d", orientedLaunchImageFile, deviceOrientation, isIPad);
+ }
+
+ self.imageView = [[[UIImageView alloc] initWithImage:launchImage] autorelease];
+ self.imageView.tag = 1;
+ self.imageView.center = CGPointMake((screenBounds.size.width / 2), (screenBounds.size.height / 2));
+
+ self.imageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth & UIViewAutoresizingFlexibleHeight & UIViewAutoresizingFlexibleLeftMargin & UIViewAutoresizingFlexibleRightMargin);
+ [self.imageView setTransform:startupImageTransform];
+ [self.view.superview addSubview:self.imageView];
+
+
+ /*
+ * The Activity View is the top spinning throbber in the status/battery bar. We init it with the default Grey Style.
+ *
+ * whiteLarge = UIActivityIndicatorViewStyleWhiteLarge
+ * white = UIActivityIndicatorViewStyleWhite
+ * gray = UIActivityIndicatorViewStyleGray
+ *
+ */
+ NSString* topActivityIndicator = [self.settings objectForKey:@"TopActivityIndicator"];
+ UIActivityIndicatorViewStyle topActivityIndicatorStyle = UIActivityIndicatorViewStyleGray;
+
+ if ([topActivityIndicator isEqualToString:@"whiteLarge"]) {
+ topActivityIndicatorStyle = UIActivityIndicatorViewStyleWhiteLarge;
+ } else if ([topActivityIndicator isEqualToString:@"white"]) {
+ topActivityIndicatorStyle = UIActivityIndicatorViewStyleWhite;
+ } else if ([topActivityIndicator isEqualToString:@"gray"]) {
+ topActivityIndicatorStyle = UIActivityIndicatorViewStyleGray;
+ }
+
+ self.activityView = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:topActivityIndicatorStyle] autorelease];
+ self.activityView.tag = 2;
+
+ id showSplashScreenSpinnerValue = [self.settings objectForKey:@"ShowSplashScreenSpinner"];
+ // backwards compatibility - if key is missing, default to true
+ if (showSplashScreenSpinnerValue == nil || [showSplashScreenSpinnerValue boolValue]) {
+ [self.view.superview addSubview:self.activityView];
+ }
+
+ self.activityView.center = self.view.center;
+ [self.activityView startAnimating];
+
+ [self.view.superview layoutSubviews];
+}
+
+BOOL gSplashScreenShown = NO;
+- (void) receivedOrientationChange
+{
+ if (self.imageView == nil) {
+ gSplashScreenShown = YES;
+ if (self.useSplashScreen) {
+ [self showSplashScreen];
+ }
+ }
+}
+
+#pragma mark PhoneGapCommands
+
+/**
+ * Fetches the command queue and executes each command. It is possible that the
+ * queue will not be empty after this function has completed since the executed
+ * commands may have run callbacks which queued more commands.
+ *
+ * Returns the number of executed commands.
+ */
+- (int) executeQueuedCommands
+{
+ // Grab all the queued commands from the JS side.
+ NSString* queuedCommandsJSON = [self.webView stringByEvaluatingJavaScriptFromString:
+ @"PhoneGap.getAndClearQueuedCommands()"];
+
+
+ // Parse the returned JSON array.
+ //PG_SBJsonParser* jsonParser = [[[PG_SBJsonParser alloc] init] autorelease];
+ NSArray* queuedCommands =
+ [queuedCommandsJSON objectFromJSONString];
+
+ // Iterate over and execute all of the commands.
+ for (NSString* commandJson in queuedCommands) {
+
+ if(![self.commandDelegate execute:
+ [InvokedUrlCommand commandFromObject:
+ [commandJson mutableObjectFromJSONString]]])
+ {
+ NSLog(@"FAILED pluginJSON = %@",commandJson);
+ }
+ }
+
+ return [queuedCommands count];
+}
+
+/**
+ * Repeatedly fetches and executes the command queue until it is empty.
+ */
+- (void) flushCommandQueue
+{
+ [self.webView stringByEvaluatingJavaScriptFromString:
+ @"PhoneGap.commandQueueFlushing = true"];
+
+ // Keep executing the command queue until no commands get executed.
+ // This ensures that commands that are queued while executing other
+ // commands are executed as well.
+ int numExecutedCommands = 0;
+ do {
+ numExecutedCommands = [self executeQueuedCommands];
+ } while (numExecutedCommands != 0);
+
+ [self.webView stringByEvaluatingJavaScriptFromString:
+ @"PhoneGap.commandQueueFlushing = false"];
+}
+
+- (BOOL) execute:(InvokedUrlCommand*)command
+{
+ if (command.className == nil || command.methodName == nil) {
+ return NO;
+ }
+
+ // Fetch an instance of this class
+ PGPlugin* obj = [self.commandDelegate getCommandInstance:command.className];
+
+ if (!([obj isKindOfClass:[PGPlugin class]])) { // still allow deprecated class, until 1.0 release
+ NSLog(@"ERROR: Plugin '%@' not found, or is not a PGPlugin. Check your plugin mapping in PhoneGap.plist.", command.className);
+ return NO;
+ }
+ BOOL retVal = YES;
+
+ // construct the fill method name to ammend the second argument.
+ NSString* fullMethodName = [[NSString alloc] initWithFormat:@"%@:withDict:", command.methodName];
+ if ([obj respondsToSelector:NSSelectorFromString(fullMethodName)]) {
+ [obj performSelector:NSSelectorFromString(fullMethodName) withObject:command.arguments withObject:command.options];
+ } else {
+ // There's no method to call, so throw an error.
+ NSLog(@"ERROR: Method '%@' not defined in Plugin '%@'", fullMethodName, command.className);
+ retVal = NO;
+ }
+ [fullMethodName release];
+
+ return retVal;
+}
+
+/**
+ Returns an instance of a PhoneGapCommand object, based on its name. If one exists already, it is returned.
+ */
+- (id) getCommandInstance:(NSString*)pluginName
+{
+ // first, we try to find the pluginName in the pluginsMap
+ // (acts as a whitelist as well) if it does not exist, we return nil
+ // NOTE: plugin names are matched as lowercase to avoid problems - however, a
+ // possible issue is there can be duplicates possible if you had:
+ // "com.phonegap.Foo" and "com.phonegap.foo" - only the lower-cased entry will match
+ NSString* className = [self.pluginsMap objectForKey:[pluginName lowercaseString]];
+ if (className == nil) {
+ return nil;
+ }
+
+ id obj = [self.pluginObjects objectForKey:className];
+ if (!obj)
+ {
+ // attempt to load the settings for this command class
+ NSDictionary* classSettings = [self.settings objectForKey:className];
+
+ if (classSettings) {
+ obj = [[NSClassFromString(className) alloc] initWithWebView:webView settings:classSettings];
+ } else {
+ obj = [[NSClassFromString(className) alloc] initWithWebView:webView];
+ }
+
+ if ([obj isKindOfClass:[PGPlugin class]] && [obj respondsToSelector:@selector(setViewController)]) {
+ [obj setViewController:self];
+ }
+
+ if (obj != nil) {
+ [self.pluginObjects setObject:obj forKey:className];
+ [obj release];
+ } else {
+ NSLog(@"PGPlugin class %@ (pluginName: %@) does not exist.", className, pluginName);
+ }
+ }
+ return obj;
+}
+
+
+#pragma mark -
+
+- (NSDictionary*) deviceProperties
+{
+ UIDevice *device = [UIDevice currentDevice];
+ NSMutableDictionary *devProps = [NSMutableDictionary dictionaryWithCapacity:4];
+ [devProps setObject:[device model] forKey:@"platform"];
+ [devProps setObject:[device systemVersion] forKey:@"version"];
+ [devProps setObject:[device uniqueIdentifier] forKey:@"uuid"];
+ [devProps setObject:[device name] forKey:@"name"];
+ [devProps setObject:[[self class] phoneGapVersion ] forKey:@"gap"];
+
+ id cmd = [self.commandDelegate getCommandInstance:@"com.phonegap.connection"];
+ if (cmd && [cmd isKindOfClass:[PGConnection class]])
+ {
+ NSMutableDictionary *connProps = [NSMutableDictionary dictionaryWithCapacity:3];
+ if ([cmd respondsToSelector:@selector(connectionType)]) {
+ [connProps setObject:[cmd connectionType] forKey:@"type"];
+ }
+ [devProps setObject:connProps forKey:@"connection"];
+ }
+
+ NSDictionary *devReturn = [NSDictionary dictionaryWithDictionary:devProps];
+ return devReturn;
+}
+
+- (NSString*) appURLScheme
+{
+ NSString* URLScheme = nil;
+
+ NSArray *URLTypes = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleURLTypes"];
+ if(URLTypes != nil ) {
+ NSDictionary* dict = [URLTypes objectAtIndex:0];
+ if(dict != nil ) {
+ NSArray* URLSchemes = [dict objectForKey:@"CFBundleURLSchemes"];
+ if( URLSchemes != nil ) {
+ URLScheme = [URLSchemes objectAtIndex:0];
+ }
+ }
+ }
+
+ return URLScheme;
+}
+
+
+
+/**
+ Returns the contents of the named plist bundle, loaded as a dictionary object
+ */
++ (NSDictionary*) getBundlePlist:(NSString*)plistName
+{
+ NSString *errorDesc = nil;
+ NSPropertyListFormat format;
+ NSString *plistPath = [[NSBundle mainBundle] pathForResource:plistName ofType:@"plist"];
+ NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
+ NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization
+ propertyListFromData:plistXML
+ mutabilityOption:NSPropertyListMutableContainersAndLeaves
+ format:&format errorDescription:&errorDesc];
+ return temp;
+}
+
+/**
+ Returns the current version of phoneGap as read from the VERSION file
+ This only touches the filesystem once and stores the result in the class variable gapVersion
+ */
+static NSString *gapVersion;
++ (NSString*) phoneGapVersion
+{
+#ifdef PG_VERSION
+ gapVersion = SYMBOL_TO_NSSTRING(PG_VERSION);
+#else
+
+ if (gapVersion == nil) {
+ NSBundle *mainBundle = [NSBundle mainBundle];
+ NSString *filename = [mainBundle pathForResource:@"VERSION" ofType:nil];
+ // read from the filesystem and save in the variable
+ // first, separate by new line
+ NSString* fileContents = [NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:NULL];
+ NSArray* all_lines = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
+ NSString* first_line = [all_lines objectAtIndex:0];
+
+ gapVersion = [first_line retain];
+ }
+#endif
+
+ return gapVersion;
+}
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+@end
+
+#pragma mark -
+
+@implementation NSDictionary (LowercaseKeys)
+
+- (NSDictionary*) dictionaryWithLowercaseKeys
+{
+ NSMutableDictionary* result = [NSMutableDictionary dictionaryWithCapacity:self.count];
+ NSString* key;
+
+ for (key in self) {
+ [result setObject:[self objectForKey:key] forKey:[key lowercaseString]];
+ }
+
+ return result;
+}
+
+@end
View
2  PhoneGapLib/Classes/PhoneGapDelegate.h 100644 → 100755
@@ -16,7 +16,7 @@
@class Console;
@class PGWhitelist;
-@interface PhoneGapDelegate : NSObject <UIApplicationDelegate, UIWebViewDelegate>
+__attribute__((deprecated)) @interface PhoneGapDelegate : NSObject <UIApplicationDelegate, UIWebViewDelegate>
{
}
View
4 PhoneGapLib/Classes/PhoneGapDelegate.m 100644 → 100755
@@ -344,11 +344,11 @@ - (void) showSplashScreen
[self.window layoutSubviews];//asking window to do layout AFTER imageView is created refer to line: 250 self.window.autoresizesSubviews = YES;
}
-BOOL gSplashScreenShown = NO;
+BOOL gSplashScreenShown_ = NO;
- (void) receivedOrientationChange
{
if (self.imageView == nil) {
- gSplashScreenShown = YES;
+ gSplashScreenShown_ = YES;
[self showSplashScreen];
}
}
View
2  PhoneGapLib/Classes/PhoneGapViewController.h
@@ -9,7 +9,7 @@
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
-@interface PhoneGapViewController : UIViewController {
+__attribute__((deprecated)) @interface PhoneGapViewController : UIViewController {
}
@property (nonatomic, retain) NSArray* supportedOrientations;
View
32 PhoneGapLib/Classes/Sound.m
@@ -7,7 +7,8 @@
#import "Sound.h"
-#import "PhonegapDelegate.h"
+#import "PGAppDelegate.h"
+#import "PGViewController.h"
#define DOCUMENTS_SCHEME_PREFIX @"documents://"
#define HTTP_SCHEME_PREFIX @"http://"
@@ -15,31 +16,6 @@
@implementation PGSound
@synthesize soundCache, avSession;
-/*
-// Maps a url to the original resource path
-- (NSString*) resourceForUrl:(NSURL*)url
-{
- NSBundle* mainBundle = [NSBundle mainBundle];
- NSString* urlString = [url description];
- NSString* retVal = @"";
-
- NSString* wwwPath = [mainBundle pathForResource:[PhoneGapDelegate wwwFolderName] ofType:@"" inDirectory:@""];
- NSString* wwwUrl = [[NSURL fileURLWithPath:wwwPath] description];
- NSString* documentsUrl = [[NSURL fileURLWithPath:[PhoneGapDelegate applicationDocumentsDirectory]] description];
-
- if ([urlString hasPrefix:wwwUrl]) {
- retVal = [urlString substringFromIndex:[wwwUrl length]];
- } else if ([urlString hasPrefix:HTTP_SCHEME_PREFIX]) {
- retVal = urlString;
- } else if ([urlString hasPrefix:documentsUrl]) {
- retVal = [NSString stringWithFormat:@"%@%@", DOCUMENTS_SCHEME_PREFIX, [urlString substringFromIndex:[documentsUrl length]]];
- } else {
- NSLog(@"Cannot map url '%@' to a resource path.", urlString);
- }
-
- return retVal;
-}
-*/
// Maps a url for a resource path
// "Naked" resource paths are assumed to be from the www folder as its base
@@ -55,11 +31,11 @@ - (NSURL*) urlForResource:(NSString*)resourcePath
NSLog(@"Will use resource '%@' from the Internet.", resourcePath);
resourceURL = [NSURL URLWithString:resourcePath];
} else if ([resourcePath hasPrefix:DOCUMENTS_SCHEME_PREFIX]) {
- filePath = [resourcePath stringByReplacingOccurrencesOfString:DOCUMENTS_SCHEME_PREFIX withString:[NSString stringWithFormat:@"%@/",[PhoneGapDelegate applicationDocumentsDirectory]]];
+ filePath = [resourcePath stringByReplacingOccurrencesOfString:DOCUMENTS_SCHEME_PREFIX withString:[NSString stringWithFormat:@"%@/",[PGViewController applicationDocumentsDirectory]]];
NSLog(@"Will use resource '%@' from the documents folder with path = %@", resourcePath, filePath);
} else {
// attempt to find file path in www directory
- filePath = [PhoneGapDelegate pathForResource:resourcePath];
+ filePath = [PGViewController pathForResource:resourcePath];
if (filePath != nil) {
NSLog(@"Found resource '%@' in the web folder.", filePath);
}else {
View
18 PhoneGapLib/Classes/UIGapView.h
@@ -0,0 +1,18 @@
+//
+// UIGapView.h
+// BetaGapApp
+//
+// Created by Jesse MacFadyen on 11-01-29.
+// Copyright 2011 RisingJ.com. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+
+@interface UIGapView : UIWebView {
+
+
+}
+
+
+@end
View
36 PhoneGapLib/Classes/UIGapView.m
@@ -0,0 +1,36 @@
+//
+// UIGapView.m
+// BetaGapApp
+//
+// Created by Jesse MacFadyen on 11-01-29.
+// Copyright 2011 RisingJ.com. All rights reserved.
+//
+
+#import "UIGapView.h"
+
+
+@implementation UIGapView
+
+
+- (void)loadRequest:(NSURLRequest *)request
+{
+ [super loadRequest:request];
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+ // Drawing code.
+}
+*/
+
+
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+@end
View
102 PhoneGapLib/PhoneGapLib.xcodeproj/project.pbxproj
@@ -45,8 +45,7 @@
3032599E136B325100982B63 /* Location.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD471090FBE7009987E8 /* Location.m */; };
303259A1136B325100982B63 /* Notification.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD4F1090FBE7009987E8 /* Notification.m */; };
303259A2136B325100982B63 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD511090FBE7009987E8 /* NSData+Base64.m */; };
- 303259A4136B325100982B63 /* PhoneGapDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD5B1090FBE7009987E8 /* PhoneGapDelegate.m */; };
- 303259A5136B325100982B63 /* PhoneGapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD5D1090FBE7009987E8 /* PhoneGapViewController.m */; };
+ 303259A4136B325100982B63 /* PGAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD5B1090FBE7009987E8 /* PGAppDelegate.m */; };
303259A6136B325100982B63 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD5F1090FBE7009987E8 /* Reachability.m */; };
303259A7136B325100982B63 /* Sound.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD611090FBE7009987E8 /* Sound.m */; };
303259A8136B325100982B63 /* Accelerometer.m in Sources */ = {isa = PBXBuildFile; fileRef = 88BA573C109BB46F00FB5E78 /* Accelerometer.m */; };
@@ -62,8 +61,7 @@
303259BC136B326300982B63 /* Location.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD461090FBE7009987E8 /* Location.h */; settings = {ATTRIBUTES = (Public, ); }; };
303259BF136B326300982B63 /* Notification.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD4E1090FBE7009987E8 /* Notification.h */; settings = {ATTRIBUTES = (Public, ); }; };
303259C0136B326300982B63 /* NSData+Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD501090FBE7009987E8 /* NSData+Base64.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 303259C2136B326300982B63 /* PhoneGapDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD5A1090FBE7009987E8 /* PhoneGapDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 303259C3136B326300982B63 /* PhoneGapViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD5C1090FBE7009987E8 /* PhoneGapViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 303259C2136B326300982B63 /* PGAppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD5A1090FBE7009987E8 /* PGAppDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
303259C4136B326300982B63 /* Reachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD5E1090FBE7009987E8 /* Reachability.h */; settings = {ATTRIBUTES = (Public, ); }; };
303259C5136B326300982B63 /* Sound.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD601090FBE7009987E8 /* Sound.h */; settings = {ATTRIBUTES = (Public, ); }; };
303259C6136B326300982B63 /* Accelerometer.h in Headers */ = {isa = PBXBuildFile; fileRef = 88BA573B109BB46F00FB5E78 /* Accelerometer.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -71,7 +69,6 @@
303259C9136B326300982B63 /* PluginResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F92F49E1314023E0046367C /* PluginResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
303259CA136B326300982B63 /* FileTransfer.h in Headers */ = {isa = PBXBuildFile; fileRef = C937A4541337599E002C4C79 /* FileTransfer.h */; settings = {ATTRIBUTES = (Public, ); }; };
30325A0C136B343700982B63 /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 30325A0B136B343700982B63 /* VERSION */; };
- 30356214141049E1006C2D43 /* PGWhitelistTests.h in Headers */ = {isa = PBXBuildFile; fileRef = 30356212141049E1006C2D43 /* PGWhitelistTests.h */; };
3035621714104C34006C2D43 /* PGWhitelistTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 30356213141049E1006C2D43 /* PGWhitelistTests.m */; };
3035621814104C3E006C2D43 /* PGWhitelistTests.h in Resources */ = {isa = PBXBuildFile; fileRef = 30356212141049E1006C2D43 /* PGWhitelistTests.h */; };
30383DE01385F65600E37E22 /* Connection.m in Sources */ = {isa = PBXBuildFile; fileRef = 307A8F9D1385A2EC00E43782 /* Connection.m */; };
@@ -91,6 +88,12 @@
30AE4E97141953C7005A9C9A /* MockUIWebview.m in Sources */ = {isa = PBXBuildFile; fileRef = 30AE4E96141953C7005A9C9A /* MockUIWebview.m */; };
30AE4EA81419596F005A9C9A /* PGContactsTests.h in Resources */ = {isa = PBXBuildFile; fileRef = 30AE4E8B1419532F005A9C9A /* PGContactsTests.h */; };
30AE4EA91419596F005A9C9A /* MockUIWebview.h in Resources */ = {isa = PBXBuildFile; fileRef = 30AE4E95141953C7005A9C9A /* MockUIWebview.h */; };
+ 30B05D6F14BD22F10046A9AC /* PhoneGapDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B05D6B14BD22F10046A9AC /* PhoneGapDelegate.h */; };
+ 30B05D7014BD22F10046A9AC /* PhoneGapDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B05D6C14BD22F10046A9AC /* PhoneGapDelegate.m */; };
+ 30B05D7114BD22F10046A9AC /* PhoneGapViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B05D6D14BD22F10046A9AC /* PhoneGapViewController.h */; };
+ 30B05D7214BD22F10046A9AC /* PhoneGapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B05D6E14BD22F10046A9AC /* PhoneGapViewController.m */; };
+ 30B05DDA14BD24A10046A9AC /* PhoneGapDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B05D6B14BD22F10046A9AC /* PhoneGapDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 30B05DDB14BD24A10046A9AC /* PhoneGapViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B05D6D14BD22F10046A9AC /* PhoneGapViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
30B39EBE13D0268B0009682A /* PGSplashScreen.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B39EBC13D0268B0009682A /* PGSplashScreen.h */; };
30B39EBF13D0268B0009682A /* PGSplashScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B39EBD13D0268B0009682A /* PGSplashScreen.m */; };
30B39EC013D0268B0009682A /* PGSplashScreen.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B39EBC13D0268B0009682A /* PGSplashScreen.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -124,6 +127,16 @@
68A32D7D141030E4006B237C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 686357AE141002F100DF4CF2 /* CoreGraphics.framework */; };
68A32D7E141030EB006B237C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 686357AA141002F100DF4CF2 /* UIKit.framework */; };
68A32D7F141030F3006B237C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 686357AC141002F100DF4CF2 /* Foundation.framework */; };
+ 8852C43A14B65FD800F0E735 /* PGViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43614B65FD800F0E735 /* PGViewController.h */; };
+ 8852C43B14B65FD800F0E735 /* PGViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43614B65FD800F0E735 /* PGViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8852C43C14B65FD800F0E735 /* PGViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43714B65FD800F0E735 /* PGViewController.m */; };
+ 8852C43D14B65FD800F0E735 /* PGViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43714B65FD800F0E735 /* PGViewController.m */; };
+ 8852C43E14B65FD800F0E735 /* PGViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43714B65FD800F0E735 /* PGViewController.m */; };
+ 8852C43F14B65FD800F0E735 /* UIGapView.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43814B65FD800F0E735 /* UIGapView.h */; };
+ 8852C44014B65FD800F0E735 /* UIGapView.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43814B65FD800F0E735 /* UIGapView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8852C44114B65FD800F0E735 /* UIGapView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43914B65FD800F0E735 /* UIGapView.m */; };
+ 8852C44214B65FD800F0E735 /* UIGapView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43914B65FD800F0E735 /* UIGapView.m */; };
+ 8852C44314B65FD800F0E735 /* UIGapView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43914B65FD800F0E735 /* UIGapView.m */; };
8887FD661090FBE7009987E8 /* Camera.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD261090FBE7009987E8 /* Camera.h */; };
8887FD671090FBE7009987E8 /* Camera.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD271090FBE7009987E8 /* Camera.m */; };
8887FD681090FBE7009987E8 /* Categories.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD281090FBE7009987E8 /* Categories.h */; };
@@ -142,10 +155,8 @@
8887FD8E1090FBE7009987E8 /* Notification.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD4F1090FBE7009987E8 /* Notification.m */; };
8887FD8F1090FBE7009987E8 /* NSData+Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD501090FBE7009987E8 /* NSData+Base64.h */; };
8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD511090FBE7009987E8 /* NSData+Base64.m */; };
- 8887FD991090FBE7009987E8 /* PhoneGapDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD5A1090FBE7009987E8 /* PhoneGapDelegate.h */; };
- 8887FD9A1090FBE7009987E8 /* PhoneGapDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD5B1090FBE7009987E8 /* PhoneGapDelegate.m */; };
- 8887FD9B1090FBE7009987E8 /* PhoneGapViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD5C1090FBE7009987E8 /* PhoneGapViewController.h */; };
- 8887FD9C1090FBE7009987E8 /* PhoneGapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD5D1090FBE7009987E8 /* PhoneGapViewController.m */; };
+ 8887FD991090FBE7009987E8 /* PGAppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD5A1090FBE7009987E8 /* PGAppDelegate.h */; };
+ 8887FD9A1090FBE7009987E8 /* PGAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD5B1090FBE7009987E8 /* PGAppDelegate.m */; };
8887FD9D1090FBE7009987E8 /* Reachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD5E1090FBE7009987E8 /* Reachability.h */; };
8887FD9E1090FBE7009987E8 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD5F1090FBE7009987E8 /* Reachability.m */; };
8887FD9F1090FBE7009987E8 /* Sound.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD601090FBE7009987E8 /* Sound.h */; };
@@ -190,6 +201,10 @@
30AE4E8C1419532F005A9C9A /* PGContactsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGContactsTests.m; sourceTree = "<group>"; };
30AE4E95141953C7005A9C9A /* MockUIWebview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockUIWebview.h; sourceTree = "<group>"; };
30AE4E96141953C7005A9C9A /* MockUIWebview.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MockUIWebview.m; sourceTree = "<group>"; };
+ 30B05D6B14BD22F10046A9AC /* PhoneGapDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PhoneGapDelegate.h; path = Classes/PhoneGapDelegate.h; sourceTree = "<group>"; };
+ 30B05D6C14BD22F10046A9AC /* PhoneGapDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PhoneGapDelegate.m; path = Classes/PhoneGapDelegate.m; sourceTree = "<group>"; };
+ 30B05D6D14BD22F10046A9AC /* PhoneGapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PhoneGapViewController.h; path = Classes/PhoneGapViewController.h; sourceTree = "<group>"; };
+ 30B05D6E14BD22F10046A9AC /* PhoneGapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PhoneGapViewController.m; path = Classes/PhoneGapViewController.m; sourceTree = "<group>"; };
30B39EBC13D0268B0009682A /* PGSplashScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGSplashScreen.h; path = Classes/PGSplashScreen.h; sourceTree = "<group>"; };
30B39EBD13D0268B0009682A /* PGSplashScreen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PGSplashScreen.m; path = Classes/PGSplashScreen.m; sourceTree = "<group>"; };
30C6847E1406CB38004C1A8E /* PGWhitelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGWhitelist.h; path = Classes/PGWhitelist.h; sourceTree = "<group>"; };
@@ -218,6 +233,10 @@
686357DC14100B1600DF4CF2 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
68A32D7114102E1C006B237C /* libPhoneGap.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPhoneGap.a; sourceTree = BUILT_PRODUCTS_DIR; };
68A32D7414103017006B237C /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
+ 8852C43614B65FD800F0E735 /* PGViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGViewController.h; path = Classes/PGViewController.h; sourceTree = "<group>"; };
+ 8852C43714B65FD800F0E735 /* PGViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PGViewController.m; path = Classes/PGViewController.m; sourceTree = "<group>"; };
+ 8852C43814B65FD800F0E735 /* UIGapView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UIGapView.h; path = Classes/UIGapView.h; sourceTree = "<group>"; };
+ 8852C43914B65FD800F0E735 /* UIGapView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UIGapView.m; path = Classes/UIGapView.m; sourceTree = "<group>"; };
8887FD261090FBE7009987E8 /* Camera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Camera.h; path = Classes/Camera.h; sourceTree = "<group>"; };
8887FD271090FBE7009987E8 /* Camera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Camera.m; path = Classes/Camera.m; sourceTree = "<group>"; };
8887FD281090FBE7009987E8 /* Categories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Categories.h; path = Classes/Categories.h; sourceTree = "<group>"; };
@@ -236,10 +255,8 @@
8887FD4F1090FBE7009987E8 /* Notification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Notification.m; path = Classes/Notification.m; sourceTree = "<group>"; };
8887FD501090FBE7009987E8 /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSData+Base64.h"; path = "Classes/NSData+Base64.h"; sourceTree = "<group>"; };
8887FD511090FBE7009987E8 /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSData+Base64.m"; path = "Classes/NSData+Base64.m"; sourceTree = "<group>"; };
- 8887FD5A1090FBE7009987E8 /* PhoneGapDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PhoneGapDelegate.h; path = Classes/PhoneGapDelegate.h; sourceTree = "<group>"; };
- 8887FD5B1090FBE7009987E8 /* PhoneGapDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PhoneGapDelegate.m; path = Classes/PhoneGapDelegate.m; sourceTree = "<group>"; };
- 8887FD5C1090FBE7009987E8 /* PhoneGapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PhoneGapViewController.h; path = Classes/PhoneGapViewController.h; sourceTree = "<group>"; };
- 8887FD5D1090FBE7009987E8 /* PhoneGapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PhoneGapViewController.m; path = Classes/PhoneGapViewController.m; sourceTree = "<group>"; };
+ 8887FD5A1090FBE7009987E8 /* PGAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGAppDelegate.h; path = Classes/PGAppDelegate.h; sourceTree = "<group>"; };
+ 8887FD5B1090FBE7009987E8 /* PGAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PGAppDelegate.m; path = Classes/PGAppDelegate.m; sourceTree = "<group>"; };
8887FD5E1090FBE7009987E8 /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Reachability.h; path = Classes/Reachability.h; sourceTree = "<group>"; };
8887FD5F1090FBE7009987E8 /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Reachability.m; path = Classes/Reachability.m; sourceTree = "<group>"; };
8887FD601090FBE7009987E8 /* Sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sound.h; path = Classes/Sound.h; sourceTree = "<group>"; };
@@ -329,6 +346,28 @@
name = Frameworks;
sourceTree = "<group>";
};
+ 3054098714B77FF3009841CA /* Cleaver */ = {
+ isa = PBXGroup;
+ children = (
+ 8852C43614B65FD800F0E735 /* PGViewController.h */,
+ 8852C43714B65FD800F0E735 /* PGViewController.m */,
+ 8852C43814B65FD800F0E735 /* UIGapView.h */,
+ 8852C43914B65FD800F0E735 /* UIGapView.m */,
+ );
+ name = Cleaver;
+ sourceTree = "<group>";
+ };
+ 30B05D6914BD22D30046A9AC /* Deprecated */ = {
+ isa = PBXGroup;
+ children = (
+ 30B05D6B14BD22F10046A9AC /* PhoneGapDelegate.h */,
+ 30B05D6C14BD22F10046A9AC /* PhoneGapDelegate.m */,
+ 30B05D6D14BD22F10046A9AC /* PhoneGapViewController.h */,
+ 30B05D6E14BD22F10046A9AC /* PhoneGapViewController.m */,
+ );
+ name = Deprecated;
+ sourceTree = "<group>";
+ };
32C88DFF0371C24200C91783 /* Other Sources */ = {
isa = PBXGroup;
children = (
@@ -436,14 +475,14 @@
8887FD101090FB43009987E8 /* Classes */ = {
isa = PBXGroup;
children = (
+ 30B05D6914BD22D30046A9AC /* Deprecated */,
+ 3054098714B77FF3009841CA /* Cleaver */,
888700D710922F56009987E8 /* Commands */,
8887FD361090FBE7009987E8 /* JSON */,
888700D910923009009987E8 /* Util */,
888700D810922FD3009987E8 /* Plugins */,
- 8887FD5A1090FBE7009987E8 /* PhoneGapDelegate.h */,
- 8887FD5B1090FBE7009987E8 /* PhoneGapDelegate.m */,
- 8887FD5C1090FBE7009987E8 /* PhoneGapViewController.h */,
- 8887FD5D1090FBE7009987E8 /* PhoneGapViewController.m */,
+ 8887FD5A1090FBE7009987E8 /* PGAppDelegate.h */,
+ 8887FD5B1090FBE7009987E8 /* PGAppDelegate.m */,
);
name = Classes;
sourceTree = "<group>";
@@ -475,8 +514,7 @@
303259BC136B326300982B63 /* Location.h in Headers */,
303259BF136B326300982B63 /* Notification.h in Headers */,
303259C0136B326300982B63 /* NSData+Base64.h in Headers */,
- 303259C2136B326300982B63 /* PhoneGapDelegate.h in Headers */,
- 303259C3136B326300982B63 /* PhoneGapViewController.h in Headers */,
+ 303259C2136B326300982B63 /* PGAppDelegate.h in Headers */,
303259C4136B326300982B63 /* Reachability.h in Headers */,
303259C5136B326300982B63 /* Sound.h in Headers */,
303259C6136B326300982B63 /* Accelerometer.h in Headers */,
@@ -493,6 +531,10 @@
30C684811406CB38004C1A8E /* PGWhitelist.h in Headers */,
30B39EC013D0268B0009682A /* PGSplashScreen.h in Headers */,
30E563D113E217EC00C949AA /* NSMutableArray+QueueAdditions.h in Headers */,
+ 8852C43B14B65FD800F0E735 /* PGViewController.h in Headers */,
+ 8852C44014B65FD800F0E735 /* UIGapView.h in Headers */,
+ 30B05DDA14BD24A10046A9AC /* PhoneGapDelegate.h in Headers */,
+ 30B05DDB14BD24A10046A9AC /* PhoneGapViewController.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -509,8 +551,7 @@
8887FD851090FBE7009987E8 /* Location.h in Headers */,
8887FD8D1090FBE7009987E8 /* Notification.h in Headers */,
8887FD8F1090FBE7009987E8 /* NSData+Base64.h in Headers */,
- 8887FD991090FBE7009987E8 /* PhoneGapDelegate.h in Headers */,
- 8887FD9B1090FBE7009987E8 /* PhoneGapViewController.h in Headers */,
+ 8887FD991090FBE7009987E8 /* PGAppDelegate.h in Headers */,
8887FD9D1090FBE7009987E8 /* Reachability.h in Headers */,
8887FD9F1090FBE7009987E8 /* Sound.h in Headers */,
88BA573D109BB46F00FB5E78 /* Accelerometer.h in Headers */,
@@ -527,8 +568,11 @@
1F2BECC013F9785B00A93BF6 /* Battery.h in Headers */,
30C684801406CB38004C1A8E /* PGWhitelist.h in Headers */,
30C684941407044B004C1A8E /* PGURLProtocol.h in Headers */,
- 30356214141049E1006C2D43 /* PGWhitelistTests.h in Headers */,
30A90B9114588697006178D3 /* JSONKit.h in Headers */,
+ 8852C43A14B65FD800F0E735 /* PGViewController.h in Headers */,
+ 8852C43F14B65FD800F0E735 /* UIGapView.h in Headers */,
+ 30B05D6F14BD22F10046A9AC /* PhoneGapDelegate.h in Headers */,
+ 30B05D7114BD22F10046A9AC /* PhoneGapViewController.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -723,8 +767,7 @@
3032599E136B325100982B63 /* Location.m in Sources */,
303259A1136B325100982B63 /* Notification.m in Sources */,
303259A2136B325100982B63 /* NSData+Base64.m in Sources */,
- 303259A4136B325100982B63 /* PhoneGapDelegate.m in Sources */,
- 303259A5136B325100982B63 /* PhoneGapViewController.m in Sources */,
+ 303259A4136B325100982B63 /* PGAppDelegate.m in Sources */,
303259A6136B325100982B63 /* Reachability.m in Sources */,
303259A7136B325100982B63 /* Sound.m in Sources */,
303259A8136B325100982B63 /* Accelerometer.m in Sources */,
@@ -737,6 +780,8 @@
30C684831406CB38004C1A8E /* PGWhitelist.m in Sources */,
30C684971407044B004C1A8E /* PGURLProtocol.m in Sources */,
30A90B9414588697006178D3 /* JSONKit.m in Sources */,
+ 8852C43D14B65FD800F0E735 /* PGViewController.m in Sources */,
+ 8852C44214B65FD800F0E735 /* UIGapView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -748,6 +793,8 @@
686357BA141002F200DF4CF2 /* PluginResultJSONSerializationTests.m in Sources */,
30AE4E8D1419532F005A9C9A /* PGContactsTests.m in Sources */,
30AE4E97141953C7005A9C9A /* MockUIWebview.m in Sources */,
+ 8852C43E14B65FD800F0E735 /* PGViewController.m in Sources */,
+ 8852C44314B65FD800F0E735 /* UIGapView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -764,8 +811,7 @@
8887FD861090FBE7009987E8 /* Location.m in Sources */,
8887FD8E1090FBE7009987E8 /* Notification.m in Sources */,
8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */,
- 8887FD9A1090FBE7009987E8 /* PhoneGapDelegate.m in Sources */,
- 8887FD9C1090FBE7009987E8 /* PhoneGapViewController.m in Sources */,
+ 8887FD9A1090FBE7009987E8 /* PGAppDelegate.m in Sources */,
8887FD9E1090FBE7009987E8 /* Reachability.m in Sources */,
8887FDA01090FBE7009987E8 /* Sound.m in Sources */,
88BA573E109BB46F00FB5E78 /* Accelerometer.m in Sources */,
@@ -782,6 +828,10 @@
30C684821406CB38004C1A8E /* PGWhitelist.m in Sources */,
30C684961407044B004C1A8E /* PGURLProtocol.m in Sources */,
30A90B9314588697006178D3 /* JSONKit.m in Sources */,
+ 8852C43C14B65FD800F0E735 /* PGViewController.m in Sources */,
+ 8852C44114B65FD800F0E735 /* UIGapView.m in Sources */,
+ 30B05D7014BD22F10046A9AC /* PhoneGapDelegate.m in Sources */,
+ 30B05D7214BD22F10046A9AC /* PhoneGapViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Please sign in to comment.
Something went wrong with that request. Please try again.