1/* 2 * Copyright (c) 2025 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 EMBEDDED_HALF_MODE = 2; 23export class HalfScreenLaunchComponent extends ViewPU { 24 constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) { 25 super(parent, __localStorage, elmtId, extraInfo); 26 if (typeof paramsLambda === 'function') { 27 this.paramsGenerator_ = paramsLambda; 28 } 29 this.content = this.doNothingBuilder; 30 this.context = getContext(this); 31 this.appId = ''; 32 this.options = undefined; 33 this.__isShow = new ObservedPropertySimplePU(false, this, 'isShow'); 34 this.subscriber = null; 35 this.onError = undefined; 36 this.onTerminated = undefined; 37 this.setInitiallyProvidedValue(params); 38 this.finalizeConstruction(); 39 } 40 setInitiallyProvidedValue(params) { 41 if (params.content !== undefined) { 42 this.content = params.content; 43 } 44 if (params.context !== undefined) { 45 this.context = params.context; 46 } 47 if (params.appId !== undefined) { 48 this.appId = params.appId; 49 } 50 if (params.options !== undefined) { 51 this.options = params.options; 52 } 53 if (params.isShow !== undefined) { 54 this.isShow = params.isShow; 55 } 56 if (params.subscriber !== undefined) { 57 this.subscriber = params.subscriber; 58 } 59 if (params.onError !== undefined) { 60 this.onError = params.onError; 61 } 62 if (params.onTerminated !== undefined) { 63 this.onTerminated = params.onTerminated; 64 } 65 } 66 updateStateVars(params) { 67 } 68 purgeVariableDependenciesOnElmtId(rmElmtId) { 69 this.__isShow.purgeDependencyOnElmtId(rmElmtId); 70 } 71 aboutToBeDeleted() { 72 this.__isShow.aboutToBeDeleted(); 73 SubscriberManager.Get().delete(this.id__()); 74 this.aboutToBeDeletedInternal(); 75 } 76 get isShow() { 77 return this.__isShow.get(); 78 } 79 set isShow(newValue) { 80 this.__isShow.set(newValue); 81 } 82 aboutToAppear() { 83 let subscribeInfo = { 84 events: [commonEventManager.Support.COMMON_EVENT_DISTRIBUTED_ACCOUNT_LOGOUT], 85 }; 86 commonEventManager.createSubscriber(subscribeInfo, (err, data) => { 87 if (err) { 88 hilog.error(0x3900, 'HalfScreenLaunchComponent', 'Failed to create subscriber, err: %{public}s.', JSON.stringify(err)); 89 return; 90 } 91 if (data === null || data === undefined) { 92 hilog.error(0x3900, 'HalfScreenLaunchComponent', 'Failed to create subscriber, data is null.'); 93 return; 94 } 95 this.subscriber = data; 96 commonEventManager.subscribe(this.subscriber, (err, data) => { 97 if (err) { 98 hilog.error(0x3900, 'HalfScreenLaunchComponent', 'Failed to subscribe common event, err: %{public}s.', JSON.stringify(err)); 99 return; 100 } 101 this.isShow = false; 102 }); 103 }); 104 } 105 aboutToDisappear() { 106 if (this.subscriber !== null) { 107 commonEventManager.unsubscribe(this.subscriber, (err) => { 108 if (err) { 109 hilog.error(0x3900, 'HalfScreenLaunchComponent', 'UnsubscribeCallBack, err: %{public}s.', JSON.stringify(err)); 110 } 111 else { 112 hilog.info(0x3900, 'HalfScreenLaunchComponent', 'Unsubscribe.'); 113 this.subscriber = null; 114 } 115 }); 116 } 117 } 118 doNothingBuilder(parent = null) { 119 } 120 resetOptions() { 121 if (this.options?.parameters) { 122 this.options.parameters['ohos.extra.param.key.showMode'] = EMBEDDED_HALF_MODE; 123 this.options.parameters['ability.want.params.IsNotifyOccupiedAreaChange'] = true; 124 this.options.parameters['ability.want.params.IsModal'] = true; 125 hilog.info(0x3900, 'HalfScreenLaunchComponent', 'replaced options is %{public}s !', JSON.stringify(this.options)); 126 } 127 else { 128 this.options = { 129 parameters: { 130 'ohos.extra.param.key.showMode': EMBEDDED_HALF_MODE, 131 'ability.want.params.IsNotifyOccupiedAreaChange': true, 132 'ability.want.params.IsModal': true 133 } 134 }; 135 } 136 } 137 async checkAbility() { 138 this.resetOptions(); 139 try { 140 const res = await abilityManager.isEmbeddedOpenAllowed(this.context, this.appId); 141 if (res) { 142 if (this.isShow) { 143 this.isShow = false; 144 hilog.error(0x3900, 'HalfScreenLaunchComponent', ' EmbeddedOpen is already show!'); 145 return; 146 } 147 this.isShow = true; 148 hilog.info(0x3900, 'HalfScreenLaunchComponent', ' EmbeddedOpen is Allowed!'); 149 } 150 else { 151 this.popUp(); 152 } 153 } 154 catch (e) { 155 hilog.error(0x3900, 'HalfScreenLaunchComponent', 'isEmbeddedOpenAllowed called error!%{public}s', e.message); 156 } 157 } 158 async popUp() { 159 this.isShow = false; 160 try { 161 const ability = await this.context.openAtomicService(this.appId, this.options); 162 hilog.info(0x3900, 'HalfScreenLaunchComponent', '%{public}s open service success!', ability.want); 163 } 164 catch (e) { 165 hilog.error(0x3900, 'HalfScreenLaunchComponent', '%{public}s open service error!', e.message); 166 } 167 } 168 initialRender() { 169 this.observeComponentCreation2((elmtId, isInitialRender) => { 170 Row.create(); 171 Row.justifyContent(FlexAlign.Center); 172 Row.onClick(() => { 173 hilog.info(0x3900, 'HalfScreenLaunchComponent', 'on start atomicservice'); 174 this.checkAbility(); 175 }); 176 Row.bindContentCover({ value: this.isShow, changeEvent: newValue => { this.isShow = newValue; } }, { builder: () => { 177 this.uiExtensionBuilder.call(this); 178 } }, { modalTransition: ModalTransition.NONE }); 179 }, Row); 180 this.content.bind(this)(); 181 Row.pop(); 182 } 183 uiExtensionBuilder(parent = null) { 184 this.observeComponentCreation2((elmtId, isInitialRender) => { 185 UIExtensionComponent.create({ 186 bundleName: `com.atomicservice.${this.appId}`, 187 flags: this.options?.flags, 188 parameters: this.options?.parameters 189 }, 190 { 191 windowModeFollowStrategy: WindowModeFollowStrategy.FOLLOW_HOST_WINDOW_MODE 192 }); 193 UIExtensionComponent.height('100%'); 194 UIExtensionComponent.width('100%'); 195 UIExtensionComponent.backgroundColor(Color.Transparent); 196 UIExtensionComponent.onError(err => { 197 if (this.onError) { 198 this.onError(err); 199 } 200 this.isShow = false; 201 hilog.error(0x3900, 'HalfScreenLaunchComponent', 'call up UIExtension error!%{public}s', err.message); 202 this.getUIContext().showAlertDialog({ 203 message: err.message 204 }); 205 }); 206 UIExtensionComponent.onTerminated(info => { 207 this.isShow = false; 208 if (this.onTerminated) { 209 this.onTerminated(info); 210 } 211 }); 212 }, UIExtensionComponent); 213 } 214 rerender() { 215 this.updateDirtyElements(); 216 } 217} 218 219export default { HalfScreenLaunchComponent };