From 73968ba1b3c3b5efeb92f70969e40d143eebf3d8 Mon Sep 17 00:00:00 2001 From: ARC Date: Wed, 13 May 2015 14:58:25 -0400 Subject: Added plugin directory as well to make sure you have all you need to compile (hopefully) --- .../src/android/StatusBar.java | 101 +++++ .../src/ios/CDVStatusBar.h | 49 +++ .../src/ios/CDVStatusBar.m | 458 +++++++++++++++++++++ .../src/windows/StatusBarProxy.js | 100 +++++ .../src/wp/StatusBar.cs | 141 +++++++ 5 files changed, 849 insertions(+) create mode 100644 plugins/org.apache.cordova.statusbar/src/android/StatusBar.java create mode 100644 plugins/org.apache.cordova.statusbar/src/ios/CDVStatusBar.h create mode 100644 plugins/org.apache.cordova.statusbar/src/ios/CDVStatusBar.m create mode 100644 plugins/org.apache.cordova.statusbar/src/windows/StatusBarProxy.js create mode 100644 plugins/org.apache.cordova.statusbar/src/wp/StatusBar.cs (limited to 'plugins/org.apache.cordova.statusbar/src') diff --git a/plugins/org.apache.cordova.statusbar/src/android/StatusBar.java b/plugins/org.apache.cordova.statusbar/src/android/StatusBar.java new file mode 100644 index 00000000..e4f748f9 --- /dev/null +++ b/plugins/org.apache.cordova.statusbar/src/android/StatusBar.java @@ -0,0 +1,101 @@ +/* + * 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. + * +*/ +package org.apache.cordova.statusbar; + +import android.app.Activity; +import android.util.Log; +import android.view.Window; +import android.view.WindowManager; + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaArgs; +import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.CordovaWebView; +import org.apache.cordova.PluginResult; +import org.json.JSONException; + +public class StatusBar extends CordovaPlugin { + private static final String TAG = "StatusBar"; + + /** + * Sets the context of the Command. This can then be used to do things like + * get file paths associated with the Activity. + * + * @param cordova The context of the main Activity. + * @param webView The CordovaWebView Cordova is running in. + */ + @Override + public void initialize(final CordovaInterface cordova, CordovaWebView webView) { + Log.v(TAG, "StatusBar: initialization"); + super.initialize(cordova, webView); + + this.cordova.getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + // Clear flag FLAG_FORCE_NOT_FULLSCREEN which is set initially + // by the Cordova. + Window window = cordova.getActivity().getWindow(); + window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + } + }); + } + + /** + * Executes the request and returns PluginResult. + * + * @param action The action to execute. + * @param args JSONArry of arguments for the plugin. + * @param callbackContext The callback id used when calling back into JavaScript. + * @return True if the action was valid, false otherwise. + */ + @Override + public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException { + Log.v(TAG, "Executing action: " + action); + final Activity activity = this.cordova.getActivity(); + final Window window = activity.getWindow(); + if ("_ready".equals(action)) { + boolean statusBarVisible = (window.getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0; + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, statusBarVisible)); + } + + if ("show".equals(action)) { + this.cordova.getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + }); + return true; + } + + if ("hide".equals(action)) { + this.cordova.getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + }); + return true; + } + + return false; + } +} diff --git a/plugins/org.apache.cordova.statusbar/src/ios/CDVStatusBar.h b/plugins/org.apache.cordova.statusbar/src/ios/CDVStatusBar.h new file mode 100644 index 00000000..84f37fa7 --- /dev/null +++ b/plugins/org.apache.cordova.statusbar/src/ios/CDVStatusBar.h @@ -0,0 +1,49 @@ +/* + 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 + +@interface CDVStatusBar : CDVPlugin { + @protected + BOOL _statusBarOverlaysWebView; + UIView* _statusBarBackgroundView; + BOOL _uiviewControllerBasedStatusBarAppearance; + UIColor* _statusBarBackgroundColor; + NSString* _eventsCallbackId; +} + +@property (atomic, assign) BOOL statusBarOverlaysWebView; + +- (void) overlaysWebView:(CDVInvokedUrlCommand*)command; + +- (void) styleDefault:(CDVInvokedUrlCommand*)command; +- (void) styleLightContent:(CDVInvokedUrlCommand*)command; +- (void) styleBlackTranslucent:(CDVInvokedUrlCommand*)command; +- (void) styleBlackOpaque:(CDVInvokedUrlCommand*)command; + +- (void) backgroundColorByName:(CDVInvokedUrlCommand*)command; +- (void) backgroundColorByHexString:(CDVInvokedUrlCommand*)command; + +- (void) hide:(CDVInvokedUrlCommand*)command; +- (void) show:(CDVInvokedUrlCommand*)command; + +- (void) _ready:(CDVInvokedUrlCommand*)command; + +@end diff --git a/plugins/org.apache.cordova.statusbar/src/ios/CDVStatusBar.m b/plugins/org.apache.cordova.statusbar/src/ios/CDVStatusBar.m new file mode 100644 index 00000000..d2bd708d --- /dev/null +++ b/plugins/org.apache.cordova.statusbar/src/ios/CDVStatusBar.m @@ -0,0 +1,458 @@ +/* + 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. + */ + +/* + NOTE: plugman/cordova cli should have already installed this, + but you need the value UIViewControllerBasedStatusBarAppearance + in your Info.plist as well to set the styles in iOS 7 + */ + +#import "CDVStatusBar.h" +#import +#import + +static const void *kHideStatusBar = &kHideStatusBar; +static const void *kStatusBarStyle = &kStatusBarStyle; + +@interface CDVViewController (StatusBar) + +@property (nonatomic, retain) id sb_hideStatusBar; +@property (nonatomic, retain) id sb_statusBarStyle; + +@end + +@implementation CDVViewController (StatusBar) + +@dynamic sb_hideStatusBar; +@dynamic sb_statusBarStyle; + +- (id)sb_hideStatusBar { + return objc_getAssociatedObject(self, kHideStatusBar); +} + +- (void)setSb_hideStatusBar:(id)newHideStatusBar { + objc_setAssociatedObject(self, kHideStatusBar, newHideStatusBar, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (id)sb_statusBarStyle { + return objc_getAssociatedObject(self, kStatusBarStyle); +} + +- (void)setSb_statusBarStyle:(id)newStatusBarStyle { + objc_setAssociatedObject(self, kStatusBarStyle, newStatusBarStyle, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (BOOL) prefersStatusBarHidden { + return [self.sb_hideStatusBar boolValue]; +} + +- (UIStatusBarStyle)preferredStatusBarStyle +{ + return (UIStatusBarStyle)[self.sb_statusBarStyle intValue]; +} + +@end + + +@interface CDVStatusBar () +- (void)fireTappedEvent; +- (void)updateIsVisible:(BOOL)visible; +@end + +@implementation CDVStatusBar + +- (id)settingForKey:(NSString*)key +{ + return [self.commandDelegate.settings objectForKey:[key lowercaseString]]; +} + +- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context +{ + if ([keyPath isEqual:@"statusBarHidden"]) { + NSNumber* newValue = [change objectForKey:NSKeyValueChangeNewKey]; + [self updateIsVisible:![newValue boolValue]]; + } +} + +- (void)pluginInitialize +{ + BOOL isiOS7 = (IsAtLeastiOSVersion(@"7.0")); + + // init + NSNumber* uiviewControllerBasedStatusBarAppearance = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"]; + _uiviewControllerBasedStatusBarAppearance = (uiviewControllerBasedStatusBarAppearance == nil || [uiviewControllerBasedStatusBarAppearance boolValue]) && isiOS7; + + // observe the statusBarHidden property + [[UIApplication sharedApplication] addObserver:self forKeyPath:@"statusBarHidden" options:NSKeyValueObservingOptionNew context:NULL]; + + _statusBarOverlaysWebView = YES; // default + + [self initializeStatusBarBackgroundView]; + + self.viewController.view.autoresizesSubviews = YES; + + NSString* setting; + + setting = @"StatusBarOverlaysWebView"; + if ([self settingForKey:setting]) { + self.statusBarOverlaysWebView = [(NSNumber*)[self settingForKey:setting] boolValue]; + } + + setting = @"StatusBarBackgroundColor"; + if ([self settingForKey:setting]) { + [self _backgroundColorByHexString:[self settingForKey:setting]]; + } + + setting = @"StatusBarStyle"; + if ([self settingForKey:setting]) { + [self setStatusBarStyle:[self settingForKey:setting]]; + } + + // blank scroll view to intercept status bar taps + self.webView.scrollView.scrollsToTop = NO; + UIScrollView *fakeScrollView = [[UIScrollView alloc] initWithFrame:UIScreen.mainScreen.bounds]; + fakeScrollView.delegate = self; + fakeScrollView.scrollsToTop = YES; + [self.viewController.view addSubview:fakeScrollView]; // Add scrollview to the view heirarchy so that it will begin accepting status bar taps + [self.viewController.view sendSubviewToBack:fakeScrollView]; // Send it to the very back of the view heirarchy + fakeScrollView.contentSize = CGSizeMake(UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height * 2.0f); // Make the scroll view longer than the screen itself + fakeScrollView.contentOffset = CGPointMake(0.0f, UIScreen.mainScreen.bounds.size.height); // Scroll down so a tap will take scroll view back to the top +} + +- (void)onReset { + _eventsCallbackId = nil; +} + +- (void)fireTappedEvent { + if (_eventsCallbackId == nil) { + return; + } + NSDictionary* payload = @{@"type": @"tap"}; + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:payload]; + [result setKeepCallbackAsBool:YES]; + [self.commandDelegate sendPluginResult:result callbackId:_eventsCallbackId]; +} + +- (void)updateIsVisible:(BOOL)visible { + if (_eventsCallbackId == nil) { + return; + } + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:visible]; + [result setKeepCallbackAsBool:YES]; + [self.commandDelegate sendPluginResult:result callbackId:_eventsCallbackId]; +} + + +- (void) _ready:(CDVInvokedUrlCommand*)command +{ + _eventsCallbackId = command.callbackId; + [self updateIsVisible:![UIApplication sharedApplication].statusBarHidden]; +} + +- (void) initializeStatusBarBackgroundView +{ + CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; + statusBarFrame = [self invertFrameIfNeeded:statusBarFrame orientation:self.viewController.interfaceOrientation]; + + _statusBarBackgroundView = [[UIView alloc] initWithFrame:statusBarFrame]; + _statusBarBackgroundView.backgroundColor = _statusBarBackgroundColor; + _statusBarBackgroundView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin); + _statusBarBackgroundView.autoresizesSubviews = YES; +} + +- (CGRect) invertFrameIfNeeded:(CGRect)rect orientation:(UIInterfaceOrientation)orientation { + // landscape is where (width > height). On iOS < 8, we need to invert since frames are + // always in Portrait context + if (UIDeviceOrientationIsLandscape(orientation) && (rect.size.width < rect.size.height) ) { + CGFloat temp = rect.size.width; + rect.size.width = rect.size.height; + rect.size.height = temp; + rect.origin = CGPointZero; + } + + return rect; +} + +- (void) setStatusBarOverlaysWebView:(BOOL)statusBarOverlaysWebView +{ + // we only care about the latest iOS version or a change in setting + if (!IsAtLeastiOSVersion(@"7.0") || statusBarOverlaysWebView == _statusBarOverlaysWebView) { + return; + } + + CGRect bounds = [[UIScreen mainScreen] bounds]; + + if (statusBarOverlaysWebView) { + + [_statusBarBackgroundView removeFromSuperview]; + if (UIDeviceOrientationIsLandscape(self.viewController.interfaceOrientation)) { + self.webView.frame = CGRectMake(0, 0, bounds.size.height, bounds.size.width); + } else { + self.webView.frame = bounds; + } + + } else { + + CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; + statusBarFrame = [self invertFrameIfNeeded:statusBarFrame orientation:self.viewController.interfaceOrientation]; + + [self initializeStatusBarBackgroundView]; + + CGRect frame = self.webView.frame; + frame.origin.y = statusBarFrame.size.height; + frame.size.height -= statusBarFrame.size.height; + + self.webView.frame = frame; + [self.webView.superview addSubview:_statusBarBackgroundView]; + } + + _statusBarOverlaysWebView = statusBarOverlaysWebView; +} + +- (BOOL) statusBarOverlaysWebView +{ + return _statusBarOverlaysWebView; +} + +- (void) overlaysWebView:(CDVInvokedUrlCommand*)command +{ + id value = [command argumentAtIndex:0]; + if (!([value isKindOfClass:[NSNumber class]])) { + value = [NSNumber numberWithBool:YES]; + } + + self.statusBarOverlaysWebView = [value boolValue]; +} + +- (void) refreshStatusBarAppearance +{ + SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate"); + if ([self.viewController respondsToSelector:sel]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [self.viewController performSelector:sel withObject:nil]; +#pragma clang diagnostic pop + } +} + +- (void) setStyleForStatusBar:(UIStatusBarStyle)style +{ + if (_uiviewControllerBasedStatusBarAppearance) { + CDVViewController* vc = (CDVViewController*)self.viewController; + vc.sb_statusBarStyle = [NSNumber numberWithInt:style]; + [self refreshStatusBarAppearance]; + + } else { + [[UIApplication sharedApplication] setStatusBarStyle:style]; + } +} + +- (void) setStatusBarStyle:(NSString*)statusBarStyle +{ + // default, lightContent, blackTranslucent, blackOpaque + NSString* lcStatusBarStyle = [statusBarStyle lowercaseString]; + + if ([lcStatusBarStyle isEqualToString:@"default"]) { + [self styleDefault:nil]; + } else if ([lcStatusBarStyle isEqualToString:@"lightcontent"]) { + [self styleLightContent:nil]; + } else if ([lcStatusBarStyle isEqualToString:@"blacktranslucent"]) { + [self styleBlackTranslucent:nil]; + } else if ([lcStatusBarStyle isEqualToString:@"blackopaque"]) { + [self styleBlackOpaque:nil]; + } +} + +- (void) styleDefault:(CDVInvokedUrlCommand*)command +{ + [self setStyleForStatusBar:UIStatusBarStyleDefault]; +} + +- (void) styleLightContent:(CDVInvokedUrlCommand*)command +{ + [self setStyleForStatusBar:UIStatusBarStyleLightContent]; +} + +- (void) styleBlackTranslucent:(CDVInvokedUrlCommand*)command +{ + [self setStyleForStatusBar:UIStatusBarStyleBlackTranslucent]; +} + +- (void) styleBlackOpaque:(CDVInvokedUrlCommand*)command +{ + [self setStyleForStatusBar:UIStatusBarStyleBlackOpaque]; +} + +- (void) backgroundColorByName:(CDVInvokedUrlCommand*)command +{ + id value = [command argumentAtIndex:0]; + if (!([value isKindOfClass:[NSString class]])) { + value = @"black"; + } + + SEL selector = NSSelectorFromString([value stringByAppendingString:@"Color"]); + if ([UIColor respondsToSelector:selector]) { + _statusBarBackgroundView.backgroundColor = [UIColor performSelector:selector]; + } +} + +- (void) _backgroundColorByHexString:(NSString*)hexString +{ + unsigned int rgbValue = 0; + NSScanner* scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:1]; + [scanner scanHexInt:&rgbValue]; + + _statusBarBackgroundColor = [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0]; + _statusBarBackgroundView.backgroundColor = _statusBarBackgroundColor; +} + +- (void) backgroundColorByHexString:(CDVInvokedUrlCommand*)command +{ + NSString* value = [command argumentAtIndex:0]; + if (!([value isKindOfClass:[NSString class]])) { + value = @"#000000"; + } + + if (![value hasPrefix:@"#"] || [value length] < 7) { + return; + } + + [self _backgroundColorByHexString:value]; +} + +- (void) hideStatusBar +{ + if (_uiviewControllerBasedStatusBarAppearance) { + CDVViewController* vc = (CDVViewController*)self.viewController; + vc.sb_hideStatusBar = [NSNumber numberWithBool:YES]; + [self refreshStatusBarAppearance]; + + } else { + UIApplication* app = [UIApplication sharedApplication]; + [app setStatusBarHidden:YES]; + } +} + +- (void) hide:(CDVInvokedUrlCommand*)command +{ + UIApplication* app = [UIApplication sharedApplication]; + + if (!app.isStatusBarHidden) + { + self.viewController.wantsFullScreenLayout = YES; + CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; + + [self hideStatusBar]; + + if (IsAtLeastiOSVersion(@"7.0")) { + [_statusBarBackgroundView removeFromSuperview]; + } + + if (!_statusBarOverlaysWebView) { + + CGRect frame = self.webView.frame; + frame.origin.y = 0; + if (!self.statusBarOverlaysWebView) { + if (UIDeviceOrientationIsLandscape(self.viewController.interfaceOrientation)) { + frame.size.height += statusBarFrame.size.width; + } else { + frame.size.height += statusBarFrame.size.height; + } + } + + self.webView.frame = frame; + } + + _statusBarBackgroundView.hidden = YES; + } +} + +- (void) showStatusBar +{ + if (_uiviewControllerBasedStatusBarAppearance) { + CDVViewController* vc = (CDVViewController*)self.viewController; + vc.sb_hideStatusBar = [NSNumber numberWithBool:NO]; + [self refreshStatusBarAppearance]; + + } else { + UIApplication* app = [UIApplication sharedApplication]; + [app setStatusBarHidden:NO]; + } +} + +- (void) show:(CDVInvokedUrlCommand*)command +{ + UIApplication* app = [UIApplication sharedApplication]; + + if (app.isStatusBarHidden) + { + BOOL isIOS7 = (IsAtLeastiOSVersion(@"7.0")); + self.viewController.wantsFullScreenLayout = isIOS7; + + [self showStatusBar]; + + if (isIOS7) { + CGRect frame = self.webView.frame; + self.viewController.view.frame = [[UIScreen mainScreen] bounds]; + + CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; + statusBarFrame = [self invertFrameIfNeeded:statusBarFrame orientation:self.viewController.interfaceOrientation]; + + if (!self.statusBarOverlaysWebView) { + + // there is a possibility that when the statusbar was hidden, it was in a different orientation + // from the current one. Therefore we need to expand the statusBarBackgroundView as well to the + // statusBar's current size + CGRect sbBgFrame = _statusBarBackgroundView.frame; + frame.origin.y = statusBarFrame.size.height; + frame.size.height -= statusBarFrame.size.height; + sbBgFrame.size = statusBarFrame.size; + + _statusBarBackgroundView.frame = sbBgFrame; + [self.webView.superview addSubview:_statusBarBackgroundView]; + } + + self.webView.frame = frame; + + } else { + + CGRect bounds = [[UIScreen mainScreen] applicationFrame]; + self.viewController.view.frame = bounds; + } + + _statusBarBackgroundView.hidden = NO; + } +} + +- (void) dealloc +{ + [[UIApplication sharedApplication] removeObserver:self forKeyPath:@"statusBarHidden"]; +} + + +#pragma mark - UIScrollViewDelegate + +- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView +{ + [self fireTappedEvent]; + return NO; +} + +@end diff --git a/plugins/org.apache.cordova.statusbar/src/windows/StatusBarProxy.js b/plugins/org.apache.cordova.statusbar/src/windows/StatusBarProxy.js new file mode 100644 index 00000000..57700999 --- /dev/null +++ b/plugins/org.apache.cordova.statusbar/src/windows/StatusBarProxy.js @@ -0,0 +1,100 @@ +/* + * + * 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. + * + */ + + var isSupported = true; // we assume + +function getViewStatusBar() { + if(isSupported) { + var ViewMan = Windows.UI.ViewManagement; // quick alias to save char + if( ViewMan.StatusBar && + ViewMan.StatusBar.getForCurrentView ) { + return ViewMan.StatusBar.getForCurrentView(); + } + else { + isSupported = false; // so we won't check again + } + } + return null; +} + +function hexToRgb(hex) { + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, function (m, r, g, b) { + return r + r + g + g + b + b; + }); + + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +} + +module.exports = { + _ready: function(win, fail) { + win(statusBar.occludedRect.height !== 0); + }, + + overlaysWebView: function () { + // not supported + }, + + styleDefault: function () { + // dark text ( to be used on a light background ) + getViewStatusBar().foregroundColor = { a: 0, r: 0, g: 0, b: 0 }; + }, + + styleLightContent: function () { + // light text ( to be used on a dark background ) + getViewStatusBar().foregroundColor = { a: 0, r: 255, g: 255, b: 255 }; + }, + + styleBlackTranslucent: function () { + // #88000000 ? Apple says to use lightContent instead + return this.styleLightContent(); + }, + + styleBlackOpaque: function () { + // #FF000000 ? Apple says to use lightContent instead + return this.styleLightContent(); + }, + + backgroundColorByHexString: function (win, fail, args) { + var rgb = hexToRgb(args[0]); + var statusBar = getViewStatusBar(); + if(statusBar) { + statusBar.backgroundColor = { a: 0, r: rgb.r, g: rgb.g, b: rgb.b }; + statusBar.backgroundOpacity = 1; + } + }, + + show: function (win, fail) { + getViewStatusBar().showAsync().done(win, fail); + }, + + hide: function (win, fail) { + getViewStatusBar().hideAsync().done(win, fail); + } +}; + +require("cordova/exec/proxy").add("StatusBar", module.exports); diff --git a/plugins/org.apache.cordova.statusbar/src/wp/StatusBar.cs b/plugins/org.apache.cordova.statusbar/src/wp/StatusBar.cs new file mode 100644 index 00000000..ec83ca8e --- /dev/null +++ b/plugins/org.apache.cordova.statusbar/src/wp/StatusBar.cs @@ -0,0 +1,141 @@ +/* + Licensed 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. +*/ + + +using Microsoft.Phone.Shell; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Threading; +using System.Windows; +using System.Windows.Media; +using System.Windows.Threading; + + +/* + * http://www.idev101.com/code/User_Interface/StatusBar.html + * https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/Bars.html + * https://developer.apple.com/library/ios/documentation/uikit/reference/UIApplication_Class/Reference/Reference.html#//apple_ref/c/econst/UIStatusBarStyleDefault + * */ + + +namespace WPCordovaClassLib.Cordova.Commands +{ + public class StatusBar : BaseCommand + { + + // returns an argb value, if the hex is only rgb, it will be full opacity + protected Color ColorFromHex(string hexString) + { + string cleanHex = hexString.Replace("#", "").Replace("0x", ""); + // turn #FFF into #FFFFFF + if (cleanHex.Length == 3) + { + cleanHex = "" + cleanHex[0] + cleanHex[0] + cleanHex[1] + cleanHex[1] + cleanHex[2] + cleanHex[2]; + } + // add an alpha 100% if it is missing + if (cleanHex.Length == 6) + { + cleanHex = "FF" + cleanHex; + } + int argb = Int32.Parse(cleanHex, NumberStyles.HexNumber); + Color clr = Color.FromArgb((byte)((argb & 0xff000000) >> 0x18), + (byte)((argb & 0xff0000) >> 0x10), + (byte)((argb & 0xff00) >> 8), + (byte)(argb & 0xff)); + return clr; + } + + public void _ready(string options) + { + Deployment.Current.Dispatcher.BeginInvoke(() => + { + bool isVis = SystemTray.IsVisible; + // TODO: pass this to JS + //Debug.WriteLine("Result::" + res); + DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isVis)); + }); + } + + public void overlaysWebView(string options) + { //exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]); + // string arg = JSON.JsonHelper.Deserialize(options)[0]; + } + + public void styleDefault(string options) + { //exec(null, null, "StatusBar", "styleDefault", []); + Deployment.Current.Dispatcher.BeginInvoke(() => + { + SystemTray.ForegroundColor = Colors.Black; + }); + } + + public void styleLightContent(string options) + { //exec(null, null, "StatusBar", "styleLightContent", []); + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + SystemTray.ForegroundColor = Colors.White; + }); + } + + public void styleBlackTranslucent(string options) + { //exec(null, null, "StatusBar", "styleBlackTranslucent", []); + styleLightContent(options); + } + + public void styleBlackOpaque(string options) + { //exec(null, null, "StatusBar", "styleBlackOpaque", []); + styleLightContent(options); + } + + public void backgroundColorByName(string options) + { //exec(null, null, "StatusBar", "backgroundColorByName", [colorname]); + // this should NOT be called, js should now be using/converting color names to hex + } + + public void backgroundColorByHexString(string options) + { //exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]); + string argb = JSON.JsonHelper.Deserialize(options)[0]; + + Color clr = ColorFromHex(argb); + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + SystemTray.Opacity = clr.A / 255.0d; + SystemTray.BackgroundColor = clr; + + }); + } + + public void hide(string options) + { //exec(null, null, "StatusBar", "hide", []); + Deployment.Current.Dispatcher.BeginInvoke(() => + { + SystemTray.IsVisible = false; + }); + + } + + public void show(string options) + { //exec(null, null, "StatusBar", "show", []); + Deployment.Current.Dispatcher.BeginInvoke(() => + { + SystemTray.IsVisible = true; + }); + } + } +} \ No newline at end of file -- cgit v1.2.3