Skip to content

Commit 935939b

Browse files
committed
Refactor the application module to prevent cyclic dependencies, which were:
* common requires application * application requires common * application requires application Make the exports typed using @hdeshev way.
1 parent d916d76 commit 935939b

File tree

4 files changed

+111
-84
lines changed

4 files changed

+111
-84
lines changed

application/application-common.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import definition = require("application");
33
import observable = require("data/observable");
44
import frame = require("ui/frame");
5+
import cssSelector = require("ui/styling/css-selector");
56
import * as fileSystemModule from "file-system";
67
import * as styleScopeModule from "ui/styling/style-scope";
78

@@ -21,6 +22,8 @@ export var mainEntry: frame.NavigationEntry;
2122

2223
export var cssFile: string = "app.css"
2324

25+
export var cssSelectorsCache: Array<cssSelector.CssSelector> = undefined;
26+
2427
export var resources: any = {};
2528

2629
export var onUncaughtError: (error: definition.NativeScriptError) => void = undefined;
@@ -39,18 +42,24 @@ export var android = undefined;
3942

4043
export var ios = undefined;
4144

42-
export function loadCss() {
43-
if (definition.cssFile) {
44-
var fs: typeof fileSystemModule = require("file-system");
45-
var styleScope: typeof styleScopeModule = require("ui/styling/style-scope");
46-
47-
var cssFileName = fs.path.join(fs.knownFolders.currentApp().path, definition.cssFile);
48-
if (fs.File.exists(cssFileName)) {
49-
var file = fs.File.fromPath(cssFileName);
50-
var applicationCss = file.readTextSync();
51-
if (applicationCss) {
52-
definition.cssSelectorsCache = styleScope.StyleScope.createSelectorsFromCss(applicationCss, cssFileName);
53-
}
45+
export function loadCss(cssFile?: string): Array<cssSelector.CssSelector> {
46+
if (!cssFile) {
47+
return undefined;
48+
}
49+
50+
var result: Array<cssSelector.CssSelector>;
51+
52+
var fs: typeof fileSystemModule = require("file-system");
53+
var styleScope: typeof styleScopeModule = require("ui/styling/style-scope");
54+
55+
var cssFileName = fs.path.join(fs.knownFolders.currentApp().path, cssFile);
56+
if (fs.File.exists(cssFileName)) {
57+
var file = fs.File.fromPath(cssFileName);
58+
var applicationCss = file.readTextSync();
59+
if (applicationCss) {
60+
result = styleScope.StyleScope.createSelectorsFromCss(applicationCss, cssFileName);
5461
}
5562
}
63+
64+
return result;
5665
}

application/application.android.ts

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import appModule = require("./application-common");
2-
import dts = require("application");
2+
import definition = require("application");
33
import frame = require("ui/frame");
44
import observable = require("data/observable");
55
import * as typesModule from "utils/types";
66
import * as fileResolverModule from "file-system/file-name-resolver";
77

88
global.moduleMerge(appModule, exports);
9+
var typedExports: typeof definition = exports;
910

1011
// 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;
1112
// TODO: This is kind of hacky and is "pure JS in TypeScript"
1213

1314
var initEvents = function () {
14-
var androidApp: dts.AndroidApplication = exports.android;
1515
// TODO: Verify whether the logic for triggerring application-wide events based on Activity callbacks is working properly
1616
var lifecycleCallbacks = new android.app.Application.ActivityLifecycleCallbacks({
1717
onActivityCreated: function (activity: any, bundle: any) {
@@ -22,7 +22,7 @@ var initEvents = function () {
2222
if (!androidApp.startActivity) {
2323
androidApp.startActivity = activity;
2424

25-
androidApp.notify(<dts.AndroidActivityBundleEventData>{ eventName: "activityCreated", object: androidApp, activity: activity, bundle: bundle });
25+
androidApp.notify(<definition.AndroidActivityBundleEventData>{ eventName: "activityCreated", object: androidApp, activity: activity, bundle: bundle });
2626

2727
if (androidApp.onActivityCreated) {
2828
androidApp.onActivityCreated(activity, bundle);
@@ -47,16 +47,16 @@ var initEvents = function () {
4747
}
4848

4949
if (activity === androidApp.startActivity) {
50-
if (exports.onExit) {
51-
exports.onExit();
50+
if (typedExports.onExit) {
51+
typedExports.onExit();
5252
}
5353

54-
exports.notify(<dts.ApplicationEventData>{ eventName: dts.exitEvent, object: androidApp, android: activity });
54+
typedExports.notify(<definition.ApplicationEventData>{ eventName: typedExports.exitEvent, object: androidApp, android: activity });
5555

5656
androidApp.startActivity = undefined;
5757
}
5858

59-
androidApp.notify(<dts.AndroidActivityEventData>{ eventName: "activityDestroyed", object: androidApp, activity: activity });
59+
androidApp.notify(<definition.AndroidActivityEventData>{ eventName: "activityDestroyed", object: androidApp, activity: activity });
6060

6161
if (androidApp.onActivityDestroyed) {
6262
androidApp.onActivityDestroyed(activity);
@@ -71,17 +71,17 @@ var initEvents = function () {
7171
return;
7272
}
7373

74-
(<any>androidApp).paused = true;
74+
androidApp.paused = true;
7575

7676
if (activity === androidApp.foregroundActivity) {
77-
if (exports.onSuspend) {
78-
exports.onSuspend();
77+
if (typedExports.onSuspend) {
78+
typedExports.onSuspend();
7979
}
8080

81-
exports.notify(<dts.ApplicationEventData>{ eventName: dts.suspendEvent, object: androidApp, android: activity });
81+
typedExports.notify(<definition.ApplicationEventData>{ eventName: typedExports.suspendEvent, object: androidApp, android: activity });
8282
}
8383

84-
androidApp.notify(<dts.AndroidActivityEventData>{ eventName: "activityPaused", object: androidApp, activity: activity });
84+
androidApp.notify(<definition.AndroidActivityEventData>{ eventName: "activityPaused", object: androidApp, activity: activity });
8585

8686
if (androidApp.onActivityPaused) {
8787
androidApp.onActivityPaused(activity);
@@ -93,17 +93,17 @@ var initEvents = function () {
9393
return;
9494
}
9595

96-
(<any>androidApp).paused = false;
96+
androidApp.paused = false;
9797

9898
if (activity === androidApp.foregroundActivity) {
99-
if (exports.onResume) {
100-
exports.onResume();
99+
if (typedExports.onResume) {
100+
typedExports.onResume();
101101
}
102102

103-
exports.notify(<dts.ApplicationEventData>{ eventName: dts.resumeEvent, object: androidApp, android: activity });
103+
typedExports.notify(<definition.ApplicationEventData>{ eventName: typedExports.resumeEvent, object: androidApp, android: activity });
104104
}
105105

106-
androidApp.notify(<dts.AndroidActivityEventData>{ eventName: "activityResumed", object: androidApp, activity: activity });
106+
androidApp.notify(<definition.AndroidActivityEventData>{ eventName: "activityResumed", object: androidApp, activity: activity });
107107

108108
if (androidApp.onActivityResumed) {
109109
androidApp.onActivityResumed(activity);
@@ -115,7 +115,7 @@ var initEvents = function () {
115115
return;
116116
}
117117

118-
androidApp.notify(<dts.AndroidActivityBundleEventData>{ eventName: "saveActivityState", object: androidApp, activity: activity, bundle: bundle });
118+
androidApp.notify(<definition.AndroidActivityBundleEventData>{ eventName: "saveActivityState", object: androidApp, activity: activity, bundle: bundle });
119119

120120
if (androidApp.onSaveActivityState) {
121121
androidApp.onSaveActivityState(activity, bundle);
@@ -129,7 +129,7 @@ var initEvents = function () {
129129

130130
androidApp.foregroundActivity = activity;
131131

132-
androidApp.notify(<dts.AndroidActivityEventData>{ eventName: "activityStarted", object: androidApp, activity: activity });
132+
androidApp.notify(<definition.AndroidActivityEventData>{ eventName: "activityStarted", object: androidApp, activity: activity });
133133

134134
if (androidApp.onActivityStarted) {
135135
androidApp.onActivityStarted(activity);
@@ -141,7 +141,7 @@ var initEvents = function () {
141141
return;
142142
}
143143

144-
androidApp.notify(<dts.AndroidActivityEventData>{ eventName: "activityStopped", object: androidApp, activity: activity });
144+
androidApp.notify(<definition.AndroidActivityEventData>{ eventName: "activityStopped", object: androidApp, activity: activity });
145145

146146
if (androidApp.onActivityStopped) {
147147
androidApp.onActivityStopped(activity);
@@ -155,15 +155,15 @@ var initEvents = function () {
155155
app.init({
156156
getActivity: function (activity: android.app.Activity) {
157157
var intent = activity.getIntent()
158-
return exports.android.getActivity(intent);
158+
return androidApp.getActivity(intent);
159159
},
160160

161161
onCreate: function () {
162-
exports.android.init(this);
162+
androidApp.init(this);
163163
}
164164
});
165165

166-
export class AndroidApplication extends observable.Observable implements dts.AndroidApplication {
166+
export class AndroidApplication extends observable.Observable implements definition.AndroidApplication {
167167
public static activityCreatedEvent = "activityCreated";
168168
public static activityDestroyedEvent = "activityDestroyed";
169169
public static activityStartedEvent = "activityStarted";
@@ -174,6 +174,7 @@ export class AndroidApplication extends observable.Observable implements dts.And
174174
public static activityResultEvent = "activityResult";
175175
public static activityBackPressedEvent = "activityBackPressed";
176176

177+
public paused: boolean;
177178
public nativeApp: android.app.Application;
178179
public context: android.content.Context;
179180
public currentContext: android.content.Context;
@@ -203,11 +204,11 @@ export class AndroidApplication extends observable.Observable implements dts.And
203204
public getActivity(intent: android.content.Intent): Object {
204205
if (intent && intent.getAction() === android.content.Intent.ACTION_MAIN) {
205206
// application's main activity
206-
if (exports.onLaunch) {
207-
exports.onLaunch(intent);
207+
if (typedExports.onLaunch) {
208+
typedExports.onLaunch(intent);
208209
}
209210

210-
exports.notify({ eventName: dts.launchEvent, object: this, android: intent });
211+
typedExports.notify({ eventName: typedExports.launchEvent, object: this, android: intent });
211212

212213
setupOrientationListener(this);
213214

@@ -221,9 +222,9 @@ export class AndroidApplication extends observable.Observable implements dts.And
221222
var topFrame = frame.topmost();
222223
if (!topFrame) {
223224
// try to navigate to the mainEntry/Module (if specified)
224-
var navParam = dts.mainEntry;
225+
var navParam = typedExports.mainEntry;
225226
if (!navParam) {
226-
navParam = dts.mainModule;
227+
navParam = typedExports.mainModule;
227228
}
228229

229230
if (navParam) {
@@ -304,25 +305,31 @@ class BroadcastReceiver extends android.content.BroadcastReceiver {
304305
}
305306
}
306307

307-
global.__onUncaughtError = function (error: Error) {
308+
global.__onUncaughtError = function (error: definition.NativeScriptError) {
308309
var types: typeof typesModule = require("utils/types");
309310

310311
// TODO: Obsolete this
311-
if (types.isFunction(exports.onUncaughtError)) {
312-
exports.onUncaughtError(error);
312+
if (types.isFunction(typedExports.onUncaughtError)) {
313+
typedExports.onUncaughtError(error);
313314
}
314315

315-
exports.notify({ eventName: dts.uncaughtErrorEvent, object: appModule.android, android: error });
316+
typedExports.notify({ eventName: typedExports.uncaughtErrorEvent, object: appModule.android, android: error });
316317
}
317318

318-
exports.start = function (entry?: frame.NavigationEntry) {
319-
if (entry) {
320-
dts.mainEntry = entry;
319+
function loadCss() {
320+
typedExports.cssSelectorsCache = typedExports.loadCss(typedExports.cssFile);
321+
}
322+
323+
export function start(entry?: frame.NavigationEntry) {
324+
if (entry) {
325+
typedExports.mainEntry = entry;
321326
}
322-
dts.loadCss();
327+
loadCss();
323328
}
324329

325-
exports.android = new AndroidApplication();
330+
var androidApp = new AndroidApplication();
331+
// use the exports object instead of 'export var' due to global namespace collision
332+
typedExports.android = androidApp;
326333

327334
var currentOrientation: number;
328335
function setupOrientationListener(androidApp: AndroidApplication) {
@@ -350,17 +357,17 @@ function onConfigurationChanged(context: android.content.Context, intent: androi
350357
break;
351358
}
352359

353-
exports.notify(<dts.OrientationChangedEventData>{
354-
eventName: dts.orientationChangedEvent,
360+
typedExports.notify(<definition.OrientationChangedEventData>{
361+
eventName: typedExports.orientationChangedEvent,
355362
android: context,
356363
newValue: newValue,
357-
object: exports.android,
364+
object: typedExports.android,
358365
});
359366
}
360367
}
361368

362369
global.__onLiveSync = function () {
363-
if (exports.android && exports.android.paused) {
370+
if (typedExports.android && typedExports.android.paused) {
364371
return;
365372
}
366373

@@ -370,7 +377,7 @@ global.__onLiveSync = function () {
370377
fileResolver.clearCache();
371378

372379
// Reload app.css in case it was changed.
373-
appModule.loadCss();
380+
loadCss();
374381

375382
// Reload current page.
376383
frame.reloadPage();

application/application.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,9 @@ declare module "application" {
118118

119119
/**
120120
* Loads css file and parses to a css syntax tree.
121+
* @param cssFile Optional parameter to point to an arbitrary css file. If not specified, the cssFile property is used.
121122
*/
122-
export function loadCss(): void;
123+
export function loadCss(cssFile?: string): Array<cssSelector.CssSelector>;
123124

124125
/**
125126
* 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" {
330331
*/
331332
packageName: string;
332333

334+
/**
335+
* True if the application is not running (suspended), false otherwise.
336+
*/
337+
paused: boolean;
338+
333339
/**
334340
* This method is called by the JavaScript Bridge when navigation to a new activity is triggered.
335341
* @param intent - Native (android) intent used to create the activity.

0 commit comments

Comments
 (0)