diff --git a/application/application-common.ts b/application/application-common.ts index 70c099870..2c3c1c3a8 100644 --- a/application/application-common.ts +++ b/application/application-common.ts @@ -2,6 +2,7 @@ import definition = require("application"); import observable = require("data/observable"); import frame = require("ui/frame"); +import cssSelector = require("ui/styling/css-selector"); import * as fileSystemModule from "file-system"; import * as styleScopeModule from "ui/styling/style-scope"; @@ -21,6 +22,8 @@ export var mainEntry: frame.NavigationEntry; export var cssFile: string = "app.css" +export var cssSelectorsCache: Array = undefined; + export var resources: any = {}; export var onUncaughtError: (error: definition.NativeScriptError) => void = undefined; @@ -39,18 +42,24 @@ export var android = undefined; export var ios = undefined; -export function loadCss() { - if (definition.cssFile) { - var fs: typeof fileSystemModule = require("file-system"); - var styleScope: typeof styleScopeModule = require("ui/styling/style-scope"); +export function loadCss(cssFile?: string): Array { + if (!cssFile) { + return undefined; + } - var cssFileName = fs.path.join(fs.knownFolders.currentApp().path, definition.cssFile); - if (fs.File.exists(cssFileName)) { - var file = fs.File.fromPath(cssFileName); - var applicationCss = file.readTextSync(); - if (applicationCss) { - definition.cssSelectorsCache = styleScope.StyleScope.createSelectorsFromCss(applicationCss, cssFileName); - } + var result: Array; + + var fs: typeof fileSystemModule = require("file-system"); + var styleScope: typeof styleScopeModule = require("ui/styling/style-scope"); + + var cssFileName = fs.path.join(fs.knownFolders.currentApp().path, cssFile); + if (fs.File.exists(cssFileName)) { + var file = fs.File.fromPath(cssFileName); + var applicationCss = file.readTextSync(); + if (applicationCss) { + result = styleScope.StyleScope.createSelectorsFromCss(applicationCss, cssFileName); } } + + return result; } \ No newline at end of file diff --git a/application/application.android.ts b/application/application.android.ts index cb711504a..435d290a3 100644 --- a/application/application.android.ts +++ b/application/application.android.ts @@ -1,17 +1,17 @@ import appModule = require("./application-common"); -import dts = require("application"); +import definition = require("application"); import frame = require("ui/frame"); import observable = require("data/observable"); import * as typesModule from "utils/types"; import * as fileResolverModule from "file-system/file-name-resolver"; global.moduleMerge(appModule, exports); +var typedExports: typeof definition = exports; // We are using the exports object for the common events since we merge the appModule with this module's exports, which is what users will receive when require("application") is called; // TODO: This is kind of hacky and is "pure JS in TypeScript" var initEvents = function () { - var androidApp: dts.AndroidApplication = exports.android; // TODO: Verify whether the logic for triggerring application-wide events based on Activity callbacks is working properly var lifecycleCallbacks = new android.app.Application.ActivityLifecycleCallbacks({ onActivityCreated: function (activity: any, bundle: any) { @@ -22,7 +22,7 @@ var initEvents = function () { if (!androidApp.startActivity) { androidApp.startActivity = activity; - androidApp.notify({ eventName: "activityCreated", object: androidApp, activity: activity, bundle: bundle }); + androidApp.notify({ eventName: "activityCreated", object: androidApp, activity: activity, bundle: bundle }); if (androidApp.onActivityCreated) { androidApp.onActivityCreated(activity, bundle); @@ -47,16 +47,16 @@ var initEvents = function () { } if (activity === androidApp.startActivity) { - if (exports.onExit) { - exports.onExit(); + if (typedExports.onExit) { + typedExports.onExit(); } - exports.notify({ eventName: dts.exitEvent, object: androidApp, android: activity }); + typedExports.notify({ eventName: typedExports.exitEvent, object: androidApp, android: activity }); androidApp.startActivity = undefined; } - androidApp.notify({ eventName: "activityDestroyed", object: androidApp, activity: activity }); + androidApp.notify({ eventName: "activityDestroyed", object: androidApp, activity: activity }); if (androidApp.onActivityDestroyed) { androidApp.onActivityDestroyed(activity); @@ -71,17 +71,17 @@ var initEvents = function () { return; } - (androidApp).paused = true; + androidApp.paused = true; if (activity === androidApp.foregroundActivity) { - if (exports.onSuspend) { - exports.onSuspend(); + if (typedExports.onSuspend) { + typedExports.onSuspend(); } - exports.notify({ eventName: dts.suspendEvent, object: androidApp, android: activity }); + typedExports.notify({ eventName: typedExports.suspendEvent, object: androidApp, android: activity }); } - androidApp.notify({ eventName: "activityPaused", object: androidApp, activity: activity }); + androidApp.notify({ eventName: "activityPaused", object: androidApp, activity: activity }); if (androidApp.onActivityPaused) { androidApp.onActivityPaused(activity); @@ -93,17 +93,17 @@ var initEvents = function () { return; } - (androidApp).paused = false; + androidApp.paused = false; if (activity === androidApp.foregroundActivity) { - if (exports.onResume) { - exports.onResume(); + if (typedExports.onResume) { + typedExports.onResume(); } - exports.notify({ eventName: dts.resumeEvent, object: androidApp, android: activity }); + typedExports.notify({ eventName: typedExports.resumeEvent, object: androidApp, android: activity }); } - androidApp.notify({ eventName: "activityResumed", object: androidApp, activity: activity }); + androidApp.notify({ eventName: "activityResumed", object: androidApp, activity: activity }); if (androidApp.onActivityResumed) { androidApp.onActivityResumed(activity); @@ -115,7 +115,7 @@ var initEvents = function () { return; } - androidApp.notify({ eventName: "saveActivityState", object: androidApp, activity: activity, bundle: bundle }); + androidApp.notify({ eventName: "saveActivityState", object: androidApp, activity: activity, bundle: bundle }); if (androidApp.onSaveActivityState) { androidApp.onSaveActivityState(activity, bundle); @@ -129,7 +129,7 @@ var initEvents = function () { androidApp.foregroundActivity = activity; - androidApp.notify({ eventName: "activityStarted", object: androidApp, activity: activity }); + androidApp.notify({ eventName: "activityStarted", object: androidApp, activity: activity }); if (androidApp.onActivityStarted) { androidApp.onActivityStarted(activity); @@ -141,7 +141,7 @@ var initEvents = function () { return; } - androidApp.notify({ eventName: "activityStopped", object: androidApp, activity: activity }); + androidApp.notify({ eventName: "activityStopped", object: androidApp, activity: activity }); if (androidApp.onActivityStopped) { androidApp.onActivityStopped(activity); @@ -155,15 +155,15 @@ var initEvents = function () { app.init({ getActivity: function (activity: android.app.Activity) { var intent = activity.getIntent() - return exports.android.getActivity(intent); + return androidApp.getActivity(intent); }, onCreate: function () { - exports.android.init(this); + androidApp.init(this); } }); -export class AndroidApplication extends observable.Observable implements dts.AndroidApplication { +export class AndroidApplication extends observable.Observable implements definition.AndroidApplication { public static activityCreatedEvent = "activityCreated"; public static activityDestroyedEvent = "activityDestroyed"; public static activityStartedEvent = "activityStarted"; @@ -174,6 +174,7 @@ export class AndroidApplication extends observable.Observable implements dts.And public static activityResultEvent = "activityResult"; public static activityBackPressedEvent = "activityBackPressed"; + public paused: boolean; public nativeApp: android.app.Application; public context: android.content.Context; public currentContext: android.content.Context; @@ -203,11 +204,11 @@ export class AndroidApplication extends observable.Observable implements dts.And public getActivity(intent: android.content.Intent): Object { if (intent && intent.getAction() === android.content.Intent.ACTION_MAIN) { // application's main activity - if (exports.onLaunch) { - exports.onLaunch(intent); + if (typedExports.onLaunch) { + typedExports.onLaunch(intent); } - exports.notify({ eventName: dts.launchEvent, object: this, android: intent }); + typedExports.notify({ eventName: typedExports.launchEvent, object: this, android: intent }); setupOrientationListener(this); @@ -221,9 +222,9 @@ export class AndroidApplication extends observable.Observable implements dts.And var topFrame = frame.topmost(); if (!topFrame) { // try to navigate to the mainEntry/Module (if specified) - var navParam = dts.mainEntry; + var navParam = typedExports.mainEntry; if (!navParam) { - navParam = dts.mainModule; + navParam = typedExports.mainModule; } if (navParam) { @@ -304,25 +305,31 @@ class BroadcastReceiver extends android.content.BroadcastReceiver { } } -global.__onUncaughtError = function (error: Error) { +global.__onUncaughtError = function (error: definition.NativeScriptError) { var types: typeof typesModule = require("utils/types"); // TODO: Obsolete this - if (types.isFunction(exports.onUncaughtError)) { - exports.onUncaughtError(error); + if (types.isFunction(typedExports.onUncaughtError)) { + typedExports.onUncaughtError(error); } - exports.notify({ eventName: dts.uncaughtErrorEvent, object: appModule.android, android: error }); + typedExports.notify({ eventName: typedExports.uncaughtErrorEvent, object: appModule.android, android: error }); } -exports.start = function (entry?: frame.NavigationEntry) { - if (entry) { - dts.mainEntry = entry; +function loadCss() { + typedExports.cssSelectorsCache = typedExports.loadCss(typedExports.cssFile); +} + +export function start(entry?: frame.NavigationEntry) { + if (entry) { + typedExports.mainEntry = entry; } - dts.loadCss(); + loadCss(); } -exports.android = new AndroidApplication(); +var androidApp = new AndroidApplication(); +// use the exports object instead of 'export var' due to global namespace collision +typedExports.android = androidApp; var currentOrientation: number; function setupOrientationListener(androidApp: AndroidApplication) { @@ -350,17 +357,17 @@ function onConfigurationChanged(context: android.content.Context, intent: androi break; } - exports.notify({ - eventName: dts.orientationChangedEvent, + typedExports.notify({ + eventName: typedExports.orientationChangedEvent, android: context, newValue: newValue, - object: exports.android, + object: typedExports.android, }); } } global.__onLiveSync = function () { - if (exports.android && exports.android.paused) { + if (typedExports.android && typedExports.android.paused) { return; } @@ -370,7 +377,7 @@ global.__onLiveSync = function () { fileResolver.clearCache(); // Reload app.css in case it was changed. - appModule.loadCss(); + loadCss(); // Reload current page. frame.reloadPage(); diff --git a/application/application.d.ts b/application/application.d.ts index 4eba814ab..060a13c3f 100644 --- a/application/application.d.ts +++ b/application/application.d.ts @@ -118,8 +118,9 @@ declare module "application" { /** * Loads css file and parses to a css syntax tree. + * @param cssFile Optional parameter to point to an arbitrary css file. If not specified, the cssFile property is used. */ - export function loadCss(): void; + export function loadCss(cssFile?: string): Array; /** * Call this method to start the application. Important: All code after this method call will not be executed! @@ -330,6 +331,11 @@ declare module "application" { */ packageName: string; + /** + * True if the application is not running (suspended), false otherwise. + */ + paused: boolean; + /** * This method is called by the JavaScript Bridge when navigation to a new activity is triggered. * @param intent - Native (android) intent used to create the activity. diff --git a/application/application.ios.ts b/application/application.ios.ts index d40ced6cb..036348601 100644 --- a/application/application.ios.ts +++ b/application/application.ios.ts @@ -7,6 +7,7 @@ import * as fileResolverModule from "file-system/file-name-resolver"; import * as enumsModule from "ui/enums"; global.moduleMerge(common, exports); +var typedExports: typeof definition = exports; class Responder extends UIResponder { // @@ -109,12 +110,12 @@ class IOSApplication implements definition.iOSApplication { this._window = Window.alloc().initWithFrame(UIScreen.mainScreen().bounds); this._window.backgroundColor = UIColor.whiteColor(); - if (exports.onLaunch) { - exports.onLaunch(); + if (typedExports.onLaunch) { + typedExports.onLaunch(undefined); } - exports.notify({ - eventName: exports.launchEvent, + typedExports.notify({ + eventName: typedExports.launchEvent, object: this, ios: notification.userInfo && notification.userInfo.objectForKey("UIApplicationLaunchOptionsLocalNotificationKey") || null }); @@ -122,9 +123,9 @@ class IOSApplication implements definition.iOSApplication { var topFrame = frame.topmost(); if (!topFrame) { // try to navigate to the mainEntry/Module (if specified) - var navParam = exports.mainEntry; + var navParam = typedExports.mainEntry; if (!navParam) { - navParam = exports.mainModule; + navParam = typedExports.mainModule; } if (navParam) { @@ -144,35 +145,35 @@ class IOSApplication implements definition.iOSApplication { } private didBecomeActive(notification: NSNotification) { - if (exports.onResume) { - exports.onResume(); + if (typedExports.onResume) { + typedExports.onResume(); } - exports.notify({ eventName: exports.resumeEvent, object: this, ios: UIApplication.sharedApplication() }); + typedExports.notify({ eventName: typedExports.resumeEvent, object: this, ios: UIApplication.sharedApplication() }); } private didEnterBackground(notification: NSNotification) { - if (exports.onSuspend) { - exports.onSuspend(); + if (typedExports.onSuspend) { + typedExports.onSuspend(); } - exports.notify({ eventName: exports.suspendEvent, object: this, ios: UIApplication.sharedApplication() }); + typedExports.notify({ eventName: typedExports.suspendEvent, object: this, ios: UIApplication.sharedApplication() }); } private willTerminate(notification: NSNotification) { - if (exports.onExit) { - exports.onExit(); + if (typedExports.onExit) { + typedExports.onExit(); } - exports.notify({ eventName: exports.exitEvent, object: this, ios: UIApplication.sharedApplication() }); + typedExports.notify({ eventName: typedExports.exitEvent, object: this, ios: UIApplication.sharedApplication() }); } private didReceiveMemoryWarning(notification: NSNotification) { - if (exports.onLowMemory) { - exports.onLowMemory(); + if (typedExports.onLowMemory) { + typedExports.onLowMemory(); } - exports.notify({ eventName: exports.lowMemoryEvent, object: this, android: undefined, ios: UIApplication.sharedApplication() }); + typedExports.notify({ eventName: typedExports.lowMemoryEvent, object: this, android: undefined, ios: UIApplication.sharedApplication() }); } private orientationDidChange(notification: NSNotification) { @@ -198,8 +199,8 @@ class IOSApplication implements definition.iOSApplication { break; } - exports.notify({ - eventName: exports.orientationChangedEvent, + typedExports.notify({ + eventName: typedExports.orientationChangedEvent, ios: this, newValue: newValue, object: this @@ -210,28 +211,32 @@ class IOSApplication implements definition.iOSApplication { } var iosApp = new IOSApplication(); -exports.ios = iosApp; +typedExports.ios = iosApp; -global.__onUncaughtError = function (error: Error) { +global.__onUncaughtError = function (error: definition.NativeScriptError) { var types: typeof typesModule = require("utils/types"); // TODO: This should be obsoleted - if (types.isFunction(exports.onUncaughtError)) { - exports.onUncaughtError(error); + if (types.isFunction(typedExports.onUncaughtError)) { + typedExports.onUncaughtError(error); } - exports.notify({ eventName: exports.uncaughtErrorEvent, object: exports.ios, ios: error }); + typedExports.notify({ eventName: typedExports.uncaughtErrorEvent, object: typedExports.ios, ios: error }); +} + +function loadCss() { + typedExports.cssSelectorsCache = typedExports.loadCss(typedExports.cssFile); } var started: boolean = false; -exports.start = function (entry?: frame.NavigationEntry) { +typedExports.start = function (entry?: frame.NavigationEntry) { if (!started) { if (entry) { exports.mainEntry = entry; } started = true; - exports.loadCss(); - UIApplicationMain(0, null, null, exports.ios && exports.ios.delegate ? NSStringFromClass(exports.ios.delegate) : NSStringFromClass(Responder)); + loadCss(); + UIApplicationMain(0, null, null, typedExports.ios && typedExports.ios.delegate ? NSStringFromClass(typedExports.ios.delegate) : NSStringFromClass(Responder)); } else { throw new Error("iOS Application already started!"); } @@ -248,7 +253,7 @@ global.__onLiveSync = function () { fileResolver.clearCache(); // Reload app.css in case it was changed. - exports.loadCss(); + loadCss(); // Reload current page. frame.reloadPage();