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