1/* 2 * Copyright (c) 2024 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 16if (!("finalizeConstruction" in ViewPU.prototype)) { 17 Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { }); 18} 19const hilog = requireNapi('hilog'); 20const abilityManager = requireNapi('app.ability.abilityManager'); 21const commonEventManager = requireNapi('commonEventManager'); 22const atomicServiceDataTag = 'ohos.atomicService.window'; 23const ERR_CODE_ABNORMAL = 100014; 24const ERR_CODE_CAPABILITY_NOT_SUPPORT = 801; 25const LOG_TAG = 'InnerFullScreenLaunchComponent'; 26export class LaunchController { 27 constructor() { 28 this.launchAtomicService = (n1, o1) => { }; 29 } 30} 31 32const EMBEDDED_FULL_MODE = 1; 33export class InnerFullScreenLaunchComponent extends ViewPU { 34 constructor(d1, e1, f1, g1 = -1, h1 = undefined, i1) { 35 super(d1, f1, g1, i1); 36 if (typeof h1 === "function") { 37 this.paramsGenerator_ = h1; 38 } 39 this.content = this.doNothingBuilder; 40 this.context = getContext(this); 41 this.controller = new LaunchController(); 42 this.appId = ''; 43 this.options = undefined; 44 this.__isShow = new ObservedPropertySimplePU(false, this, "isShow"); 45 this.subscriber = null; 46 this.onReceive = undefined; 47 this.launchAtomicService = (k1, l1) => { 48 hilog.info(0x3900, LOG_TAG, 'launchAtomicService, appId: %{public}s.', k1); 49 this.appId = k1; 50 this.options = l1; 51 this.checkAbility(); 52 }; 53 this.setInitiallyProvidedValue(e1); 54 this.finalizeConstruction(); 55 } 56 setInitiallyProvidedValue(c1) { 57 if (c1.content !== undefined) { 58 this.content = c1.content; 59 } 60 if (c1.context !== undefined) { 61 this.context = c1.context; 62 } 63 if (c1.controller !== undefined) { 64 this.controller = c1.controller; 65 } 66 if (c1.appId !== undefined) { 67 this.appId = c1.appId; 68 } 69 if (c1.options !== undefined) { 70 this.options = c1.options; 71 } 72 if (c1.isShow !== undefined) { 73 this.isShow = c1.isShow; 74 } 75 if (c1.subscriber !== undefined) { 76 this.subscriber = c1.subscriber; 77 } 78 if (c1.launchAtomicService !== undefined) { 79 this.launchAtomicService = c1.launchAtomicService; 80 } 81 if (c1.onReceive !== undefined) { 82 this.onReceive = c1.onReceive; 83 } 84 } 85 updateStateVars(b1) { 86 } 87 purgeVariableDependenciesOnElmtId(a1) { 88 this.__isShow.purgeDependencyOnElmtId(a1); 89 } 90 aboutToBeDeleted() { 91 this.__isShow.aboutToBeDeleted(); 92 SubscriberManager.Get().delete(this.id__()); 93 this.aboutToBeDeletedInternal(); 94 } 95 get isShow() { 96 return this.__isShow.get(); 97 } 98 set isShow(z) { 99 this.__isShow.set(z); 100 } 101 aboutToAppear() { 102 let s = { 103 events: [commonEventManager.Support.COMMON_EVENT_DISTRIBUTED_ACCOUNT_LOGOUT], 104 }; 105 commonEventManager.createSubscriber(s, (u, v) => { 106 if (u) { 107 hilog.error(0x3900, LOG_TAG, 'Failed to create subscriber, err: %{public}s.', u.message); 108 return; 109 } 110 if (v == null || v == undefined) { 111 hilog.error(0x3900, LOG_TAG, 'Failed to create subscriber, data is null.'); 112 return; 113 } 114 this.subscriber = v; 115 commonEventManager.subscribe(this.subscriber, (x, y) => { 116 if (x) { 117 hilog.error(0x3900, LOG_TAG, 'Failed to subscribe common event, err: %{public}s.', x.message); 118 return; 119 } 120 hilog.info(0x3900, LOG_TAG, 'Received account logout event.'); 121 this.isShow = false; 122 }); 123 }); 124 this.controller.launchAtomicService = this.launchAtomicService; 125 } 126 aboutToDisappear() { 127 if (this.subscriber !== null) { 128 commonEventManager.unsubscribe(this.subscriber, (r) => { 129 if (r) { 130 hilog.error(0x3900, LOG_TAG, 'UnsubscribeCallBack, err: %{public}s.', r.message); 131 } 132 else { 133 this.subscriber = null; 134 } 135 }); 136 } 137 } 138 doNothingBuilder(p = null) { 139 } 140 resetOptions() { 141 if (this.options?.parameters) { 142 this.options.parameters['ohos.extra.param.key.showMode'] = EMBEDDED_FULL_MODE; 143 this.options.parameters['ability.want.params.IsNotifyOccupiedAreaChange'] = true; 144 hilog.info(0x3900, LOG_TAG, 'replaced options is %{public}s !', JSON.stringify(this.options)); 145 } 146 else { 147 this.options = { 148 parameters: { 149 'ohos.extra.param.key.showMode': EMBEDDED_FULL_MODE, 150 'ability.want.params.IsNotifyOccupiedAreaChange': true, 151 } 152 }; 153 } 154 } 155 async checkAbility() { 156 if (this.isShow) { 157 hilog.error(0x3900, LOG_TAG, 'EmbeddedAbility already shows'); 158 this.isShow = false; 159 return; 160 } 161 this.resetOptions(); 162 try { 163 abilityManager.queryAtomicServiceStartupRule(this.context, this.appId) 164 .then((data) => { 165 if (data.isOpenAllowed) { 166 if (data.isEmbeddedAllowed) { 167 this.isShow = true; 168 hilog.info(0x3900, LOG_TAG, 'EmbeddedOpen is Allowed!'); 169 } else { 170 this.popUp(); 171 } 172 } else { 173 hilog.info(0x3900, LOG_TAG, 'is not allowed open!'); 174 } 175 }).catch((err) => { 176 hilog.error(0x3900, LOG_TAG, 'queryAtomicServiceStartupRule called error!%{public}s', err.message); 177 if (ERR_CODE_CAPABILITY_NOT_SUPPORT === err.code) { 178 this.popUp(); 179 } 180 }); 181 } 182 catch (err) { 183 hilog.error(0x3900, LOG_TAG, 'AtomicServiceStartupRule failed: %{public}s', err.message); 184 this.popUp(); 185 } 186 } 187 async popUp() { 188 this.isShow = false; 189 try { 190 const m = await this.context.openAtomicService(this.appId, this.options); 191 hilog.info(0x3900, LOG_TAG, '%{public}s open service success!', m.want); 192 } 193 catch (l) { 194 hilog.error(0x3900, LOG_TAG, '%{public}s open service error!', l.message); 195 } 196 } 197 handleOnReceiveEvent(data) { 198 if (data === undefined || data === null) { 199 return; 200 } 201 if (this.onReceive !== undefined) { 202 const sourceKeys = Object.keys(data); 203 let atomicServiceData = {}; 204 for (let i = 0; i < sourceKeys.length; i++) { 205 if (sourceKeys[i].includes(atomicServiceDataTag)) { 206 atomicServiceData[sourceKeys[i]] = data[sourceKeys[i]]; 207 } 208 } 209 this.onReceive(atomicServiceData); 210 } 211 } 212 initialRender() { 213 this.observeComponentCreation2((i, j) => { 214 Row.create(); 215 Row.justifyContent(FlexAlign.Center); 216 Row.bindContentCover({ value: this.isShow, changeEvent: k => { this.isShow = k; } }, { builder: () => { 217 this.uiExtensionBuilder.call(this); 218 } }, { 219 modalTransition: ModalTransition.DEFAULT, 220 enableSafeArea: true 221 }); 222 }, Row); 223 this.content.bind(this)(this); 224 Row.pop(); 225 } 226 uiExtensionBuilder(a = null) { 227 this.observeComponentCreation2((w20, x20) => { 228 Column.create(); 229 Column.height(LayoutPolicy.matchParent); 230 Column.width(LayoutPolicy.matchParent); 231 Column.ignoreLayoutSafeArea([LayoutSafeAreaType.SYSTEM], [LayoutSafeAreaEdge.TOP, LayoutSafeAreaEdge.BOTTOM]); 232 }, Column); 233 this.observeComponentCreation2((c, d) => { 234 UIExtensionComponent.create({ 235 bundleName: `com.atomicservice.${this.appId}`, 236 flags: this.options?.flags, 237 parameters: this.options?.parameters 238 }, { 239 windowModeFollowStrategy: WindowModeFollowStrategy.FOLLOW_HOST_WINDOW_MODE 240 }); 241 UIExtensionComponent.backgroundColor({ 'id': -1, 'type': 10001, params: ['sys.color.ohos_id_color_titlebar_bg'], 'bundleName': '__harDefaultBundleName__', 'moduleName': '__harDefaultModuleName__' }); 242 UIExtensionComponent.defaultFocus(true); 243 UIExtensionComponent.height('100%'); 244 UIExtensionComponent.width('100%'); 245 UIExtensionComponent.onRelease(() => { 246 hilog.error(0x3900, LOG_TAG, 'onRelease'); 247 this.isShow = false; 248 }); 249 UIExtensionComponent.onError(g => { 250 this.isShow = false; 251 hilog.error(0x3900, LOG_TAG, 'call up UIExtension error!%{public}s', g.message); 252 if (g.code !== ERR_CODE_ABNORMAL) { 253 this.getUIContext().showAlertDialog({ 254 message: g.message 255 }); 256 } 257 }); 258 UIExtensionComponent.onReceive(data => { 259 this.handleOnReceiveEvent(data); 260 }); 261 }, UIExtensionComponent); 262 Column.pop(); 263 } 264 rerender() { 265 this.updateDirtyElements(); 266 } 267} 268 269 270export default { InnerFullScreenLaunchComponent, LaunchController};