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