Return-Path: X-Original-To: apmail-cordova-commits-archive@www.apache.org Delivered-To: apmail-cordova-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id EE0AB10202 for ; Tue, 11 Jun 2013 01:22:38 +0000 (UTC) Received: (qmail 73271 invoked by uid 500); 11 Jun 2013 01:22:38 -0000 Delivered-To: apmail-cordova-commits-archive@cordova.apache.org Received: (qmail 73248 invoked by uid 500); 11 Jun 2013 01:22:38 -0000 Mailing-List: contact commits-help@cordova.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cordova.apache.org Delivered-To: mailing list commits@cordova.apache.org Received: (qmail 73241 invoked by uid 99); 11 Jun 2013 01:22:38 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 11 Jun 2013 01:22:38 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 4349F8A3226; Tue, 11 Jun 2013 01:22:37 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: steven@apache.org To: commits@cordova.apache.org Date: Tue, 11 Jun 2013 01:22:38 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [3/6] removed native plugin files for various plugins http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/4c1a0e4d/CordovaLib/Classes/CDVInAppBrowser.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVInAppBrowser.m b/CordovaLib/Classes/CDVInAppBrowser.m deleted file mode 100644 index b832e23..0000000 --- a/CordovaLib/Classes/CDVInAppBrowser.m +++ /dev/null @@ -1,818 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -#import "CDVInAppBrowser.h" -#import "CDVPluginResult.h" -#import "CDVUserAgentUtil.h" -#import "CDVJSON.h" - -#define kInAppBrowserTargetSelf @"_self" -#define kInAppBrowserTargetSystem @"_system" -#define kInAppBrowserTargetBlank @"_blank" - -#define TOOLBAR_HEIGHT 44.0 -#define LOCATIONBAR_HEIGHT 21.0 -#define FOOTER_HEIGHT ((TOOLBAR_HEIGHT) + (LOCATIONBAR_HEIGHT)) - -#pragma mark CDVInAppBrowser - -@implementation CDVInAppBrowser - -- (CDVInAppBrowser*)initWithWebView:(UIWebView*)theWebView -{ - self = [super initWithWebView:theWebView]; - if (self != nil) { - // your initialization here - } - - return self; -} - -- (void)onReset -{ - [self close:nil]; -} - -- (void)close:(CDVInvokedUrlCommand*)command -{ - if (self.inAppBrowserViewController != nil) { - [self.inAppBrowserViewController close]; - self.inAppBrowserViewController = nil; - } - - self.callbackId = nil; -} - -- (void)open:(CDVInvokedUrlCommand*)command -{ - CDVPluginResult* pluginResult; - - NSString* url = [command argumentAtIndex:0]; - NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf]; - NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]]; - - self.callbackId = command.callbackId; - - if (url != nil) { - NSURL* baseUrl = [self.webView.request URL]; - NSURL* absoluteUrl = [[NSURL URLWithString:url relativeToURL:baseUrl] absoluteURL]; - if ([target isEqualToString:kInAppBrowserTargetSelf]) { - [self openInCordovaWebView:absoluteUrl withOptions:options]; - } else if ([target isEqualToString:kInAppBrowserTargetSystem]) { - [self openInSystem:absoluteUrl]; - } else { // _blank or anything else - [self openInInAppBrowser:absoluteUrl withOptions:options]; - } - - pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; - } else { - pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"incorrect number of arguments"]; - } - - [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]]; - [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; -} - -- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options -{ - if (self.inAppBrowserViewController == nil) { - NSString* originalUA = [CDVUserAgentUtil originalUserAgent]; - self.inAppBrowserViewController = [[CDVInAppBrowserViewController alloc] initWithUserAgent:originalUA prevUserAgent:[self.commandDelegate userAgent]]; - self.inAppBrowserViewController.navigationDelegate = self; - - if ([self.viewController conformsToProtocol:@protocol(CDVScreenOrientationDelegate)]) { - self.inAppBrowserViewController.orientationDelegate = (UIViewController *)self.viewController; - } - } - - - CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options]; - [self.inAppBrowserViewController showLocationBar:browserOptions.location]; - [self.inAppBrowserViewController showToolBar:browserOptions.toolbar]; - if (browserOptions.closebuttoncaption != nil) { - [self.inAppBrowserViewController setCloseButtonTitle:browserOptions.closebuttoncaption]; - } - // Set Presentation Style - UIModalPresentationStyle presentationStyle = UIModalPresentationFullScreen; // default - if (browserOptions.presentationstyle != nil) { - if ([[browserOptions.presentationstyle lowercaseString] isEqualToString:@"pagesheet"]) { - presentationStyle = UIModalPresentationPageSheet; - } else if ([[browserOptions.presentationstyle lowercaseString] isEqualToString:@"formsheet"]) { - presentationStyle = UIModalPresentationFormSheet; - } - } - self.inAppBrowserViewController.modalPresentationStyle = presentationStyle; - - // Set Transition Style - UIModalTransitionStyle transitionStyle = UIModalTransitionStyleCoverVertical; // default - if (browserOptions.transitionstyle != nil) { - if ([[browserOptions.transitionstyle lowercaseString] isEqualToString:@"fliphorizontal"]) { - transitionStyle = UIModalTransitionStyleFlipHorizontal; - } else if ([[browserOptions.transitionstyle lowercaseString] isEqualToString:@"crossdissolve"]) { - transitionStyle = UIModalTransitionStyleCrossDissolve; - } - } - self.inAppBrowserViewController.modalTransitionStyle = transitionStyle; - - - // UIWebView options - self.inAppBrowserViewController.webView.scalesPageToFit = browserOptions.enableviewportscale; - self.inAppBrowserViewController.webView.mediaPlaybackRequiresUserAction = browserOptions.mediaplaybackrequiresuseraction; - self.inAppBrowserViewController.webView.allowsInlineMediaPlayback = browserOptions.allowinlinemediaplayback; - if (IsAtLeastiOSVersion(@"6.0")) { - self.inAppBrowserViewController.webView.keyboardDisplayRequiresUserAction = browserOptions.keyboarddisplayrequiresuseraction; - self.inAppBrowserViewController.webView.suppressesIncrementalRendering = browserOptions.suppressesincrementalrendering; - } - - if (! browserOptions.hidden) { - if (self.viewController.modalViewController != self.inAppBrowserViewController) { - [self.viewController presentModalViewController:self.inAppBrowserViewController animated:YES]; - } - } - [self.inAppBrowserViewController navigateTo:url]; -} - -- (void)show:(CDVInvokedUrlCommand*)command -{ - [self.viewController presentModalViewController:self.inAppBrowserViewController animated:YES]; -} - -- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options -{ - if ([self.commandDelegate URLIsWhitelisted:url]) { - NSURLRequest* request = [NSURLRequest requestWithURL:url]; - [self.webView loadRequest:request]; - } else { // this assumes the InAppBrowser can be excepted from the white-list - [self openInInAppBrowser:url withOptions:options]; - } -} - -- (void)openInSystem:(NSURL*)url -{ - if ([[UIApplication sharedApplication] canOpenURL:url]) { - [[UIApplication sharedApplication] openURL:url]; - } else { // handle any custom schemes to plugins - [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]]; - } -} - -// This is a helper method for the inject{Script|Style}{Code|File} API calls, which -// provides a consistent method for injecting JavaScript code into the document. -// -// If a wrapper string is supplied, then the source string will be JSON-encoded (adding -// quotes) and wrapped using string formatting. (The wrapper string should have a single -// '%@' marker). -// -// If no wrapper is supplied, then the source string is executed directly. - -- (void)injectDeferredObject:(NSString*)source withWrapper:(NSString*)jsWrapper -{ - if (!_injectedIframeBridge) { - _injectedIframeBridge = YES; - // Create an iframe bridge in the new document to communicate with the CDVInAppBrowserViewController - [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:@"(function(d){var e = _cdvIframeBridge = d.createElement('iframe');e.style.display='none';d.body.appendChild(e);})(document)"]; - } - - if (jsWrapper != nil) { - NSString* sourceArrayString = [@[source] JSONString]; - if (sourceArrayString) { - NSString* sourceString = [sourceArrayString substringWithRange:NSMakeRange(1, [sourceArrayString length] - 2)]; - NSString* jsToInject = [NSString stringWithFormat:jsWrapper, sourceString]; - [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:jsToInject]; - } - } else { - [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:source]; - } -} - -- (void)injectScriptCode:(CDVInvokedUrlCommand*)command -{ - NSString* jsWrapper = nil; - - if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) { - jsWrapper = [NSString stringWithFormat:@"_cdvIframeBridge.src='gap-iab://%@/'+window.escape(JSON.stringify([eval(%%@)]));", command.callbackId]; - } - [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper]; -} - -- (void)injectScriptFile:(CDVInvokedUrlCommand*)command -{ - NSString* jsWrapper; - - if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) { - jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('script'); c.src = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId]; - } else { - jsWrapper = @"(function(d) { var c = d.createElement('script'); c.src = %@; d.body.appendChild(c); })(document)"; - } - [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper]; -} - -- (void)injectStyleCode:(CDVInvokedUrlCommand*)command -{ - NSString* jsWrapper; - - if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) { - jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('style'); c.innerHTML = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId]; - } else { - jsWrapper = @"(function(d) { var c = d.createElement('style'); c.innerHTML = %@; d.body.appendChild(c); })(document)"; - } - [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper]; -} - -- (void)injectStyleFile:(CDVInvokedUrlCommand*)command -{ - NSString* jsWrapper; - - if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) { - jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId]; - } else { - jsWrapper = @"(function(d) { var c = d.createElement('link'); c.rel='stylesheet', c.type='text/css'; c.href = %@; d.body.appendChild(c); })(document)"; - } - [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper]; -} - -/** - * The iframe bridge provided for the InAppBrowser is capable of executing any oustanding callback belonging - * to the InAppBrowser plugin. Care has been taken that other callbacks cannot be triggered, and that no - * other code execution is possible. - * - * To trigger the bridge, the iframe (or any other resource) should attempt to load a url of the form: - * - * gap-iab:/// - * - * where is the string id of the callback to trigger (something like "InAppBrowser0123456789") - * - * If present, the path component of the special gap-iab:// url is expected to be a URL-escaped JSON-encoded - * value to pass to the callback. [NSURL path] should take care of the URL-unescaping, and a JSON_EXCEPTION - * is returned if the JSON is invalid. - */ -- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType -{ - NSURL* url = request.URL; - BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]]; - - // See if the url uses the 'gap-iab' protocol. If so, the host should be the id of a callback to execute, - // and the path, if present, should be a JSON-encoded value to pass to the callback. - if ([[url scheme] isEqualToString:@"gap-iab"]) { - NSString* scriptCallbackId = [url host]; - CDVPluginResult* pluginResult = nil; - - if ([scriptCallbackId hasPrefix:@"InAppBrowser"]) { - NSString* scriptResult = [url path]; - NSError* __autoreleasing error = nil; - - // The message should be a JSON-encoded array of the result of the script which executed. - if ((scriptResult != nil) && ([scriptResult length] > 1)) { - scriptResult = [scriptResult substringFromIndex:1]; - NSData* decodedResult = [NSJSONSerialization JSONObjectWithData:[scriptResult dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error]; - if ((error == nil) && [decodedResult isKindOfClass:[NSArray class]]) { - pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:(NSArray*)decodedResult]; - } else { - pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_JSON_EXCEPTION]; - } - } else { - pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:@[]]; - } - [self.commandDelegate sendPluginResult:pluginResult callbackId:scriptCallbackId]; - return NO; - } - } else if ((self.callbackId != nil) && isTopLevelNavigation) { - // Send a loadstart event for each top-level navigation (includes redirects). - CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK - messageAsDictionary:@{@"type":@"loadstart", @"url":[url absoluteString]}]; - [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]]; - - [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; - } - - return YES; -} - -- (void)webViewDidStartLoad:(UIWebView*)theWebView -{ - _injectedIframeBridge = NO; -} - -- (void)webViewDidFinishLoad:(UIWebView*)theWebView -{ - if (self.callbackId != nil) { - // TODO: It would be more useful to return the URL the page is actually on (e.g. if it's been redirected). - NSString* url = [self.inAppBrowserViewController.currentURL absoluteString]; - CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK - messageAsDictionary:@{@"type":@"loadstop", @"url":url}]; - [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]]; - - [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; - } -} - -- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error -{ - if (self.callbackId != nil) { - NSString* url = [self.inAppBrowserViewController.currentURL absoluteString]; - CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR - messageAsDictionary:@{@"type":@"loaderror", @"url":url, @"code": [NSNumber numberWithInt:error.code], @"message": error.localizedDescription}]; - [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]]; - - [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; - } -} - -- (void)browserExit -{ - if (self.callbackId != nil) { - CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK - messageAsDictionary:@{@"type":@"exit"}]; - [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]]; - - [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; - } - // Don't recycle the ViewController since it may be consuming a lot of memory. - // Also - this is required for the PDF/User-Agent bug work-around. - self.inAppBrowserViewController = nil; -} - -@end - -#pragma mark CDVInAppBrowserViewController - -@implementation CDVInAppBrowserViewController - -@synthesize currentURL; - -- (id)initWithUserAgent:(NSString*)userAgent prevUserAgent:(NSString*)prevUserAgent -{ - self = [super init]; - if (self != nil) { - _userAgent = userAgent; - _prevUserAgent = prevUserAgent; - _webViewDelegate = [[CDVWebViewDelegate alloc] initWithDelegate:self]; - [self createViews]; - } - - return self; -} - -- (void)createViews -{ - // We create the views in code for primarily for ease of upgrades and not requiring an external .xib to be included - - CGRect webViewBounds = self.view.bounds; - - webViewBounds.size.height -= FOOTER_HEIGHT; - - self.webView = [[UIWebView alloc] initWithFrame:webViewBounds]; - self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); - - [self.view addSubview:self.webView]; - [self.view sendSubviewToBack:self.webView]; - - self.webView.delegate = _webViewDelegate; - self.webView.backgroundColor = [UIColor whiteColor]; - - self.webView.clearsContextBeforeDrawing = YES; - self.webView.clipsToBounds = YES; - self.webView.contentMode = UIViewContentModeScaleToFill; - self.webView.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}"); - self.webView.multipleTouchEnabled = YES; - self.webView.opaque = YES; - self.webView.scalesPageToFit = NO; - self.webView.userInteractionEnabled = YES; - - self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; - self.spinner.alpha = 1.000; - self.spinner.autoresizesSubviews = YES; - self.spinner.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin; - self.spinner.clearsContextBeforeDrawing = NO; - self.spinner.clipsToBounds = NO; - self.spinner.contentMode = UIViewContentModeScaleToFill; - self.spinner.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}"); - self.spinner.frame = CGRectMake(454.0, 231.0, 20.0, 20.0); - self.spinner.hidden = YES; - self.spinner.hidesWhenStopped = YES; - self.spinner.multipleTouchEnabled = NO; - self.spinner.opaque = NO; - self.spinner.userInteractionEnabled = NO; - [self.spinner stopAnimating]; - - self.closeButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)]; - self.closeButton.enabled = YES; - - UIBarButtonItem* flexibleSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; - - UIBarButtonItem* fixedSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; - fixedSpaceButton.width = 20; - - self.toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, (self.view.bounds.size.height - TOOLBAR_HEIGHT), self.view.bounds.size.width, TOOLBAR_HEIGHT)]; - self.toolbar.alpha = 1.000; - self.toolbar.autoresizesSubviews = YES; - self.toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; - self.toolbar.barStyle = UIBarStyleBlackOpaque; - self.toolbar.clearsContextBeforeDrawing = NO; - self.toolbar.clipsToBounds = NO; - self.toolbar.contentMode = UIViewContentModeScaleToFill; - self.toolbar.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}"); - self.toolbar.hidden = NO; - self.toolbar.multipleTouchEnabled = NO; - self.toolbar.opaque = NO; - self.toolbar.userInteractionEnabled = YES; - - CGFloat labelInset = 5.0; - self.addressLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelInset, (self.view.bounds.size.height - FOOTER_HEIGHT), self.view.bounds.size.width - labelInset, LOCATIONBAR_HEIGHT)]; - self.addressLabel.adjustsFontSizeToFitWidth = NO; - self.addressLabel.alpha = 1.000; - self.addressLabel.autoresizesSubviews = YES; - self.addressLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin; - self.addressLabel.backgroundColor = [UIColor clearColor]; - self.addressLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; - self.addressLabel.clearsContextBeforeDrawing = YES; - self.addressLabel.clipsToBounds = YES; - self.addressLabel.contentMode = UIViewContentModeScaleToFill; - self.addressLabel.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}"); - self.addressLabel.enabled = YES; - self.addressLabel.hidden = NO; - self.addressLabel.lineBreakMode = UILineBreakModeTailTruncation; - self.addressLabel.minimumFontSize = 10.000; - self.addressLabel.multipleTouchEnabled = NO; - self.addressLabel.numberOfLines = 1; - self.addressLabel.opaque = NO; - self.addressLabel.shadowOffset = CGSizeMake(0.0, -1.0); - self.addressLabel.text = @"Loading..."; - self.addressLabel.textAlignment = UITextAlignmentLeft; - self.addressLabel.textColor = [UIColor colorWithWhite:1.000 alpha:1.000]; - self.addressLabel.userInteractionEnabled = NO; - - NSString* frontArrowString = @"►"; // create arrow from Unicode char - self.forwardButton = [[UIBarButtonItem alloc] initWithTitle:frontArrowString style:UIBarButtonItemStylePlain target:self action:@selector(goForward:)]; - self.forwardButton.enabled = YES; - self.forwardButton.imageInsets = UIEdgeInsetsZero; - - NSString* backArrowString = @"◄"; // create arrow from Unicode char - self.backButton = [[UIBarButtonItem alloc] initWithTitle:backArrowString style:UIBarButtonItemStylePlain target:self action:@selector(goBack:)]; - self.backButton.enabled = YES; - self.backButton.imageInsets = UIEdgeInsetsZero; - - [self.toolbar setItems:@[self.closeButton, flexibleSpaceButton, self.backButton, fixedSpaceButton, self.forwardButton]]; - - self.view.backgroundColor = [UIColor grayColor]; - [self.view addSubview:self.toolbar]; - [self.view addSubview:self.addressLabel]; - [self.view addSubview:self.spinner]; -} - -- (void)setCloseButtonTitle:(NSString*)title -{ - // the advantage of using UIBarButtonSystemItemDone is the system will localize it for you automatically - // but, if you want to set this yourself, knock yourself out (we can't set the title for a system Done button, so we have to create a new one) - self.closeButton = nil; - self.closeButton = [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStyleBordered target:self action:@selector(close)]; - self.closeButton.enabled = YES; - self.closeButton.tintColor = [UIColor colorWithRed:60.0 / 255.0 green:136.0 / 255.0 blue:230.0 / 255.0 alpha:1]; - - NSMutableArray* items = [self.toolbar.items mutableCopy]; - [items replaceObjectAtIndex:0 withObject:self.closeButton]; - [self.toolbar setItems:items]; -} - -- (void)showLocationBar:(BOOL)show -{ - CGRect locationbarFrame = self.addressLabel.frame; - - BOOL toolbarVisible = !self.toolbar.hidden; - - // prevent double show/hide - if (show == !(self.addressLabel.hidden)) { - return; - } - - if (show) { - self.addressLabel.hidden = NO; - - if (toolbarVisible) { - // toolBar at the bottom, leave as is - // put locationBar on top of the toolBar - - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= FOOTER_HEIGHT; - self.webView.frame = webViewBounds; - - locationbarFrame.origin.y = webViewBounds.size.height; - self.addressLabel.frame = locationbarFrame; - } else { - // no toolBar, so put locationBar at the bottom - - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= LOCATIONBAR_HEIGHT; - self.webView.frame = webViewBounds; - - locationbarFrame.origin.y = webViewBounds.size.height; - self.addressLabel.frame = locationbarFrame; - } - } else { - self.addressLabel.hidden = YES; - - if (toolbarVisible) { - // locationBar is on top of toolBar, hide locationBar - - // webView take up whole height less toolBar height - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= TOOLBAR_HEIGHT; - self.webView.frame = webViewBounds; - } else { - // no toolBar, expand webView to screen dimensions - - CGRect webViewBounds = self.view.bounds; - self.webView.frame = webViewBounds; - } - } -} - -- (void)showToolBar:(BOOL)show -{ - CGRect toolbarFrame = self.toolbar.frame; - CGRect locationbarFrame = self.addressLabel.frame; - - BOOL locationbarVisible = !self.addressLabel.hidden; - - // prevent double show/hide - if (show == !(self.toolbar.hidden)) { - return; - } - - if (show) { - self.toolbar.hidden = NO; - - if (locationbarVisible) { - // locationBar at the bottom, move locationBar up - // put toolBar at the bottom - - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= FOOTER_HEIGHT; - self.webView.frame = webViewBounds; - - locationbarFrame.origin.y = webViewBounds.size.height; - self.addressLabel.frame = locationbarFrame; - - toolbarFrame.origin.y = (webViewBounds.size.height + LOCATIONBAR_HEIGHT); - self.toolbar.frame = toolbarFrame; - } else { - // no locationBar, so put toolBar at the bottom - - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= TOOLBAR_HEIGHT; - self.webView.frame = webViewBounds; - - toolbarFrame.origin.y = webViewBounds.size.height; - self.toolbar.frame = toolbarFrame; - } - } else { - self.toolbar.hidden = YES; - - if (locationbarVisible) { - // locationBar is on top of toolBar, hide toolBar - // put locationBar at the bottom - - // webView take up whole height less locationBar height - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= LOCATIONBAR_HEIGHT; - self.webView.frame = webViewBounds; - - // move locationBar down - locationbarFrame.origin.y = webViewBounds.size.height; - self.addressLabel.frame = locationbarFrame; - } else { - // no locationBar, expand webView to screen dimensions - - CGRect webViewBounds = self.view.bounds; - self.webView.frame = webViewBounds; - } - } -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; -} - -- (void)viewDidUnload -{ - [self.webView loadHTMLString:nil baseURL:nil]; - [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; - [super viewDidUnload]; -} - -- (void)close -{ - [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; - - if ([self respondsToSelector:@selector(presentingViewController)]) { - [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil]; - } else { - [[self parentViewController] dismissModalViewControllerAnimated:YES]; - } - - self.currentURL = nil; - - if ((self.navigationDelegate != nil) && [self.navigationDelegate respondsToSelector:@selector(browserExit)]) { - [self.navigationDelegate browserExit]; - } -} - -- (void)navigateTo:(NSURL*)url -{ - NSURLRequest* request = [NSURLRequest requestWithURL:url]; - - if (_userAgentLockToken != 0) { - [self.webView loadRequest:request]; - } else { - [CDVUserAgentUtil acquireLock:^(NSInteger lockToken) { - _userAgentLockToken = lockToken; - [CDVUserAgentUtil setUserAgent:_userAgent lockToken:lockToken]; - [self.webView loadRequest:request]; - }]; - } -} - -- (void)goBack:(id)sender -{ - [self.webView goBack]; -} - -- (void)goForward:(id)sender -{ - [self.webView goForward]; -} - -#pragma mark UIWebViewDelegate - -- (void)webViewDidStartLoad:(UIWebView*)theWebView -{ - // loading url, start spinner, update back/forward - - self.addressLabel.text = @"Loading..."; - self.backButton.enabled = theWebView.canGoBack; - self.forwardButton.enabled = theWebView.canGoForward; - - [self.spinner startAnimating]; - - return [self.navigationDelegate webViewDidStartLoad:theWebView]; -} - -- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType -{ - BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]]; - - if (isTopLevelNavigation) { - self.currentURL = request.URL; - } - return [self.navigationDelegate webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType]; -} - -- (void)webViewDidFinishLoad:(UIWebView*)theWebView -{ - // update url, stop spinner, update back/forward - - self.addressLabel.text = [self.currentURL absoluteString]; - self.backButton.enabled = theWebView.canGoBack; - self.forwardButton.enabled = theWebView.canGoForward; - - [self.spinner stopAnimating]; - - // Work around a bug where the first time a PDF is opened, all UIWebViews - // reload their User-Agent from NSUserDefaults. - // This work-around makes the following assumptions: - // 1. The app has only a single Cordova Webview. If not, then the app should - // take it upon themselves to load a PDF in the background as a part of - // their start-up flow. - // 2. That the PDF does not require any additional network requests. We change - // the user-agent here back to that of the CDVViewController, so requests - // from it must pass through its white-list. This *does* break PDFs that - // contain links to other remote PDF/websites. - // More info at https://issues.apache.org/jira/browse/CB-2225 - BOOL isPDF = [@"true" isEqualToString :[theWebView stringByEvaluatingJavaScriptFromString:@"document.body==null"]]; - if (isPDF) { - [CDVUserAgentUtil setUserAgent:_prevUserAgent lockToken:_userAgentLockToken]; - } - - [self.navigationDelegate webViewDidFinishLoad:theWebView]; -} - -- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error -{ - // log fail message, stop spinner, update back/forward - NSLog(@"webView:didFailLoadWithError - %@", [error localizedDescription]); - - self.backButton.enabled = theWebView.canGoBack; - self.forwardButton.enabled = theWebView.canGoForward; - [self.spinner stopAnimating]; - - self.addressLabel.text = @"Load Error"; - - [self.navigationDelegate webView:theWebView didFailLoadWithError:error]; -} - -#pragma mark CDVScreenOrientationDelegate - -- (BOOL)shouldAutorotate -{ - if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotate)]) { - return [self.orientationDelegate shouldAutorotate]; - } - return YES; -} - -- (NSUInteger)supportedInterfaceOrientations -{ - if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(supportedInterfaceOrientations)]) { - return [self.orientationDelegate supportedInterfaceOrientations]; - } - - return 1 << UIInterfaceOrientationPortrait; -} - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -{ - if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) { - return [self.orientationDelegate shouldAutorotateToInterfaceOrientation:interfaceOrientation]; - } - - return YES; -} - -@end - -@implementation CDVInAppBrowserOptions - -- (id)init -{ - if (self = [super init]) { - // default values - self.location = YES; - self.toolbar = YES; - self.closebuttoncaption = nil; - - self.enableviewportscale = NO; - self.mediaplaybackrequiresuseraction = NO; - self.allowinlinemediaplayback = NO; - self.keyboarddisplayrequiresuseraction = YES; - self.suppressesincrementalrendering = NO; - self.hidden = NO; - } - - return self; -} - -+ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options -{ - CDVInAppBrowserOptions* obj = [[CDVInAppBrowserOptions alloc] init]; - - // NOTE: this parsing does not handle quotes within values - NSArray* pairs = [options componentsSeparatedByString:@","]; - - // parse keys and values, set the properties - for (NSString* pair in pairs) { - NSArray* keyvalue = [pair componentsSeparatedByString:@"="]; - - if ([keyvalue count] == 2) { - NSString* key = [[keyvalue objectAtIndex:0] lowercaseString]; - NSString* value = [keyvalue objectAtIndex:1]; - NSString* value_lc = [value lowercaseString]; - - BOOL isBoolean = [value_lc isEqualToString:@"yes"] || [value_lc isEqualToString:@"no"]; - NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init]; - [numberFormatter setAllowsFloats:YES]; - BOOL isNumber = [numberFormatter numberFromString:value_lc] != nil; - - // set the property according to the key name - if ([obj respondsToSelector:NSSelectorFromString(key)]) { - if (isNumber) { - [obj setValue:[numberFormatter numberFromString:value_lc] forKey:key]; - } else if (isBoolean) { - [obj setValue:[NSNumber numberWithBool:[value_lc isEqualToString:@"yes"]] forKey:key]; - } else { - [obj setValue:value forKey:key]; - } - } - } - } - - return obj; -} - -@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/4c1a0e4d/CordovaLib/Classes/CDVLocation.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVLocation.h b/CordovaLib/Classes/CDVLocation.h deleted file mode 100644 index caf0798..0000000 --- a/CordovaLib/Classes/CDVLocation.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -#import -#import -#import "CDVPlugin.h" - -enum CDVHeadingStatus { - HEADINGSTOPPED = 0, - HEADINGSTARTING, - HEADINGRUNNING, - HEADINGERROR -}; -typedef NSUInteger CDVHeadingStatus; - -enum CDVLocationStatus { - PERMISSIONDENIED = 1, - POSITIONUNAVAILABLE, - TIMEOUT -}; -typedef NSUInteger CDVLocationStatus; - -// simple object to keep track of heading information -@interface CDVHeadingData : NSObject {} - -@property (nonatomic, assign) CDVHeadingStatus headingStatus; -@property (nonatomic, strong) CLHeading* headingInfo; -@property (nonatomic, strong) NSMutableArray* headingCallbacks; -@property (nonatomic, copy) NSString* headingFilter; -@property (nonatomic, strong) NSDate* headingTimestamp; -@property (assign) NSInteger timeout; - -@end - -// simple object to keep track of location information -@interface CDVLocationData : NSObject { - CDVLocationStatus locationStatus; - NSMutableArray* locationCallbacks; - NSMutableDictionary* watchCallbacks; - CLLocation* locationInfo; -} - -@property (nonatomic, assign) CDVLocationStatus locationStatus; -@property (nonatomic, strong) CLLocation* locationInfo; -@property (nonatomic, strong) NSMutableArray* locationCallbacks; -@property (nonatomic, strong) NSMutableDictionary* watchCallbacks; - -@end - -@interface CDVLocation : CDVPlugin { - @private BOOL __locationStarted; - @private BOOL __highAccuracyEnabled; - CDVHeadingData* headingData; - CDVLocationData* locationData; -} - -@property (nonatomic, strong) CLLocationManager* locationManager; -@property (strong) CDVHeadingData* headingData; -@property (nonatomic, strong) CDVLocationData* locationData; - -- (BOOL)hasHeadingSupport; -- (void)getLocation:(CDVInvokedUrlCommand*)command; -- (void)addWatch:(CDVInvokedUrlCommand*)command; -- (void)clearWatch:(CDVInvokedUrlCommand*)command; -- (void)returnLocationInfo:(NSString*)callbackId andKeepCallback:(BOOL)keepCallback; -- (void)returnLocationError:(NSUInteger)errorCode withMessage:(NSString*)message; -- (void)startLocation:(BOOL)enableHighAccuracy; - -- (void)locationManager:(CLLocationManager*)manager - didUpdateToLocation:(CLLocation*)newLocation - fromLocation:(CLLocation*)oldLocation; - -- (void)locationManager:(CLLocationManager*)manager - didFailWithError:(NSError*)error; - -- (BOOL)isLocationServicesEnabled; - -- (void)getHeading:(CDVInvokedUrlCommand*)command; -- (void)returnHeadingInfo:(NSString*)callbackId keepCallback:(BOOL)bRetain; -- (void)watchHeadingFilter:(CDVInvokedUrlCommand*)command; -- (void)stopHeading:(CDVInvokedUrlCommand*)command; -- (void)startHeadingWithFilter:(CLLocationDegrees)filter; -- (void)locationManager:(CLLocationManager*)manager - didUpdateHeading:(CLHeading*)heading; - -- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager*)manager; - -@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/4c1a0e4d/CordovaLib/Classes/CDVLocation.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVLocation.m b/CordovaLib/Classes/CDVLocation.m deleted file mode 100644 index ed9ec26..0000000 --- a/CordovaLib/Classes/CDVLocation.m +++ /dev/null @@ -1,623 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -#import "CDVLocation.h" -#import "NSArray+Comparisons.h" - -#pragma mark Constants - -#define kPGLocationErrorDomain @"kPGLocationErrorDomain" -#define kPGLocationDesiredAccuracyKey @"desiredAccuracy" -#define kPGLocationForcePromptKey @"forcePrompt" -#define kPGLocationDistanceFilterKey @"distanceFilter" -#define kPGLocationFrequencyKey @"frequency" - -#pragma mark - -#pragma mark Categories - -@interface NSError (JSONMethods) - -- (NSString*)JSONRepresentation; - -@end - -@interface CLLocation (JSONMethods) - -- (NSString*)JSONRepresentation; - -@end - -@interface CLHeading (JSONMethods) - -- (NSString*)JSONRepresentation; - -@end - -#pragma mark - -#pragma mark CDVHeadingData - -@implementation CDVHeadingData - -@synthesize headingStatus, headingInfo, headingCallbacks, headingFilter, headingTimestamp, timeout; -- (CDVHeadingData*)init -{ - self = (CDVHeadingData*)[super init]; - if (self) { - self.headingStatus = HEADINGSTOPPED; - self.headingInfo = nil; - self.headingCallbacks = nil; - self.headingFilter = nil; - self.headingTimestamp = nil; - self.timeout = 10; - } - return self; -} - -@end - -@implementation CDVLocationData - -@synthesize locationStatus, locationInfo, locationCallbacks, watchCallbacks; -- (CDVLocationData*)init -{ - self = (CDVLocationData*)[super init]; - if (self) { - self.locationInfo = nil; - self.locationCallbacks = nil; - self.watchCallbacks = nil; - } - return self; -} - -@end - -#pragma mark - -#pragma mark CDVLocation - -@implementation CDVLocation - -@synthesize locationManager, headingData, locationData; - -- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView -{ - self = (CDVLocation*)[super initWithWebView:(UIWebView*)theWebView]; - if (self) { - self.locationManager = [[CLLocationManager alloc] init]; - self.locationManager.delegate = self; // Tells the location manager to send updates to this object - __locationStarted = NO; - __highAccuracyEnabled = NO; - self.headingData = nil; - self.locationData = nil; - } - return self; -} - -- (BOOL)hasHeadingSupport -{ - BOOL headingInstancePropertyAvailable = [self.locationManager respondsToSelector:@selector(headingAvailable)]; // iOS 3.x - BOOL headingClassPropertyAvailable = [CLLocationManager respondsToSelector:@selector(headingAvailable)]; // iOS 4.x - - if (headingInstancePropertyAvailable) { // iOS 3.x - return [(id)self.locationManager headingAvailable]; - } else if (headingClassPropertyAvailable) { // iOS 4.x - return [CLLocationManager headingAvailable]; - } else { // iOS 2.x - return NO; - } -} - -- (BOOL)isAuthorized -{ - BOOL authorizationStatusClassPropertyAvailable = [CLLocationManager respondsToSelector:@selector(authorizationStatus)]; // iOS 4.2+ - - if (authorizationStatusClassPropertyAvailable) { - NSUInteger authStatus = [CLLocationManager authorizationStatus]; - return (authStatus == kCLAuthorizationStatusAuthorized) || (authStatus == kCLAuthorizationStatusNotDetermined); - } - - // by default, assume YES (for iOS < 4.2) - return YES; -} - -- (BOOL)isLocationServicesEnabled -{ - BOOL locationServicesEnabledInstancePropertyAvailable = [self.locationManager respondsToSelector:@selector(locationServicesEnabled)]; // iOS 3.x - BOOL locationServicesEnabledClassPropertyAvailable = [CLLocationManager respondsToSelector:@selector(locationServicesEnabled)]; // iOS 4.x - - if (locationServicesEnabledClassPropertyAvailable) { // iOS 4.x - return [CLLocationManager locationServicesEnabled]; - } else if (locationServicesEnabledInstancePropertyAvailable) { // iOS 2.x, iOS 3.x - return [(id)self.locationManager locationServicesEnabled]; - } else { - return NO; - } -} - -- (void)startLocation:(BOOL)enableHighAccuracy -{ - if (![self isLocationServicesEnabled]) { - [self returnLocationError:PERMISSIONDENIED withMessage:@"Location services are not enabled."]; - return; - } - if (![self isAuthorized]) { - NSString* message = nil; - BOOL authStatusAvailable = [CLLocationManager respondsToSelector:@selector(authorizationStatus)]; // iOS 4.2+ - if (authStatusAvailable) { - NSUInteger code = [CLLocationManager authorizationStatus]; - if (code == kCLAuthorizationStatusNotDetermined) { - // could return POSITION_UNAVAILABLE but need to coordinate with other platforms - message = @"User undecided on application's use of location services."; - } else if (code == kCLAuthorizationStatusRestricted) { - message = @"Application's use of location services is restricted."; - } - } - // PERMISSIONDENIED is only PositionError that makes sense when authorization denied - [self returnLocationError:PERMISSIONDENIED withMessage:message]; - - return; - } - - // Tell the location manager to start notifying us of location updates. We - // first stop, and then start the updating to ensure we get at least one - // update, even if our location did not change. - [self.locationManager stopUpdatingLocation]; - [self.locationManager startUpdatingLocation]; - __locationStarted = YES; - if (enableHighAccuracy) { - __highAccuracyEnabled = YES; - // Set to distance filter to "none" - which should be the minimum for best results. - self.locationManager.distanceFilter = kCLDistanceFilterNone; - // Set desired accuracy to Best. - self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; - } else { - __highAccuracyEnabled = NO; - // TODO: Set distance filter to 10 meters? and desired accuracy to nearest ten meters? arbitrary. - self.locationManager.distanceFilter = 10; - self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; - } -} - -- (void)_stopLocation -{ - if (__locationStarted) { - if (![self isLocationServicesEnabled]) { - return; - } - - [self.locationManager stopUpdatingLocation]; - __locationStarted = NO; - __highAccuracyEnabled = NO; - } -} - -- (void)locationManager:(CLLocationManager*)manager - didUpdateToLocation:(CLLocation*)newLocation - fromLocation:(CLLocation*)oldLocation -{ - CDVLocationData* cData = self.locationData; - - cData.locationInfo = newLocation; - if (self.locationData.locationCallbacks.count > 0) { - for (NSString* callbackId in self.locationData.locationCallbacks) { - [self returnLocationInfo:callbackId andKeepCallback:NO]; - } - - [self.locationData.locationCallbacks removeAllObjects]; - } - if (self.locationData.watchCallbacks.count > 0) { - for (NSString* timerId in self.locationData.watchCallbacks) { - [self returnLocationInfo:[self.locationData.watchCallbacks objectForKey:timerId] andKeepCallback:YES]; - } - } else { - // No callbacks waiting on us anymore, turn off listening. - [self _stopLocation]; - } -} - -- (void)getLocation:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - BOOL enableHighAccuracy = [[command.arguments objectAtIndex:0] boolValue]; - - if ([self isLocationServicesEnabled] == NO) { - NSMutableDictionary* posError = [NSMutableDictionary dictionaryWithCapacity:2]; - [posError setObject:[NSNumber numberWithInt:PERMISSIONDENIED] forKey:@"code"]; - [posError setObject:@"Location services are disabled." forKey:@"message"]; - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:posError]; - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; - } else { - if (!self.locationData) { - self.locationData = [[CDVLocationData alloc] init]; - } - CDVLocationData* lData = self.locationData; - if (!lData.locationCallbacks) { - lData.locationCallbacks = [NSMutableArray arrayWithCapacity:1]; - } - - if (!__locationStarted || (__highAccuracyEnabled != enableHighAccuracy)) { - // add the callbackId into the array so we can call back when get data - if (callbackId != nil) { - [lData.locationCallbacks addObject:callbackId]; - } - // Tell the location manager to start notifying us of heading updates - [self startLocation:enableHighAccuracy]; - } else { - [self returnLocationInfo:callbackId andKeepCallback:NO]; - } - } -} - -- (void)addWatch:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - NSString* timerId = [command.arguments objectAtIndex:0]; - BOOL enableHighAccuracy = [[command.arguments objectAtIndex:1] boolValue]; - - if (!self.locationData) { - self.locationData = [[CDVLocationData alloc] init]; - } - CDVLocationData* lData = self.locationData; - - if (!lData.watchCallbacks) { - lData.watchCallbacks = [NSMutableDictionary dictionaryWithCapacity:1]; - } - - // add the callbackId into the dictionary so we can call back whenever get data - [lData.watchCallbacks setObject:callbackId forKey:timerId]; - - if ([self isLocationServicesEnabled] == NO) { - NSMutableDictionary* posError = [NSMutableDictionary dictionaryWithCapacity:2]; - [posError setObject:[NSNumber numberWithInt:PERMISSIONDENIED] forKey:@"code"]; - [posError setObject:@"Location services are disabled." forKey:@"message"]; - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:posError]; - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; - } else { - if (!__locationStarted || (__highAccuracyEnabled != enableHighAccuracy)) { - // Tell the location manager to start notifying us of location updates - [self startLocation:enableHighAccuracy]; - } - } -} - -- (void)clearWatch:(CDVInvokedUrlCommand*)command -{ - NSString* timerId = [command.arguments objectAtIndex:0]; - - if (self.locationData && self.locationData.watchCallbacks && [self.locationData.watchCallbacks objectForKey:timerId]) { - [self.locationData.watchCallbacks removeObjectForKey:timerId]; - } -} - -- (void)stopLocation:(CDVInvokedUrlCommand*)command -{ - [self _stopLocation]; -} - -- (void)returnLocationInfo:(NSString*)callbackId andKeepCallback:(BOOL)keepCallback -{ - CDVPluginResult* result = nil; - CDVLocationData* lData = self.locationData; - - if (lData && !lData.locationInfo) { - // return error - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:POSITIONUNAVAILABLE]; - } else if (lData && lData.locationInfo) { - CLLocation* lInfo = lData.locationInfo; - NSMutableDictionary* returnInfo = [NSMutableDictionary dictionaryWithCapacity:8]; - NSNumber* timestamp = [NSNumber numberWithDouble:([lInfo.timestamp timeIntervalSince1970] * 1000)]; - [returnInfo setObject:timestamp forKey:@"timestamp"]; - [returnInfo setObject:[NSNumber numberWithDouble:lInfo.speed] forKey:@"velocity"]; - [returnInfo setObject:[NSNumber numberWithDouble:lInfo.verticalAccuracy] forKey:@"altitudeAccuracy"]; - [returnInfo setObject:[NSNumber numberWithDouble:lInfo.horizontalAccuracy] forKey:@"accuracy"]; - [returnInfo setObject:[NSNumber numberWithDouble:lInfo.course] forKey:@"heading"]; - [returnInfo setObject:[NSNumber numberWithDouble:lInfo.altitude] forKey:@"altitude"]; - [returnInfo setObject:[NSNumber numberWithDouble:lInfo.coordinate.latitude] forKey:@"latitude"]; - [returnInfo setObject:[NSNumber numberWithDouble:lInfo.coordinate.longitude] forKey:@"longitude"]; - - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:returnInfo]; - [result setKeepCallbackAsBool:keepCallback]; - } - if (result) { - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; - } -} - -- (void)returnLocationError:(NSUInteger)errorCode withMessage:(NSString*)message -{ - NSMutableDictionary* posError = [NSMutableDictionary dictionaryWithCapacity:2]; - - [posError setObject:[NSNumber numberWithInt:errorCode] forKey:@"code"]; - [posError setObject:message ? message:@"" forKey:@"message"]; - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:posError]; - - for (NSString* callbackId in self.locationData.locationCallbacks) { - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; - } - - [self.locationData.locationCallbacks removeAllObjects]; - - for (NSString* callbackId in self.locationData.watchCallbacks) { - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; - } -} - -// called to get the current heading -// Will call location manager to startUpdatingHeading if necessary - -- (void)getHeading:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - NSDictionary* options = [command.arguments objectAtIndex:0 withDefault:nil]; - NSNumber* filter = [options valueForKey:@"filter"]; - - if (filter) { - [self watchHeadingFilter:command]; - return; - } - if ([self hasHeadingSupport] == NO) { - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:20]; - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; - } else { - // heading retrieval does is not affected by disabling locationServices and authorization of app for location services - if (!self.headingData) { - self.headingData = [[CDVHeadingData alloc] init]; - } - CDVHeadingData* hData = self.headingData; - - if (!hData.headingCallbacks) { - hData.headingCallbacks = [NSMutableArray arrayWithCapacity:1]; - } - // add the callbackId into the array so we can call back when get data - [hData.headingCallbacks addObject:callbackId]; - - if ((hData.headingStatus != HEADINGRUNNING) && (hData.headingStatus != HEADINGERROR)) { - // Tell the location manager to start notifying us of heading updates - [self startHeadingWithFilter:0.2]; - } else { - [self returnHeadingInfo:callbackId keepCallback:NO]; - } - } -} - -// called to request heading updates when heading changes by a certain amount (filter) -- (void)watchHeadingFilter:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - NSDictionary* options = [command.arguments objectAtIndex:0 withDefault:nil]; - NSNumber* filter = [options valueForKey:@"filter"]; - CDVHeadingData* hData = self.headingData; - - if ([self hasHeadingSupport] == NO) { - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:20]; - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; - } else { - if (!hData) { - self.headingData = [[CDVHeadingData alloc] init]; - hData = self.headingData; - } - if (hData.headingStatus != HEADINGRUNNING) { - // Tell the location manager to start notifying us of heading updates - [self startHeadingWithFilter:[filter doubleValue]]; - } else { - // if already running check to see if due to existing watch filter - if (hData.headingFilter && ![hData.headingFilter isEqualToString:callbackId]) { - // new watch filter being specified - // send heading data one last time to clear old successCallback - [self returnHeadingInfo:hData.headingFilter keepCallback:NO]; - } - } - // save the new filter callback and update the headingFilter setting - hData.headingFilter = callbackId; - // check if need to stop and restart in order to change value??? - self.locationManager.headingFilter = [filter doubleValue]; - } -} - -- (void)returnHeadingInfo:(NSString*)callbackId keepCallback:(BOOL)bRetain -{ - CDVPluginResult* result = nil; - CDVHeadingData* hData = self.headingData; - - self.headingData.headingTimestamp = [NSDate date]; - - if (hData && (hData.headingStatus == HEADINGERROR)) { - // return error - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:0]; - } else if (hData && (hData.headingStatus == HEADINGRUNNING) && hData.headingInfo) { - // if there is heading info, return it - CLHeading* hInfo = hData.headingInfo; - NSMutableDictionary* returnInfo = [NSMutableDictionary dictionaryWithCapacity:4]; - NSNumber* timestamp = [NSNumber numberWithDouble:([hInfo.timestamp timeIntervalSince1970] * 1000)]; - [returnInfo setObject:timestamp forKey:@"timestamp"]; - [returnInfo setObject:[NSNumber numberWithDouble:hInfo.magneticHeading] forKey:@"magneticHeading"]; - id trueHeading = __locationStarted ? (id)[NSNumber numberWithDouble : hInfo.trueHeading] : (id)[NSNull null]; - [returnInfo setObject:trueHeading forKey:@"trueHeading"]; - [returnInfo setObject:[NSNumber numberWithDouble:hInfo.headingAccuracy] forKey:@"headingAccuracy"]; - - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:returnInfo]; - [result setKeepCallbackAsBool:bRetain]; - } - if (result) { - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; - } -} - -- (void)stopHeading:(CDVInvokedUrlCommand*)command -{ - // CDVHeadingData* hData = self.headingData; - if (self.headingData && (self.headingData.headingStatus != HEADINGSTOPPED)) { - if (self.headingData.headingFilter) { - // callback one last time to clear callback - [self returnHeadingInfo:self.headingData.headingFilter keepCallback:NO]; - self.headingData.headingFilter = nil; - } - [self.locationManager stopUpdatingHeading]; - NSLog(@"heading STOPPED"); - self.headingData = nil; - } -} - -// helper method to check the orientation and start updating headings -- (void)startHeadingWithFilter:(CLLocationDegrees)filter -{ - // FYI UIDeviceOrientation and CLDeviceOrientation enums are currently the same - self.locationManager.headingOrientation = (CLDeviceOrientation)self.viewController.interfaceOrientation; - self.locationManager.headingFilter = filter; - [self.locationManager startUpdatingHeading]; - self.headingData.headingStatus = HEADINGSTARTING; -} - -- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager*)manager -{ - return YES; -} - -- (void)locationManager:(CLLocationManager*)manager - didUpdateHeading:(CLHeading*)heading -{ - CDVHeadingData* hData = self.headingData; - - // normally we would clear the delegate to stop getting these notifications, but - // we are sharing a CLLocationManager to get location data as well, so we do a nil check here - // ideally heading and location should use their own CLLocationManager instances - if (hData == nil) { - return; - } - - // save the data for next call into getHeadingData - hData.headingInfo = heading; - BOOL bTimeout = NO; - if (!hData.headingFilter && hData.headingTimestamp) { - bTimeout = fabs([hData.headingTimestamp timeIntervalSinceNow]) > hData.timeout; - } - - if (hData.headingStatus == HEADINGSTARTING) { - hData.headingStatus = HEADINGRUNNING; // so returnHeading info will work - - // this is the first update - for (NSString* callbackId in hData.headingCallbacks) { - [self returnHeadingInfo:callbackId keepCallback:NO]; - } - - [hData.headingCallbacks removeAllObjects]; - } - if (hData.headingFilter) { - [self returnHeadingInfo:hData.headingFilter keepCallback:YES]; - } else if (bTimeout) { - [self stopHeading:nil]; - } - hData.headingStatus = HEADINGRUNNING; // to clear any error -} - -- (void)locationManager:(CLLocationManager*)manager didFailWithError:(NSError*)error -{ - NSLog(@"locationManager::didFailWithError %@", [error localizedFailureReason]); - - // Compass Error - if ([error code] == kCLErrorHeadingFailure) { - CDVHeadingData* hData = self.headingData; - if (hData) { - if (hData.headingStatus == HEADINGSTARTING) { - // heading error during startup - report error - for (NSString* callbackId in hData.headingCallbacks) { - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:0]; - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; - } - - [hData.headingCallbacks removeAllObjects]; - } // else for frequency watches next call to getCurrentHeading will report error - if (hData.headingFilter) { - CDVPluginResult* resultFilter = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:0]; - [self.commandDelegate sendPluginResult:resultFilter callbackId:hData.headingFilter]; - } - hData.headingStatus = HEADINGERROR; - } - } - // Location Error - else { - CDVLocationData* lData = self.locationData; - if (lData && __locationStarted) { - // TODO: probably have to once over the various error codes and return one of: - // PositionError.PERMISSION_DENIED = 1; - // PositionError.POSITION_UNAVAILABLE = 2; - // PositionError.TIMEOUT = 3; - NSUInteger positionError = POSITIONUNAVAILABLE; - if (error.code == kCLErrorDenied) { - positionError = PERMISSIONDENIED; - } - [self returnLocationError:positionError withMessage:[error localizedDescription]]; - } - } - - [self.locationManager stopUpdatingLocation]; - __locationStarted = NO; -} - -- (void)dealloc -{ - self.locationManager.delegate = nil; -} - -- (void)onReset -{ - [self _stopLocation]; - [self.locationManager stopUpdatingHeading]; - self.headingData = nil; -} - -@end - -#pragma mark - -#pragma mark CLLocation(JSONMethods) - -@implementation CLLocation (JSONMethods) - -- (NSString*)JSONRepresentation -{ - return [NSString stringWithFormat: - @"{ timestamp: %.00f, \ - coords: { latitude: %f, longitude: %f, altitude: %.02f, heading: %.02f, speed: %.02f, accuracy: %.02f, altitudeAccuracy: %.02f } \ - }", - [self.timestamp timeIntervalSince1970] * 1000.0, - self.coordinate.latitude, - self.coordinate.longitude, - self.altitude, - self.course, - self.speed, - self.horizontalAccuracy, - self.verticalAccuracy - ]; -} - -@end - -#pragma mark NSError(JSONMethods) - -@implementation NSError (JSONMethods) - -- (NSString*)JSONRepresentation -{ - return [NSString stringWithFormat: - @"{ code: %d, message: '%@'}", - self.code, - [self localizedDescription] - ]; -} - -@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/4c1a0e4d/CordovaLib/Classes/CDVNotification.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVNotification.h b/CordovaLib/Classes/CDVNotification.h deleted file mode 100644 index 5b5b89f..0000000 --- a/CordovaLib/Classes/CDVNotification.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -#import -#import -#import -#import "CDVPlugin.h" - -@interface CDVNotification : CDVPlugin {} - -- (void)alert:(CDVInvokedUrlCommand*)command; -- (void)confirm:(CDVInvokedUrlCommand*)command; -- (void)prompt:(CDVInvokedUrlCommand*)command; -- (void)vibrate:(CDVInvokedUrlCommand*)command; - -@end - -@interface CDVAlertView : UIAlertView {} -@property (nonatomic, copy) NSString* callbackId; - -@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/4c1a0e4d/CordovaLib/Classes/CDVNotification.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVNotification.m b/CordovaLib/Classes/CDVNotification.m deleted file mode 100644 index 464eb1f..0000000 --- a/CordovaLib/Classes/CDVNotification.m +++ /dev/null @@ -1,130 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -#import "CDVNotification.h" -#import "NSDictionary+Extensions.h" - -#define DIALOG_TYPE_ALERT @"alert" -#define DIALOG_TYPE_PROMPT @"prompt" - -@implementation CDVNotification - -/* - * showDialogWithMessage - Common method to instantiate the alert view for alert, confirm, and prompt notifications. - * Parameters: - * message The alert view message. - * title The alert view title. - * buttons The array of customized strings for the buttons. - * defaultText The input text for the textbox (if textbox exists). - * callbackId The commmand callback id. - * dialogType The type of alert view [alert | prompt]. - */ -- (void)showDialogWithMessage:(NSString*)message title:(NSString*)title buttons:(NSArray*)buttons defaultText:(NSString*)defaultText callbackId:(NSString*)callbackId dialogType:(NSString*)dialogType -{ - CDVAlertView* alertView = [[CDVAlertView alloc] - initWithTitle:title - message:message - delegate:self - cancelButtonTitle:nil - otherButtonTitles:nil]; - - alertView.callbackId = callbackId; - - int count = [buttons count]; - - for (int n = 0; n < count; n++) { - [alertView addButtonWithTitle:[buttons objectAtIndex:n]]; - } - - if ([dialogType isEqualToString:DIALOG_TYPE_PROMPT]) { - alertView.alertViewStyle = UIAlertViewStylePlainTextInput; - UITextField* textField = [alertView textFieldAtIndex:0]; - textField.text = defaultText; - } - - [alertView show]; -} - -- (void)alert:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - NSString* message = [command argumentAtIndex:0]; - NSString* title = [command argumentAtIndex:1]; - NSString* buttons = [command argumentAtIndex:2]; - - [self showDialogWithMessage:message title:title buttons:@[buttons] defaultText:nil callbackId:callbackId dialogType:DIALOG_TYPE_ALERT]; -} - -- (void)confirm:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - NSString* message = [command argumentAtIndex:0]; - NSString* title = [command argumentAtIndex:1]; - NSArray* buttons = [command argumentAtIndex:2]; - - [self showDialogWithMessage:message title:title buttons:buttons defaultText:nil callbackId:callbackId dialogType:DIALOG_TYPE_ALERT]; -} - -- (void)prompt:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - NSString* message = [command argumentAtIndex:0]; - NSString* title = [command argumentAtIndex:1]; - NSArray* buttons = [command argumentAtIndex:2]; - NSString* defaultText = [command argumentAtIndex:3]; - - [self showDialogWithMessage:message title:title buttons:buttons defaultText:defaultText callbackId:callbackId dialogType:DIALOG_TYPE_PROMPT]; -} - -/** - * Callback invoked when an alert dialog's buttons are clicked. - */ -- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - CDVAlertView* cdvAlertView = (CDVAlertView*)alertView; - CDVPluginResult* result; - - // Determine what gets returned to JS based on the alert view type. - if (alertView.alertViewStyle == UIAlertViewStyleDefault) { - // For alert and confirm, return button index as int back to JS. - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:buttonIndex + 1]; - } else { - // For prompt, return button index and input text back to JS. - NSString* value0 = [[alertView textFieldAtIndex:0] text]; - NSDictionary* info = @{ - @"buttonIndex":@(buttonIndex + 1), - @"input1":(value0 ? value0 : [NSNull null]) - }; - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:info]; - } - [self.commandDelegate sendPluginResult:result callbackId:cdvAlertView.callbackId]; -} - -- (void)vibrate:(CDVInvokedUrlCommand*)command -{ - AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); -} - -@end - -@implementation CDVAlertView - -@synthesize callbackId; - -@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/4c1a0e4d/CordovaLib/Classes/CDVSplashScreen.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVSplashScreen.h b/CordovaLib/Classes/CDVSplashScreen.h deleted file mode 100644 index 704ab43..0000000 --- a/CordovaLib/Classes/CDVSplashScreen.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -#import -#import "CDVPlugin.h" - -@interface CDVSplashScreen : CDVPlugin { - UIActivityIndicatorView* _activityView; - UIImageView* _imageView; - NSString* _curImageName; - BOOL _visible; -} - -- (void)show:(CDVInvokedUrlCommand*)command; -- (void)hide:(CDVInvokedUrlCommand*)command; - -@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/4c1a0e4d/CordovaLib/Classes/CDVSplashScreen.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVSplashScreen.m b/CordovaLib/Classes/CDVSplashScreen.m deleted file mode 100644 index fdb79fa..0000000 --- a/CordovaLib/Classes/CDVSplashScreen.m +++ /dev/null @@ -1,230 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -#import "CDVSplashScreen.h" - -#define kSplashScreenDurationDefault 0.25f - -@implementation CDVSplashScreen - -- (void)pluginInitialize -{ - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pageDidLoad) name:CDVPageDidLoadNotification object:self.webView]; - - [self setVisible:YES]; -} - -- (void)show:(CDVInvokedUrlCommand*)command -{ - [self setVisible:YES]; -} - -- (void)hide:(CDVInvokedUrlCommand*)command -{ - [self setVisible:NO]; -} - -- (void)pageDidLoad -{ - id autoHideSplashScreenValue = [self.commandDelegate.settings objectForKey:@"AutoHideSplashScreen"]; - - // if value is missing, default to yes - if ((autoHideSplashScreenValue == nil) || [autoHideSplashScreenValue boolValue]) { - [self setVisible:NO]; - } -} - -- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context -{ - [self updateImage]; -} - -- (void)createViews -{ - /* - * 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.commandDelegate.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; - } - - UIView* parentView = self.viewController.view; - parentView.userInteractionEnabled = NO; // disable user interaction while splashscreen is shown - _activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:topActivityIndicatorStyle]; - _activityView.center = CGPointMake(parentView.bounds.size.width / 2, parentView.bounds.size.height / 2); - _activityView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin - | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin; - [_activityView startAnimating]; - - // Set the frame & image later. - _imageView = [[UIImageView alloc] init]; - [parentView addSubview:_imageView]; - - id showSplashScreenSpinnerValue = [self.commandDelegate.settings objectForKey:@"ShowSplashScreenSpinner"]; - // backwards compatibility - if key is missing, default to true - if ((showSplashScreenSpinnerValue == nil) || [showSplashScreenSpinnerValue boolValue]) { - [parentView addSubview:_activityView]; - } - - // Frame is required when launching in portrait mode. - // Bounds for landscape since it captures the rotation. - [parentView addObserver:self forKeyPath:@"frame" options:0 context:nil]; - [parentView addObserver:self forKeyPath:@"bounds" options:0 context:nil]; - - [self updateImage]; -} - -- (void)destroyViews -{ - [_imageView removeFromSuperview]; - [_activityView removeFromSuperview]; - _imageView = nil; - _activityView = nil; - _curImageName = nil; - - self.viewController.view.userInteractionEnabled = YES; // re-enable user interaction upon completion - [self.viewController.view removeObserver:self forKeyPath:@"frame"]; - [self.viewController.view removeObserver:self forKeyPath:@"bounds"]; -} - -// Sets the view's frame and image. -- (void)updateImage -{ - UIInterfaceOrientation orientation = self.viewController.interfaceOrientation; - - // Use UILaunchImageFile if specified in plist. Otherwise, use Default. - NSString* imageName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchImageFile"]; - - if (imageName) { - imageName = [imageName stringByDeletingPathExtension]; - } else { - imageName = @"Default"; - } - - if (CDV_IsIPhone5()) { - imageName = [imageName stringByAppendingString:@"-568h"]; - } else if (CDV_IsIPad()) { - switch (orientation) { - case UIInterfaceOrientationLandscapeLeft: - case UIInterfaceOrientationLandscapeRight: - imageName = [imageName stringByAppendingString:@"-Landscape"]; - break; - - case UIInterfaceOrientationPortrait: - case UIInterfaceOrientationPortraitUpsideDown: - default: - imageName = [imageName stringByAppendingString:@"-Portrait"]; - break; - } - } - - if (![imageName isEqualToString:_curImageName]) { - UIImage* img = [UIImage imageNamed:imageName]; - _imageView.image = img; - _curImageName = imageName; - } - - // Check that splash screen's image exists before updating bounds - if (_imageView.image) { - [self updateBounds]; - } else { - NSLog(@"WARNING: The splashscreen image named %@ was not found", imageName); - } -} - -- (void)updateBounds -{ - UIImage* img = _imageView.image; - CGRect imgBounds = CGRectMake(0, 0, img.size.width, img.size.height); - - CGSize screenSize = [self.viewController.view convertRect:[UIScreen mainScreen].bounds fromView:nil].size; - - // There's a special case when the image is the size of the screen. - if (CGSizeEqualToSize(screenSize, imgBounds.size)) { - CGRect statusFrame = [self.viewController.view convertRect:[UIApplication sharedApplication].statusBarFrame fromView:nil]; - imgBounds.origin.y -= statusFrame.size.height; - } else { - CGRect viewBounds = self.viewController.view.bounds; - CGFloat imgAspect = imgBounds.size.width / imgBounds.size.height; - CGFloat viewAspect = viewBounds.size.width / viewBounds.size.height; - // This matches the behaviour of the native splash screen. - CGFloat ratio; - if (viewAspect > imgAspect) { - ratio = viewBounds.size.width / imgBounds.size.width; - } else { - ratio = viewBounds.size.height / imgBounds.size.height; - } - imgBounds.size.height *= ratio; - imgBounds.size.width *= ratio; - } - - _imageView.frame = imgBounds; -} - -- (void)setVisible:(BOOL)visible -{ - if (visible == _visible) { - return; - } - _visible = visible; - - id fadeSplashScreenValue = [self.commandDelegate.settings objectForKey:@"FadeSplashScreen"]; - id fadeSplashScreenDuration = [self.commandDelegate.settings objectForKey:@"FadeSplashScreenDuration"]; - - float fadeDuration = fadeSplashScreenDuration == nil ? kSplashScreenDurationDefault : [fadeSplashScreenDuration floatValue]; - - if ((fadeSplashScreenValue == nil) || ![fadeSplashScreenValue boolValue]) { - fadeDuration = 0; - } - - // Never animate the showing of the splash screen. - if (visible) { - if (_imageView == nil) { - [self createViews]; - } - } else if (fadeDuration == 0) { - [self destroyViews]; - } else { - [UIView transitionWithView:self.viewController.view - duration:fadeDuration - options:UIViewAnimationOptionTransitionNone - animations:^(void) { - [_imageView setAlpha:0]; - [_activityView setAlpha:0]; - } - - completion:^(BOOL finished) { - [self destroyViews]; - }]; - } -} - -@end