• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { Log } from '../../utils/index';
17import {
18  defineFn,
19  bootstrap,
20  genTimerAPI
21} from './bundle';
22import { appMap } from './map';
23import { getPageGlobal } from './helper';
24import { App } from './App';
25import Page from '../page/index';
26import { destroy } from '../page/api/index';
27import { mockSystemPlugin } from '../extend/systemplugin/index';
28import { compileBundle } from '../page/entry/init';
29import { removePrefix } from '../util/index';
30import { requireModule } from '../page/register';
31
32/**
33 * Device information for mediaQuery.
34 */
35export interface MediaQueryInfo {
36  'orientation': string;
37  'deviceType': string;
38  'deviceWidth': string;
39  'deviceHeight': string;
40  'roundScreen': boolean;
41  'width': string;
42  'height': string;
43  'isInit': boolean;
44  'resolution': string;
45  'aspectRatio': string;
46  'darkMode': string;
47}
48
49/**
50 * Information of App.
51 */
52export interface Options extends MediaQueryInfo {
53  'appInstanceId': string;
54  'packageName': string;
55  'appCreate': boolean;
56  'appCode': string | Function;
57  'pcPreview': string;
58  'resourcesConfiguration': object;
59  'i18n': object;
60  'language': string;
61  'appGlobalData'?: object;
62  'bundleUrl': string;
63}
64
65/**
66 * Framework Services.
67 */
68export interface Services {
69  service: object;
70  I18n?: Function;
71  dpi?: Function;
72}
73
74interface ParseOptions {
75  $app_define$(...args: any[]): void; // eslint-disable-line camelcase
76  $app_bootstrap$(name: string, config: any, _data: any): void; // eslint-disable-line camelcase
77  $app_require$(name: string): void; // eslint-disable-line camelcase
78}
79
80const pageMap: Map<string, Page> = App.pageMap;
81
82/**
83 * Create app page, run jsbundle code.
84 * @param {Page} page
85 * @param {Options} options
86 * @param {Object} data
87 * @param {Services} services
88 */
89export function appCreate(page: Page, options: Options, data: object, services: Services): void {
90  if (!options || !options.appCreate || !options.appCode) {
91    return;
92  }
93  if (options.pcPreview && options.pcPreview === 'enable') {
94    mockSystemPlugin();
95  }
96  const packageName: string = page.packageName;
97  const appPage: Page = new Page(options.appInstanceId, options, packageName, data);
98  pageMap.set(appPage.id, appPage);
99  Log.debug(`Create a page with: ${packageName}.`);
100  appMap[packageName] = new App(packageName, options.appInstanceId);
101  const timerAPIs: object = genTimerAPI(appPage);
102  appMap[packageName].setTimer(timerAPIs);
103  const code = options.appCode;
104  global.__appProto__ = getPageGlobal(packageName);
105
106  // prepare page env methods
107  const appDefine = (...args: any[]): void => defineFn(page, packageName, ...args);
108  const appBootstrap = (name: string, config: any, _data: any): void => {
109    bootstrap(page, packageName, name, config, _data || data);
110    Log.debug(`After create a page(${page.id}).`);
111  };
112
113  // require in top app(instance)
114  const appRequireModule = name => requireModule(page || appPage, removePrefix(name));
115  const parseOptions: ParseOptions = {
116    $app_define$: appDefine,
117    $app_bootstrap$: appBootstrap,
118    $app_require$: appRequireModule
119  };
120
121  // Compile js bundle code and get result.
122  if (typeof code === 'function') {
123    Log.info('call Function directly when appCreate');
124    code.call(global, parseOptions);
125  } else {
126    // Function with code and use strict mode.
127    const functionCode: string = `(function(global){\n\n"use strict";\n\n ${code} \n\n})(this.__appProto__)`;
128    compileBundle(functionCode, 'app.js', parseOptions, timerAPIs, services);
129  }
130}
131
132/**
133 * Emit onError event.
134 * @param {string} packageName
135 * @param {*} errors
136 */
137export function appError(packageName: string, errors: any): void {
138  Log.debug(`AppError an app with: ${packageName}.`);
139  const app: App = appMap[packageName];
140  if (!app) {
141    Log.debug(`AppError an app error ${packageName}.`);
142    return;
143  }
144  Log.debug(`AppError an app error ${packageName}.`);
145  app.emitEvent('hook:onError', errors);
146}
147
148/**
149 * Emit onShow event.
150 * @param {string} packageName - Package name.
151 */
152export function appShow(packageName: string): void {
153  Log.debug(`Show an app with: ${packageName}.`);
154  const app: App = appMap[packageName];
155  if (!app) {
156    Log.debug(`Show an app error ${packageName}.`);
157    return;
158  }
159  app.emitEvent('hook:onShow');
160}
161
162/**
163 * Emit onHide event.
164 * @param {string} packageName - Package name.
165 */
166export function appHide(packageName: string): void {
167  Log.debug(`Hide an app with: ${packageName}.`);
168  const app: App = appMap[packageName];
169  if (!app) {
170    Log.debug(`Hide an app error ${packageName}.`);
171    return;
172  }
173  app.emitEvent('hook:onHide');
174}
175
176/**
177 * Emit onDestroy event.
178 * @param {string} packageName - Package name.
179 */
180export function appDestroy(packageName: string): void {
181  Log.debug(`Destroy an app with: ${packageName}.`);
182  const app: App = appMap[packageName];
183  if (!app) {
184    Log.error(`Destroy an app error ${packageName}.`);
185    return;
186  }
187  app.emitEvent('hook:onDestroy');
188  app.deleteGlobalKeys();
189  delete appMap[packageName];
190  const appPage: Page = pageMap.get(app.appInstanceId);
191  if (appPage) {
192    if (appPage.doc.taskCenter.callbackIsEmpty()) {
193      appPage.callTasks([{
194        module: 'internal.jsResult',
195        method: 'appDestroyFinish',
196        args: []
197      }]);
198      destroy(appPage);
199      pageMap.delete(appPage.id);
200    } else {
201      appPage.destroyed = true;
202    }
203  }
204}
205
206/**
207 * Init language resource.
208 * @param {*} i18nData
209 */
210export function updateLocale(i18nData: any): void {
211  if (i18nData) {
212    global.aceapp._i18n_data_ = { messages: i18nData.resources };
213  } else {
214    global.aceapp._i18n_data_ = null;
215  }
216}
217
218/**
219 * Init image dpi.
220 * @param {Object} dpiData
221 */
222export function updateDpi(dpiData: object): void {
223  if (dpiData) {
224    global.aceapp._dpi_data_ = { images: dpiData };
225  } else {
226    global.aceapp._dpi_data_ = null;
227  }
228}
229