1 | import { initAccessibilityCssHelper } from '../accessibility/accessibility-css-helper';
|
2 | import { initAccessibilityFontScale } from '../accessibility/font-scale';
|
3 | import { CoreTypes } from '../core-types';
|
4 | import { CSSUtils } from '../css/system-classes';
|
5 | import { Device, Screen } from '../platform';
|
6 | import { profile } from '../profiling';
|
7 | import { Trace } from '../trace';
|
8 | import { Builder } from '../ui/builder';
|
9 | import * as bindableResources from '../ui/core/bindable/bindable-resources';
|
10 |
|
11 | const ORIENTATION_CSS_CLASSES = [
|
12 | `${CSSUtils.CLASS_PREFIX}${CoreTypes.DeviceOrientation.portrait}`,
|
13 | `${CSSUtils.CLASS_PREFIX}${CoreTypes.DeviceOrientation.landscape}`,
|
14 | `${CSSUtils.CLASS_PREFIX}${CoreTypes.DeviceOrientation.unknown}`,
|
15 | ];
|
16 |
|
17 | const SYSTEM_APPEARANCE_CSS_CLASSES = [
|
18 | `${CSSUtils.CLASS_PREFIX}${CoreTypes.SystemAppearance.light}`,
|
19 | `${CSSUtils.CLASS_PREFIX}${CoreTypes.SystemAppearance.dark}`,
|
20 | ];
|
21 | const globalEvents = global.NativeScriptGlobals.events;
|
22 | export class ApplicationCommon {
|
23 | |
24 |
|
25 |
|
26 | constructor() {
|
27 | this.launchEvent = 'launch';
|
28 | this.suspendEvent = 'suspend';
|
29 | this.displayedEvent = 'displayed';
|
30 | this.backgroundEvent = 'background';
|
31 | this.foregroundEvent = 'foreground';
|
32 | this.resumeEvent = 'resume';
|
33 | this.exitEvent = 'exit';
|
34 | this.lowMemoryEvent = 'lowMemory';
|
35 | this.uncaughtErrorEvent = 'uncaughtError';
|
36 | this.discardedErrorEvent = 'discardedError';
|
37 | this.orientationChangedEvent = 'orientationChanged';
|
38 | this.systemAppearanceChangedEvent = 'systemAppearanceChanged';
|
39 | this.fontScaleChangedEvent = 'fontScaleChanged';
|
40 | this.livesyncEvent = 'livesync';
|
41 | this.loadAppCssEvent = 'loadAppCss';
|
42 | this.cssChangedEvent = 'cssChanged';
|
43 | this.initRootViewEvent = 'initRootView';
|
44 |
|
45 | this.on = globalEvents.on.bind(globalEvents);
|
46 | this.once = globalEvents.once.bind(globalEvents);
|
47 | this.off = globalEvents.off.bind(globalEvents);
|
48 | this.notify = globalEvents.notify.bind(globalEvents);
|
49 | this.hasListeners = globalEvents.hasListeners.bind(globalEvents);
|
50 | this.cssFile = './app.css';
|
51 | |
52 |
|
53 |
|
54 | this.autoSystemAppearanceChanged = true;
|
55 | this._inBackground = false;
|
56 | this._suspended = false;
|
57 | this.started = false;
|
58 | global.NativeScriptGlobals.appInstanceReady = true;
|
59 | global.__onUncaughtError = (error) => {
|
60 | this.notify({
|
61 | eventName: this.uncaughtErrorEvent,
|
62 | object: this,
|
63 | android: error,
|
64 | ios: error,
|
65 | error: error,
|
66 | });
|
67 | };
|
68 | global.__onDiscardedError = (error) => {
|
69 | this.notify({
|
70 | eventName: this.discardedErrorEvent,
|
71 | object: this,
|
72 | error: error,
|
73 | });
|
74 | };
|
75 | global.__onLiveSync = (context) => {
|
76 | if (this.suspended) {
|
77 | return;
|
78 | }
|
79 | const rootView = this.getRootView();
|
80 | this.livesync(rootView, context);
|
81 | };
|
82 | }
|
83 | |
84 |
|
85 |
|
86 | livesync(rootView, context) {
|
87 | this.notify({ eventName: this.livesyncEvent, object: this });
|
88 | const liveSyncCore = global.__onLiveSyncCore;
|
89 | let reapplyAppStyles = false;
|
90 |
|
91 | if (context && context.path) {
|
92 | const styleExtensions = ['css', 'scss'];
|
93 | const appStylesFullFileName = this.getCssFileName();
|
94 | const appStylesFileName = appStylesFullFileName.substring(0, appStylesFullFileName.lastIndexOf('.') + 1);
|
95 | reapplyAppStyles = styleExtensions.some((ext) => context.path === appStylesFileName.concat(ext));
|
96 | }
|
97 |
|
98 | if (rootView && reapplyAppStyles) {
|
99 | rootView._onCssStateChange();
|
100 | }
|
101 | else if (liveSyncCore) {
|
102 | liveSyncCore(context);
|
103 | }
|
104 | }
|
105 | |
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 | applyCssClass(rootView, cssClasses, newCssClass, skipCssUpdate = false) {
|
114 | if (!rootView.cssClasses.has(newCssClass)) {
|
115 | cssClasses.forEach((cssClass) => this.removeCssClass(rootView, cssClass));
|
116 | this.addCssClass(rootView, newCssClass);
|
117 | this.increaseStyleScopeApplicationCssSelectorVersion(rootView);
|
118 | if (!skipCssUpdate) {
|
119 | rootView._onCssStateChange();
|
120 | }
|
121 | if (Trace.isEnabled()) {
|
122 | const rootCssClasses = Array.from(rootView.cssClasses);
|
123 | Trace.write(`Applying root css class: ${newCssClass}. rootView css classes: ${rootCssClasses.join(' ')}`, Trace.categories.Style);
|
124 | }
|
125 | }
|
126 | }
|
127 | addCssClass(rootView, cssClass) {
|
128 | CSSUtils.pushToSystemCssClasses(cssClass);
|
129 | rootView.cssClasses.add(cssClass);
|
130 | }
|
131 | removeCssClass(rootView, cssClass) {
|
132 | CSSUtils.removeSystemCssClass(cssClass);
|
133 | rootView.cssClasses.delete(cssClass);
|
134 | }
|
135 | increaseStyleScopeApplicationCssSelectorVersion(rootView) {
|
136 | const styleScope = rootView._styleScope ?? rootView?.currentPage?._styleScope;
|
137 | if (styleScope) {
|
138 | styleScope._increaseApplicationCssSelectorVersion();
|
139 | }
|
140 | }
|
141 | setRootViewCSSClasses(rootView) {
|
142 | const platform = Device.os.toLowerCase();
|
143 | const deviceType = Device.deviceType.toLowerCase();
|
144 | const orientation = this.orientation();
|
145 | const systemAppearance = this.systemAppearance();
|
146 | if (platform) {
|
147 | CSSUtils.pushToSystemCssClasses(`${CSSUtils.CLASS_PREFIX}${platform}`);
|
148 | }
|
149 | if (deviceType) {
|
150 | CSSUtils.pushToSystemCssClasses(`${CSSUtils.CLASS_PREFIX}${deviceType}`);
|
151 | }
|
152 | if (orientation) {
|
153 | CSSUtils.pushToSystemCssClasses(`${CSSUtils.CLASS_PREFIX}${orientation}`);
|
154 | }
|
155 | if (systemAppearance) {
|
156 | CSSUtils.pushToSystemCssClasses(`${CSSUtils.CLASS_PREFIX}${systemAppearance}`);
|
157 | }
|
158 | rootView.cssClasses.add(CSSUtils.ROOT_VIEW_CSS_CLASS);
|
159 | const rootViewCssClasses = CSSUtils.getSystemCssClasses();
|
160 | rootViewCssClasses.forEach((c) => rootView.cssClasses.add(c));
|
161 | this.increaseStyleScopeApplicationCssSelectorVersion(rootView);
|
162 | rootView._onCssStateChange();
|
163 | if (Trace.isEnabled()) {
|
164 | const rootCssClasses = Array.from(rootView.cssClasses);
|
165 | Trace.write(`Setting root css classes: ${rootCssClasses.join(' ')}`, Trace.categories.Style);
|
166 | }
|
167 | }
|
168 | |
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 | setMaxRefreshRate(options) {
|
182 |
|
183 | }
|
184 | |
185 |
|
186 |
|
187 | getMainEntry() {
|
188 | return this.mainEntry;
|
189 | }
|
190 | notifyLaunch(additionalLanchEventData) {
|
191 | const launchArgs = {
|
192 | eventName: this.launchEvent,
|
193 | object: this,
|
194 | ios: this.ios,
|
195 | android: this.android,
|
196 | ...additionalLanchEventData,
|
197 | };
|
198 | this.notify(launchArgs);
|
199 | this.loadAppCss();
|
200 | return launchArgs.root;
|
201 | }
|
202 | createRootView(view, fireLaunchEvent = false, additionalLanchEventData) {
|
203 | let rootView = view;
|
204 | if (!rootView) {
|
205 | if (fireLaunchEvent) {
|
206 | rootView = this.notifyLaunch(additionalLanchEventData);
|
207 |
|
208 | if (rootView === null) {
|
209 | return null;
|
210 | }
|
211 | }
|
212 | if (!rootView) {
|
213 |
|
214 | if (!this.mainEntry) {
|
215 | throw new Error('Main entry is missing. App cannot be started. Verify app bootstrap.');
|
216 | }
|
217 | rootView = Builder.createViewFromEntry(this.mainEntry);
|
218 | }
|
219 | }
|
220 | return rootView;
|
221 | }
|
222 | getRootView() {
|
223 | throw new Error('getRootView() Not implemented.');
|
224 | }
|
225 | resetRootView(entry) {
|
226 | this.mainEntry = typeof entry === 'string' ? { moduleName: entry } : entry;
|
227 |
|
228 | }
|
229 | initRootView(rootView) {
|
230 | this.setRootViewCSSClasses(rootView);
|
231 | initAccessibilityCssHelper();
|
232 | initAccessibilityFontScale();
|
233 | this.notify({ eventName: this.initRootViewEvent, rootView });
|
234 | }
|
235 | |
236 |
|
237 |
|
238 | getResources() {
|
239 | return bindableResources.get();
|
240 | }
|
241 | |
242 |
|
243 |
|
244 | setResources(res) {
|
245 | bindableResources.set(res);
|
246 | }
|
247 | |
248 |
|
249 |
|
250 | setCssFileName(cssFileName) {
|
251 | this.cssFile = cssFileName;
|
252 | this.notify({
|
253 | eventName: this.cssChangedEvent,
|
254 | object: this,
|
255 | cssFile: cssFileName,
|
256 | });
|
257 | }
|
258 | |
259 |
|
260 |
|
261 | getCssFileName() {
|
262 | return this.cssFile;
|
263 | }
|
264 | |
265 |
|
266 |
|
267 |
|
268 |
|
269 |
|
270 | loadAppCss() {
|
271 | try {
|
272 | this.notify({
|
273 | eventName: this.loadAppCssEvent,
|
274 | object: this,
|
275 | ios: this.ios,
|
276 | android: this.android,
|
277 | cssFile: this.getCssFileName(),
|
278 | });
|
279 | }
|
280 | catch (e) {
|
281 | if (Trace.isEnabled()) {
|
282 | Trace.write(`The app CSS file ${this.getCssFileName()} couldn't be loaded!`, Trace.categories.Style, Trace.messageType.warn);
|
283 | }
|
284 | }
|
285 | }
|
286 | addCss(cssText, attributeScoped) {
|
287 | this.notify({
|
288 | eventName: this.cssChangedEvent,
|
289 | object: this,
|
290 | cssText: cssText,
|
291 | });
|
292 | if (!attributeScoped) {
|
293 | const rootView = this.getRootView();
|
294 | if (rootView) {
|
295 | rootView._onCssStateChange();
|
296 | }
|
297 | }
|
298 | }
|
299 | run(entry) {
|
300 | throw new Error('run() Not implemented.');
|
301 | }
|
302 | getOrientation() {
|
303 |
|
304 | throw new Error('getOrientation() not implemented');
|
305 | }
|
306 | setOrientation(value) {
|
307 | if (this._orientation === value) {
|
308 | return;
|
309 | }
|
310 | this._orientation = value;
|
311 |
|
312 |
|
313 | Screen.mainScreen._updateMetrics();
|
314 | this.orientationChanged(this.getRootView(), value);
|
315 | this.notify({
|
316 | eventName: this.orientationChangedEvent,
|
317 | android: this.android,
|
318 | ios: this.ios,
|
319 | newValue: value,
|
320 | object: this,
|
321 | });
|
322 | }
|
323 | orientation() {
|
324 | return (this._orientation ?? (this._orientation = this.getOrientation()));
|
325 | }
|
326 | orientationChanged(rootView, newOrientation) {
|
327 | if (!rootView) {
|
328 | return;
|
329 | }
|
330 | const newOrientationCssClass = `${CSSUtils.CLASS_PREFIX}${newOrientation}`;
|
331 | this.applyCssClass(rootView, ORIENTATION_CSS_CLASSES, newOrientationCssClass, true);
|
332 | const rootModalViews = rootView._getRootModalViews();
|
333 | rootModalViews.forEach((rootModalView) => {
|
334 | this.applyCssClass(rootModalView, ORIENTATION_CSS_CLASSES, newOrientationCssClass, true);
|
335 |
|
336 | rootModalView._onCssStateChange();
|
337 | });
|
338 |
|
339 | rootView._onCssStateChange();
|
340 | }
|
341 | getNativeApplication() {
|
342 |
|
343 | throw new Error('getNativeApplication() not implemented');
|
344 | }
|
345 | hasLaunched() {
|
346 | return global.NativeScriptGlobals && global.NativeScriptGlobals.launched;
|
347 | }
|
348 | getSystemAppearance() {
|
349 |
|
350 | throw new Error('getSystemAppearance() not implemented');
|
351 | }
|
352 | setSystemAppearance(value) {
|
353 | if (this._systemAppearance === value) {
|
354 | return;
|
355 | }
|
356 | this._systemAppearance = value;
|
357 | this.systemAppearanceChanged(this.getRootView(), value);
|
358 | this.notify({
|
359 | eventName: this.systemAppearanceChangedEvent,
|
360 | android: this.android,
|
361 | ios: this.ios,
|
362 | newValue: value,
|
363 | object: this,
|
364 | });
|
365 | }
|
366 | systemAppearance() {
|
367 |
|
368 | return (this._systemAppearance ?? (this._systemAppearance = this.getSystemAppearance()));
|
369 | }
|
370 | |
371 |
|
372 |
|
373 | setAutoSystemAppearanceChanged(value) {
|
374 | this.autoSystemAppearanceChanged = value;
|
375 | }
|
376 | |
377 |
|
378 |
|
379 |
|
380 |
|
381 | systemAppearanceChanged(rootView, newSystemAppearance) {
|
382 | if (!rootView || !this.autoSystemAppearanceChanged) {
|
383 | return;
|
384 | }
|
385 | const newSystemAppearanceCssClass = `${CSSUtils.CLASS_PREFIX}${newSystemAppearance}`;
|
386 | this.applyCssClass(rootView, SYSTEM_APPEARANCE_CSS_CLASSES, newSystemAppearanceCssClass, true);
|
387 | const rootModalViews = rootView._getRootModalViews();
|
388 | rootModalViews.forEach((rootModalView) => {
|
389 | this.applyCssClass(rootModalView, SYSTEM_APPEARANCE_CSS_CLASSES, newSystemAppearanceCssClass, true);
|
390 |
|
391 | rootModalView._onCssStateChange();
|
392 | });
|
393 |
|
394 | rootView._onCssStateChange();
|
395 | }
|
396 | get inBackground() {
|
397 | return this._inBackground;
|
398 | }
|
399 | setInBackground(value, additonalData) {
|
400 | this._inBackground = value;
|
401 | this.notify({
|
402 | eventName: value ? this.backgroundEvent : this.foregroundEvent,
|
403 | object: this,
|
404 | ios: this.ios,
|
405 | ...additonalData,
|
406 | });
|
407 | }
|
408 | get suspended() {
|
409 | return this._suspended;
|
410 | }
|
411 | setSuspended(value, additonalData) {
|
412 | this._suspended = value;
|
413 | this.notify({
|
414 | eventName: value ? this.suspendEvent : this.resumeEvent,
|
415 | object: this,
|
416 | ios: this.ios,
|
417 | android: this.android,
|
418 | ...additonalData,
|
419 | });
|
420 | }
|
421 | get android() {
|
422 | return undefined;
|
423 | }
|
424 | get ios() {
|
425 | return undefined;
|
426 | }
|
427 | get AndroidApplication() {
|
428 | return this.android;
|
429 | }
|
430 | get iOSApplication() {
|
431 | return this.ios;
|
432 | }
|
433 | }
|
434 |
|
435 |
|
436 |
|
437 |
|
438 | ApplicationCommon.on = globalEvents.on.bind(globalEvents);
|
439 |
|
440 |
|
441 |
|
442 | ApplicationCommon.once = globalEvents.once.bind(globalEvents);
|
443 |
|
444 |
|
445 |
|
446 | ApplicationCommon.off = globalEvents.off.bind(globalEvents);
|
447 |
|
448 |
|
449 |
|
450 | ApplicationCommon.notify = globalEvents.notify.bind(globalEvents);
|
451 |
|
452 |
|
453 |
|
454 | ApplicationCommon.hasListeners = globalEvents.hasListeners.bind(globalEvents);
|
455 | __decorate([
|
456 | profile,
|
457 | __metadata("design:type", Function),
|
458 | __metadata("design:paramtypes", [Object]),
|
459 | __metadata("design:returntype", Function)
|
460 | ], ApplicationCommon.prototype, "notifyLaunch", null);
|
461 | __decorate([
|
462 | profile,
|
463 | __metadata("design:type", Function),
|
464 | __metadata("design:paramtypes", [Function, Object, Object]),
|
465 | __metadata("design:returntype", void 0)
|
466 | ], ApplicationCommon.prototype, "createRootView", null);
|
467 |
|
\ | No newline at end of file |