• 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    });
19}
20const TAG = 'AVInputCastPicker_component';
21
22/**
23 * Definition of av cast picker state.
24 */
25export let AVCastPickerState;
26(function (AVCastPickerState) {
27    /**
28     * The picker starts showing.
29     */
30    AVCastPickerState[AVCastPickerState['STATE_APPEARING'] = 0] = 'STATE_APPEARING';
31    /**
32     * The picker finishes presenting.
33     */
34    AVCastPickerState[AVCastPickerState['STATE_DISAPPEARING'] = 1] = 'STATE_DISAPPEARING';
35})(AVCastPickerState || (AVCastPickerState = {}));
36
37export class AVInputCastPicker extends ViewPU {
38    constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
39        super(parent, __localStorage, elmtId, extraInfo);
40        if (typeof paramsLambda === 'function') {
41            this.paramsGenerator_ = paramsLambda;
42        }
43        this.customPicker = undefined;
44        this.__deviceInfoList = new ObservedPropertyObjectPU([], this, 'deviceInfoList');
45        this.__touchMenuItemIndex = new ObservedPropertySimplePU(-1, this, 'touchMenuItemIndex');
46        this.__isDarkMode = new ObservedPropertySimplePU(false, this, 'isDarkMode');
47        this.__isRTL = new ObservedPropertySimplePU(false, this, 'isRTL');
48        this.onStateChange = undefined;
49        this.extensionProxy = null;
50        this.pickerClickTime = -1;
51        this.pickerCountOnCreation = 0;
52        this.setInitiallyProvidedValue(params);
53        this.finalizeConstruction();
54    }
55
56    setInitiallyProvidedValue(params) {
57        if (params.customPicker !== undefined) {
58            this.customPicker = params.customPicker;
59        }
60        if (params.deviceInfoList !== undefined) {
61            this.deviceInfoList = params.deviceInfoList;
62        }
63        if (params.touchMenuItemIndex !== undefined) {
64            this.touchMenuItemIndex = params.touchMenuItemIndex;
65        }
66        if (params.isDarkMode !== undefined) {
67            this.isDarkMode = params.isDarkMode;
68        }
69        if (params.isRTL !== undefined) {
70            this.isRTL = params.isRTL;
71        }
72        if (params.onStateChange !== undefined) {
73            this.onStateChange = params.onStateChange;
74        }
75        if (params.extensionProxy !== undefined) {
76            this.extensionProxy = params.extensionProxy;
77        }
78        if (params.pickerClickTime !== undefined) {
79            this.pickerClickTime = params.pickerClickTime;
80        }
81        if (params.pickerCountOnCreation !== undefined) {
82            this.pickerCountOnCreation = params.pickerCountOnCreation;
83        }
84    }
85
86    updateStateVars(params) {
87    }
88
89    purgeVariableDependenciesOnElmtId(rmElmtId) {
90        this.__deviceInfoList.purgeDependencyOnElmtId(rmElmtId);
91        this.__touchMenuItemIndex.purgeDependencyOnElmtId(rmElmtId);
92        this.__isDarkMode.purgeDependencyOnElmtId(rmElmtId);
93        this.__isRTL.purgeDependencyOnElmtId(rmElmtId);
94    }
95
96    aboutToBeDeleted() {
97        this.__deviceInfoList.aboutToBeDeleted();
98        this.__touchMenuItemIndex.aboutToBeDeleted();
99        this.__isDarkMode.aboutToBeDeleted();
100        this.__isRTL.aboutToBeDeleted();
101        SubscriberManager.Get().delete(this.id__());
102        this.aboutToBeDeletedInternal();
103    }
104
105    get deviceInfoList() {
106        return this.__deviceInfoList.get();
107    }
108
109    set deviceInfoList(newValue) {
110        this.__deviceInfoList.set(newValue);
111    }
112
113    get touchMenuItemIndex() {
114        return this.__touchMenuItemIndex.get();
115    }
116
117    set touchMenuItemIndex(newValue) {
118        this.__touchMenuItemIndex.set(newValue);
119    }
120
121    get isDarkMode() {
122        return this.__isDarkMode.get();
123    }
124
125    set isDarkMode(newValue) {
126        this.__isDarkMode.set(newValue);
127    }
128
129    get isRTL() {
130        return this.__isRTL.get();
131    }
132
133    set isRTL(newValue) {
134        this.__isRTL.set(newValue);
135    }
136
137    aboutToAppear() {
138        AVInputCastPicker.currentPickerCount += 1;
139        this.pickerCountOnCreation = AVInputCastPicker.currentPickerCount;
140    }
141
142    aboutToDisappear() {
143        AVInputCastPicker.currentPickerCount -= 1;
144    }
145
146    iconBuilder(item, isSelected, parent = null) {
147        this.observeComponentCreation2((elmtId, isInitialRender) => {
148            SymbolGlyph.create(!isSelected ? {
149                'id': -1,
150                'type': -1,
151                params: [item.deviceIconName],
152                'bundleName': '__harDefaultBundleName__',
153                'moduleName': '__harDefaultModuleName__'
154            } : {
155                'id': -1,
156                'type': -1,
157                params: [item.selectedIconName],
158                'bundleName': '__harDefaultBundleName__',
159                'moduleName': '__harDefaultModuleName__'
160            });
161            SymbolGlyph.fontSize('24vp');
162            SymbolGlyph.fontColor((isSelected && !this.isDarkMode) ?
163                [{
164                    'id': -1,
165                    'type': 10001,
166                    params: ['sys.color.comp_background_emphasize'],
167                    'bundleName': '__harDefaultBundleName__',
168                    'moduleName': '__harDefaultModuleName__'
169                }] : [{
170                    'id': -1,
171                    'type': 10001,
172                    params: ['sys.color.icon_primary'],
173                    'bundleName': '__harDefaultBundleName__',
174                    'moduleName': '__harDefaultModuleName__'
175                }]);
176            SymbolGlyph.renderingStrategy(SymbolRenderingStrategy.SINGLE);
177        }, SymbolGlyph);
178    }
179
180    textBuilder(item, parent = null) {
181        this.observeComponentCreation2((elmtId, isInitialRender) => {
182            Text.create(item.deviceName);
183            Text.fontSize({
184                'id': -1,
185                'type': 10002,
186                params: ['sys.float.ohos_id_text_size_body2'],
187                'bundleName': '__harDefaultBundleName__',
188                'moduleName': '__harDefaultModuleName__'
189            });
190            Text.fontColor(item.isConnected ? (!this.isDarkMode ? {
191                'id': -1,
192                'type': 10001,
193                params: ['sys.color.font_emphasize'],
194                'bundleName': '__harDefaultBundleName__',
195                'moduleName': '__harDefaultModuleName__'
196            } : {
197                'id': -1,
198                'type': 10001,
199                params: ['sys.color.font_primary'],
200                'bundleName': '__harDefaultBundleName__',
201                'moduleName': '__harDefaultModuleName__'
202            }) :
203                (!this.isDarkMode ? {
204                    'id': -1,
205                    'type': 10001,
206                    params: ['sys.color.font_primary'],
207                    'bundleName': '__harDefaultBundleName__',
208                    'moduleName': '__harDefaultModuleName__'
209                } : {
210                    'id': -1,
211                    'type': 10001,
212                    params: ['sys.color.font_secondary'],
213                    'bundleName': '__harDefaultBundleName__',
214                    'moduleName': '__harDefaultModuleName__'
215                }));
216            Text.width(254);
217            Text.padding({
218                left: 8,
219                top: 11,
220                right: 8,
221                bottom: 11
222            });
223            Text.textOverflow({ overflow: TextOverflow.Ellipsis });
224            Text.maxLines(2);
225            Text.wordBreak(WordBreak.BREAK_WORD);
226            Text.direction(this.isRTL ? Direction.Rtl : Direction.Ltr);
227        }, Text);
228        Text.pop();
229    }
230
231    deviceMenu(parent = null) {
232        this.observeComponentCreation2((elmtId, isInitialRender) => {
233            Column.create();
234            Column.width(326);
235            Column.borderRadius(8);
236        }, Column);
237        this.observeComponentCreation2((elmtId, isInitialRender) => {
238            ForEach.create();
239            const forEachItemGenFunction = (_item, index) => {
240                const item = _item;
241                this.observeComponentCreation2((elmtId, isInitialRender) => {
242                    Flex.create({
243                        direction: FlexDirection.Column,
244                        justifyContent: FlexAlign.SpaceBetween,
245                        alignItems: ItemAlign.End
246                    });
247                    Flex.width('100%');
248                    Flex.onClick(() => {
249                        console.info(TAG, ` item click ${item.isConnected}`);
250                        if (this.extensionProxy !== null && !item.isConnected) {
251                            this.extensionProxy.send({ 'selectedDeviceInfo': item });
252                        }
253                    });
254                }, Flex);
255                this.observeComponentCreation2((elmtId, isInitialRender) => {
256                    Flex.create({
257                        direction: FlexDirection.Row,
258                        justifyContent: FlexAlign.SpaceBetween,
259                        alignItems: ItemAlign.Center
260                    });
261                    Flex.constraintSize({ minHeight: 40 });
262                    Flex.padding({ left: 12, right: 12 });
263                    Flex.onTouch((event) => {
264                        if (event.type === TouchType.Down) {
265                            this.touchMenuItemIndex = index;
266                        } else if (event.type === TouchType.Up) {
267                            this.touchMenuItemIndex = -1;
268                        }
269                    });
270                    Flex.backgroundColor(this.touchMenuItemIndex === index ? {
271                        'id': -1,
272                        'type': 10001,
273                        params: ['sys.color.interactive_click'],
274                        'bundleName': '__harDefaultBundleName__',
275                        'moduleName': '__harDefaultModuleName__'
276                    } : '#00FFFFFF');
277                    Flex.borderRadius(this.touchMenuItemIndex === index ? {
278                        'id': -1,
279                        'type': 10002,
280                        params: ['sys.float.corner_radius_level2'],
281                        'bundleName': '__harDefaultBundleName__',
282                        'moduleName': '__harDefaultModuleName__'
283                    } : 0);
284                }, Flex);
285                this.observeComponentCreation2((elmtId, isInitialRender) => {
286                    Row.create();
287                    Row.alignItems(VerticalAlign.Center);
288                }, Row);
289                this.iconBuilder.bind(this)(item, false);
290                this.textBuilder.bind(this)(item);
291                Row.pop();
292                this.observeComponentCreation2((elmtId, isInitialRender) => {
293                    If.create();
294                    if (item.isConnected && item.selectedIconName !== null && item.selectedIconName !== undefined) {
295                        this.ifElseBranchUpdateFunction(0, () => {
296                            this.observeComponentCreation2((elmtId, isInitialRender) => {
297                                Row.create();
298                                Row.alignItems(VerticalAlign.Center);
299                            }, Row);
300                            this.iconBuilder.bind(this)(item, true);
301                            Row.pop();
302                        });
303                    } else {
304                        this.ifElseBranchUpdateFunction(1, () => {
305                        });
306                    }
307                }, If);
308                If.pop();
309                Flex.pop();
310                this.observeComponentCreation2((elmtId, isInitialRender) => {
311                    If.create();
312                    if (index !== this.deviceInfoList.length - 1) {
313                        this.ifElseBranchUpdateFunction(0, () => {
314                            this.observeComponentCreation2((elmtId, isInitialRender) => {
315                                Row.create();
316                                Row.width('100%');
317                                Row.height(2);
318                            }, Row);
319                            Row.pop();
320                        });
321                    } else {
322                        this.ifElseBranchUpdateFunction(1, () => {
323                        });
324                    }
325                }, If);
326                If.pop();
327                Flex.pop();
328            };
329            this.forEachUpdateFunction(elmtId, this.deviceInfoList, forEachItemGenFunction, undefined, true, false);
330        }, ForEach);
331        ForEach.pop();
332        Column.pop();
333    }
334
335    buildDefaultPicker(isCustomPicker, parent = null) {
336        this.observeComponentCreation2((elmtId, isInitialRender) => {
337            UIExtensionComponent.create({
338                abilityName: 'AVInputCastPickerAbility',
339                bundleName: 'com.hmos.mediacontroller',
340                parameters: {
341                    'ability.want.params.uiExtensionType': 'sysPicker/mediaControl',
342                    'isCustomPicker': isCustomPicker,
343                    'currentPickerCount': this.pickerCountOnCreation,
344                }
345            });
346            UIExtensionComponent.size({ width: '100%', height: '100%' });
347            UIExtensionComponent.bindMenu({
348                builder: () => {
349                    this.deviceMenu.call(this);
350                }
351            }, {
352                onDisappear: () => {
353                    this.touchMenuItemIndex = -1;
354                    if (this.onStateChange !== null && this.onStateChange !== undefined) {
355                        this.onStateChange(AVCastPickerState.STATE_DISAPPEARING);
356                    }
357                },
358                onAppear: () => {
359                    if (this.onStateChange !== null && this.onStateChange !== undefined) {
360                        this.onStateChange(AVCastPickerState.STATE_APPEARING);
361                    }
362                    if (this.extensionProxy !== null && this.pickerClickTime !== -1) {
363                        this.extensionProxy.send({ 'timeCost': new Date().getTime() - this.pickerClickTime });
364                        this.pickerClickTime = -1;
365                    }
366                }
367            });
368            UIExtensionComponent.onClick(() => {
369                this.pickerClickTime = new Date().getTime();
370            });
371            UIExtensionComponent.onRemoteReady((proxy) => {
372                console.info(TAG, 'onRemoteReady');
373                this.extensionProxy = proxy;
374            });
375            UIExtensionComponent.onReceive((data) => {
376                if (JSON.stringify(data['deviceInfoList']) !== undefined) {
377                    this.deviceInfoList = JSON.parse(JSON.stringify(data['deviceInfoList']));
378                }
379                if (JSON.stringify(data['isDarkMode']) !== undefined) {
380                    console.info(TAG, `isDarkMode : ${JSON.stringify(data['isDarkMode'])}`);
381                    this.isDarkMode = data['isDarkMode'];
382                }
383                if (JSON.stringify(data['isRTL']) !== undefined) {
384                    console.info(TAG, `isRTL : ${JSON.stringify(data['isRTL'])}`);
385                    this.isRTL = data['isRTL'];
386                }
387            });
388            UIExtensionComponent.onTerminated((info) => {
389                console.info(TAG, ` onTerminated code: ${info?.code}`);
390            });
391            UIExtensionComponent.onError((error) => {
392                console.info(TAG, ` onError code: ${error?.code} message: ${error?.message}`);
393            });
394        }, UIExtensionComponent);
395    }
396
397    buildCustomPicker(parent = null) {
398        this.observeComponentCreation2((elmtId, isInitialRender) => {
399            Stack.create({ alignContent: Alignment.Center });
400            Stack.size({ width: '100%', height: '100%' });
401        }, Stack);
402        this.observeComponentCreation2((elmtId, isInitialRender) => {
403            Column.create();
404            Column.alignItems(HorizontalAlign.Center);
405            Column.justifyContent(FlexAlign.Center);
406            Column.size({ width: '100%', height: '100%' });
407            Column.zIndex(0);
408        }, Column);
409        this.customPicker.bind(this)();
410        Column.pop();
411        this.observeComponentCreation2((elmtId, isInitialRender) => {
412            Column.create();
413            Column.alignItems(HorizontalAlign.Center);
414            Column.justifyContent(FlexAlign.Center);
415            Column.size({ width: '100%', height: '100%' });
416            Column.zIndex(1);
417        }, Column);
418        this.buildDefaultPicker.bind(this)(true);
419        Column.pop();
420        Stack.pop();
421    }
422
423    initialRender() {
424        this.observeComponentCreation2((elmtId, isInitialRender) => {
425            Column.create();
426            Column.size({ width: '100%', height: '100%' });
427        }, Column);
428        this.observeComponentCreation2((elmtId, isInitialRender) => {
429            If.create();
430            if (this.customPicker === undefined) {
431                this.ifElseBranchUpdateFunction(0, () => {
432                    this.buildDefaultPicker.bind(this)(false);
433                });
434            } else {
435                this.ifElseBranchUpdateFunction(1, () => {
436                    this.buildCustomPicker.bind(this)();
437                });
438            }
439        }, If);
440        If.pop();
441        Column.pop();
442    }
443
444    rerender() {
445        this.updateDirtyElements();
446    }
447}
448
449AVInputCastPicker.currentPickerCount = 0;
450export default { AVInputCastPicker };