@nativescript-community/systemui
Version:
Provides API for changing the styles of SystemUI (StatusBar, NavigationBar...) on iOS.
402 lines • 15 kB
JavaScript
import { Application, Frame, View } from '@nativescript/core';
import { statusBarStyleProperty } from '@nativescript/core/ui/page';
import { SDK_VERSION } from '@nativescript/core/utils';
import { applyMixins, cssProperty, cssStatusBarColorProperty, cssWindowBgColorProperty, findTopView, keepScreenAwakeProperty, screenBrightnessProperty, screenOrientationProperty, statusBarHiddenProperty } from './index-common';
const STATUSBAR_VIEW_TAG = 3245411;
/**
* find the exact object by which the property is owned in the prototype chain
* @param object
* @param property
* @returns {*}
*/
function findPrototypeForProperty(object, property) {
while (false === object.hasOwnProperty(property)) {
object = Object.getPrototypeOf(object);
}
return object;
}
function setShouldAutoRotate(page, value) {
const prototypeForNavController = findPrototypeForProperty(page.viewController, 'shouldAutorotate');
Object.defineProperty(prototypeForNavController, 'shouldAutorotate', {
configurable: true,
enumerable: false,
get() {
return value;
}
});
}
function setSupportedInterfaceOrientations(page, value) {
const prototypeForNavController = findPrototypeForProperty(page.viewController, 'supportedInterfaceOrientations');
Object.defineProperty(prototypeForNavController, 'supportedInterfaceOrientations', {
configurable: true,
enumerable: false,
get() {
return value;
}
});
}
export async function setScreenOrientation(page, type) {
if (SDK_VERSION >= 16) {
let mask;
switch (type?.toLowerCase()) {
case 'landscape':
mask = 24 /* UIInterfaceOrientationMask.Landscape */;
break;
case 'portrait':
mask = 2 /* UIInterfaceOrientationMask.Portrait */;
break;
default:
mask = 30 /* UIInterfaceOrientationMask.All */;
break;
}
setSupportedInterfaceOrientations(page, mask);
const viewController = page.viewController;
const windowScene = page.nativeViewProtected?.window?.windowScene ?? UIApplication.sharedApplication.connectedScenes.anyObject();
windowScene?.requestGeometryUpdateWithPreferencesErrorHandler(UIWindowSceneGeometryPreferencesIOS.alloc().initWithInterfaceOrientations(mask), (error) => {
console.error(error);
});
if (viewController && viewController.setNeedsUpdateOfSupportedInterfaceOrientations) {
viewController.setNeedsUpdateOfSupportedInterfaceOrientations();
}
else {
UIViewController.attemptRotationToDeviceOrientation();
}
}
else {
switch (type?.toLowerCase()) {
case 'landscape':
UIDevice.currentDevice.setValueForKey(4 /* UIInterfaceOrientation.LandscapeLeft */, 'orientation');
setShouldAutoRotate(page, false);
break;
case 'portrait':
UIDevice.currentDevice.setValueForKey(1 /* UIInterfaceOrientation.Portrait */, 'orientation');
setShouldAutoRotate(page, false);
break;
default:
setShouldAutoRotate(page, true);
break;
}
}
}
let defaultStatusBarHidden;
function updatePagewSystemUI(page) {
if (!page) {
return;
}
// if (this.navigationBarColor) {
// this[cssNavigationBarColorProperty.setNative](this.navigationBarColor);
// }
page.checkStatusBarVisibility();
if (page.statusBarStyle) {
page.updateStatusBar();
}
if (page.statusBarColor) {
page.setStatusBarColor(page.statusBarColor);
}
if (page.windowBgColor) {
page.setWindowBgColor(page.windowBgColor);
}
if (page.keepScreenAwake) {
page[keepScreenAwakeProperty.setNative](page.keepScreenAwake);
}
if (page.screenBrightness > 0) {
page.applyCustomBrightness();
}
if (page.screenOrientation) {
setScreenOrientation(page, page.screenOrientation);
}
else {
setScreenOrientation(page, null);
}
}
let UIViewControllerBasedStatusBarAppearance;
class PageExtended {
setStatusBarVisibility(value, animated = true, duration = 200) {
UIApplication.sharedApplication.setStatusBarHiddenWithAnimation(!value, animated ? 2 /* UIStatusBarAnimation.Slide */ : 0 /* UIStatusBarAnimation.None */);
const statusBarView = this.getStatusBarView();
if (statusBarView) {
if (animated) {
UIView.animateWithDurationAnimations(duration / 1000, () => {
statusBarView.alpha = value ? 1 : 0;
});
}
else {
statusBarView.alpha = value ? 1 : 0;
}
}
}
checkStatusBarVisibility() {
if (defaultStatusBarHidden === undefined) {
defaultStatusBarHidden = UIApplication.sharedApplication.statusBarHidden;
}
this.setStatusBarVisibility(!(this.statusBarHidden ?? UIApplication.sharedApplication.statusBarHidden));
}
showStatusBar(animated = true) {
this.setStatusBarVisibility(true, animated);
}
hideStatusBar(animated = true) {
this.setStatusBarVisibility(false, animated);
}
getStatusBarView() {
const topParent = findTopView(this);
const viewController = topParent.viewController;
const topView = viewController.view.superview;
if (topView) {
return topView.viewWithTag(STATUSBAR_VIEW_TAG);
}
return null;
}
hideStatusBarColor() {
const topParent = findTopView(this);
const viewController = topParent.viewController;
const topView = viewController && viewController.view.superview;
if (topView) {
const statusBarView = topView.viewWithTag(STATUSBAR_VIEW_TAG);
if (statusBarView) {
statusBarView.hidden = true;
}
}
}
setStatusBarColor(color) {
const topParent = findTopView(this);
const viewController = topParent.viewController;
if (viewController.modalPresentationStyle === 2 /* UIModalPresentationStyle.FormSheet */) {
return null;
}
const topView = viewController.view.superview;
if (!topView && topParent._modalParent) {
topParent.once(View.shownModallyEvent, () => {
this.setStatusBarColor(color);
});
return;
}
if (topView) {
let statusBarView = topView.viewWithTag(STATUSBAR_VIEW_TAG);
if (!statusBarView) {
const statusBarFrame = UIApplication.sharedApplication.statusBarFrame;
statusBarView = UIView.alloc().initWithFrame(statusBarFrame);
statusBarView.tag = STATUSBAR_VIEW_TAG;
statusBarView.autoresizingMask = 2 /* FlexibleWidth */ | 32 /* FlexibleBottomMargin */;
statusBarView.autoresizesSubviews = true;
statusBarView.userInteractionEnabled = false;
topView.addSubview(statusBarView);
}
if (statusBarView) {
statusBarView.hidden = false;
statusBarView.backgroundColor = color ? color.ios : null;
}
}
}
setWindowBgColor(color) {
const nativeApp = UIApplication.sharedApplication;
const firstWindow = nativeApp.keyWindow || (nativeApp.windows.count > 0 && nativeApp.windows[0]);
if (firstWindow && firstWindow.rootViewController) {
firstWindow.rootViewController.view.backgroundColor = color ? color.ios : null;
return;
}
if (firstWindow) {
firstWindow.backgroundColor = color ? color.ios : null;
}
}
[cssStatusBarColorProperty.setNative](color) {
this.setStatusBarColor(color);
}
[statusBarHiddenProperty.setNative](value) {
this.setStatusBarVisibility(!value, true);
}
_updateStatusBarStyle(value) {
const frame = this.frame;
if (UIViewControllerBasedStatusBarAppearance === undefined) {
UIViewControllerBasedStatusBarAppearance = NSBundle.mainBundle.infoDictionary.objectForKey('UIViewControllerBasedStatusBarAppearance');
}
if (value) {
if (this.frame) {
const navigationController = frame.ios.controller;
const navigationBar = navigationController.navigationBar;
if (value === 'dark') {
navigationBar.barStyle = 1 /* UIBarStyle.Black */;
}
else {
navigationBar.barStyle = 0 /* UIBarStyle.Default */;
}
}
if (!UIViewControllerBasedStatusBarAppearance) {
if (value === 'dark') {
UIApplication.sharedApplication.setStatusBarStyleAnimated(1 /* UIStatusBarStyle.LightContent */, true);
}
else {
UIApplication.sharedApplication.setStatusBarStyleAnimated(3 /* UIStatusBarStyle.DarkContent */, true);
}
}
}
}
[statusBarStyleProperty.setNative](value) {
this._updateStatusBarStyle(value);
}
[cssWindowBgColorProperty.setNative](value) {
this.setWindowBgColor(value);
}
[keepScreenAwakeProperty.setNative](value) {
if (value) {
const app = UIApplication.sharedApplication;
if (!app.idleTimerDisabled) {
app.idleTimerDisabled = true;
}
}
else {
const app = UIApplication.sharedApplication;
if (app.idleTimerDisabled) {
app.idleTimerDisabled = false;
}
}
}
[screenBrightnessProperty.setNative](value) {
if (value < 0) {
this.resetCustomBrightness();
}
else {
this.applyCustomBrightness();
}
}
[screenOrientationProperty.setNative](value) {
setScreenOrientation(this, value);
}
didBecomeActive() {
if (this.screenBrightness > 0) {
this.applyCustomBrightness();
}
}
applyCustomBrightness() {
if (!this.didBecomeActiveListener) {
this.didBecomeActiveListener = this.didBecomeActive.bind(this);
addApplicationDidBecomeActiveListener(this.didBecomeActiveListener);
}
if (!this.savedBrightness) {
this.savedBrightness = UIScreen.mainScreen.brightness;
}
UIScreen.mainScreen.brightness = this.screenBrightness;
}
resetCustomBrightness() {
if (this.savedBrightness) {
UIScreen.mainScreen.brightness = this.savedBrightness;
this.savedBrightness = null;
}
}
_raiseShowingModallyEvent() {
updatePagewSystemUI(this);
}
_raiseShowingBottomSheetEvent() {
updatePagewSystemUI(this);
}
_raiseClosingModallyEvent() {
// if (this.keepScreenAwake) {
// this[keepScreenAwakeProperty.setNative](0);
// }
const currentPage = Frame.topmost()?.currentPage;
if (currentPage) {
updatePagewSystemUI(currentPage);
}
}
_raiseClosedBottomSheetEvent() {
// if (this.keepScreenAwake) {
// this[keepScreenAwakeProperty.setNative](0);
// }
const currentPage = Frame.topmost()?.currentPage;
if (currentPage) {
updatePagewSystemUI(currentPage);
}
}
onNavigatingTo(context, isBackNavigation, bindingContext) {
if (isBackNavigation) {
updatePagewSystemUI(this);
}
}
updateWithWillAppear() {
if (this.screenBrightness > 0) {
this.applyCustomBrightness();
}
}
updateWithWillDisappear() {
if (this.savedBrightness) {
this.resetCustomBrightness();
}
}
disposeNativeView() {
if (this.didBecomeActiveListener) {
removeApplicationDidBecomeActiveListener(this.didBecomeActiveListener);
this.didBecomeActiveListener = null;
}
}
}
__decorate([
cssProperty
], PageExtended.prototype, "navigationBarColor", void 0);
__decorate([
cssProperty
], PageExtended.prototype, "statusBarColor", void 0);
__decorate([
cssProperty
], PageExtended.prototype, "statusBarHidden", void 0);
__decorate([
cssProperty
], PageExtended.prototype, "windowBgColor", void 0);
__decorate([
cssProperty
], PageExtended.prototype, "keepScreenAwake", void 0);
__decorate([
cssProperty
], PageExtended.prototype, "screenBrightness", void 0);
__decorate([
cssProperty
], PageExtended.prototype, "screenOrientation", void 0);
let mixinInstalled = false;
export function overridePageBase() {
const NSPage = require('@nativescript/core/ui/page').Page;
applyMixins(NSPage, [PageExtended]);
}
function getAppDelegate() {
// Play nice with other plugins by not completely ignoring anything already added to the appdelegate
if (Application.ios.delegate === undefined) {
var UIApplicationDelegateImpl = /** @class */ (function (_super) {
__extends(UIApplicationDelegateImpl, _super);
function UIApplicationDelegateImpl() {
return _super !== null && _super.apply(this, arguments) || this;
}
UIApplicationDelegateImpl.ObjCProtocols = [UIApplicationDelegate];
return UIApplicationDelegateImpl;
}(UIResponder));
Application.ios.delegate = UIApplicationDelegateImpl;
}
return Application.ios.delegate;
}
const applicationDidBecomeActiveListeners = [];
function addApplicationDidBecomeActiveListener(l) {
applicationDidBecomeActiveListeners.push(l);
}
function removeApplicationDidBecomeActiveListener(l) {
const index = applicationDidBecomeActiveListeners.indexOf(l);
if (index !== -1) {
applicationDidBecomeActiveListeners.splice(index, 1);
}
}
function addAppDelegateMethods(appDelegate) {
// we need the launchOptions for this one so it's a bit hard to use the UIApplicationDidFinishLaunchingNotification pattern we're using for other things
// however, let's not override 'applicationDidFinishLaunchingWithOptions' if we don't really need it:
const oldMethod = appDelegate.prototype.applicationDidBecomeActive;
appDelegate.prototype.applicationDidBecomeActive = function (application) {
if (oldMethod) {
oldMethod.call(this, application);
}
applicationDidBecomeActiveListeners.forEach((l) => l());
return true;
};
}
export function installMixins() {
if (!mixinInstalled) {
mixinInstalled = true;
overridePageBase();
const delegate = getAppDelegate();
addAppDelegateMethods(delegate);
}
}
//# sourceMappingURL=index.ios.js.map