180922886Sopenharmony_ci/*
280922886Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
380922886Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
480922886Sopenharmony_ci * you may not use this file except in compliance with the License.
580922886Sopenharmony_ci * You may obtain a copy of the License at
680922886Sopenharmony_ci *
780922886Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
880922886Sopenharmony_ci *
980922886Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1080922886Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1180922886Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1280922886Sopenharmony_ci * See the License for the specific language governing permissions and
1380922886Sopenharmony_ci * limitations under the License.
1480922886Sopenharmony_ci */
1580922886Sopenharmony_ci
1680922886Sopenharmony_ciconst TAG = 'avcastpicker_component ';
1780922886Sopenharmony_ci
1880922886Sopenharmony_ci/**
1980922886Sopenharmony_ci * Definition of av cast picker state.
2080922886Sopenharmony_ci */
2180922886Sopenharmony_ciexport enum AVCastPickerState {
2280922886Sopenharmony_ci  /**
2380922886Sopenharmony_ci   * The picker starts showing.
2480922886Sopenharmony_ci   */
2580922886Sopenharmony_ci  STATE_APPEARING,
2680922886Sopenharmony_ci
2780922886Sopenharmony_ci  /**
2880922886Sopenharmony_ci   * The picker finishes presenting.
2980922886Sopenharmony_ci   */
3080922886Sopenharmony_ci  STATE_DISAPPEARING
3180922886Sopenharmony_ci}
3280922886Sopenharmony_ci
3380922886Sopenharmony_ci/**
3480922886Sopenharmony_ci * Definition of av cast picker state.
3580922886Sopenharmony_ci */
3680922886Sopenharmony_ciexport enum AVCastPickerStyle {
3780922886Sopenharmony_ci  /**
3880922886Sopenharmony_ci   * The picker shows in a panel style.
3980922886Sopenharmony_ci   */
4080922886Sopenharmony_ci  STYLE_PANEL,
4180922886Sopenharmony_ci
4280922886Sopenharmony_ci  /**
4380922886Sopenharmony_ci   * The picker shows in a menu style.
4480922886Sopenharmony_ci   */
4580922886Sopenharmony_ci  STYLE_MENU
4680922886Sopenharmony_ci}
4780922886Sopenharmony_ci
4880922886Sopenharmony_cienum DeviceSource {
4980922886Sopenharmony_ci  /**
5080922886Sopenharmony_ci   * local device
5180922886Sopenharmony_ci   */
5280922886Sopenharmony_ci  LOCAL,
5380922886Sopenharmony_ci
5480922886Sopenharmony_ci  /**
5580922886Sopenharmony_ci   * cast device
5680922886Sopenharmony_ci   */
5780922886Sopenharmony_ci  CAST
5880922886Sopenharmony_ci}
5980922886Sopenharmony_ci
6080922886Sopenharmony_cienum ConfigurationColorMode {
6180922886Sopenharmony_ci  /**
6280922886Sopenharmony_ci   * the color mode is not set.
6380922886Sopenharmony_ci   */
6480922886Sopenharmony_ci  COLOR_MODE_NOT_SET = -1,
6580922886Sopenharmony_ci
6680922886Sopenharmony_ci  /**
6780922886Sopenharmony_ci   * Dark mode.
6880922886Sopenharmony_ci   */
6980922886Sopenharmony_ci  COLOR_MODE_DARK = 0,
7080922886Sopenharmony_ci
7180922886Sopenharmony_ci  /**
7280922886Sopenharmony_ci   * Light mode.
7380922886Sopenharmony_ci   */
7480922886Sopenharmony_ci  COLOR_MODE_LIGHT = 1
7580922886Sopenharmony_ci}
7680922886Sopenharmony_ci
7780922886Sopenharmony_cienum AVCastPickerColorMode {
7880922886Sopenharmony_ci  /**
7980922886Sopenharmony_ci   * the color mode of picker is not set.
8080922886Sopenharmony_ci   */
8180922886Sopenharmony_ci  AUTO = 0,
8280922886Sopenharmony_ci
8380922886Sopenharmony_ci  /**
8480922886Sopenharmony_ci   * Dark mode of picker.
8580922886Sopenharmony_ci   */
8680922886Sopenharmony_ci  DARK = 1,
8780922886Sopenharmony_ci
8880922886Sopenharmony_ci  /**
8980922886Sopenharmony_ci   * Light mode of picker.
9080922886Sopenharmony_ci   */
9180922886Sopenharmony_ci  LIGHT = 2
9280922886Sopenharmony_ci}
9380922886Sopenharmony_ci
9480922886Sopenharmony_ci/**
9580922886Sopenharmony_ci * menuItem device info
9680922886Sopenharmony_ci */
9780922886Sopenharmony_ciexport interface AVCastPickerDeviceInfo {
9880922886Sopenharmony_ci  deviceId: number | String,
9980922886Sopenharmony_ci  deviceType: number,
10080922886Sopenharmony_ci  deviceName: string,
10180922886Sopenharmony_ci  deviceIconName: string,
10280922886Sopenharmony_ci  isConnected: boolean,
10380922886Sopenharmony_ci  selectedIconName: string,
10480922886Sopenharmony_ci  deviceSource: DeviceSource
10580922886Sopenharmony_ci}
10680922886Sopenharmony_ci
10780922886Sopenharmony_ci@Component
10880922886Sopenharmony_ciexport struct AVCastPicker {
10980922886Sopenharmony_ci  /**
11080922886Sopenharmony_ci   * Assigns the color of picker component at normal state.
11180922886Sopenharmony_ci   */
11280922886Sopenharmony_ci  @State normalColor: Color | number | string | undefined = undefined;
11380922886Sopenharmony_ci
11480922886Sopenharmony_ci  /**
11580922886Sopenharmony_ci   * Assigns the color of picker component at active state.
11680922886Sopenharmony_ci   */
11780922886Sopenharmony_ci  @State activeColor: Color | number | string | undefined = undefined;
11880922886Sopenharmony_ci
11980922886Sopenharmony_ci  /**
12080922886Sopenharmony_ci   * Definition of color mode of picker.
12180922886Sopenharmony_ci   */
12280922886Sopenharmony_ci  @State colorMode: AVCastPickerColorMode = AVCastPickerColorMode.AUTO;
12380922886Sopenharmony_ci
12480922886Sopenharmony_ci  /**
12580922886Sopenharmony_ci   * The device that is displayed in the menu.
12680922886Sopenharmony_ci   */
12780922886Sopenharmony_ci  @State deviceList: Array<AVCastPickerDeviceInfo> = [];
12880922886Sopenharmony_ci
12980922886Sopenharmony_ci  /**
13080922886Sopenharmony_ci   * Session type transferred by the application.
13180922886Sopenharmony_ci   */
13280922886Sopenharmony_ci  @State sessionType: string = 'audio';
13380922886Sopenharmony_ci
13480922886Sopenharmony_ci  /**
13580922886Sopenharmony_ci   * Display form of application transfer.
13680922886Sopenharmony_ci   */
13780922886Sopenharmony_ci  @State pickerStyle: AVCastPickerStyle = AVCastPickerStyle.STYLE_PANEL;
13880922886Sopenharmony_ci
13980922886Sopenharmony_ci  /**
14080922886Sopenharmony_ci   * Display form mediaController.
14180922886Sopenharmony_ci   */
14280922886Sopenharmony_ci  @State pickerStyleFromMediaController: AVCastPickerStyle = AVCastPickerStyle.STYLE_PANEL;
14380922886Sopenharmony_ci
14480922886Sopenharmony_ci  /**
14580922886Sopenharmony_ci   * Whether to display the menu.
14680922886Sopenharmony_ci   */
14780922886Sopenharmony_ci  @State@Watch('MenuStateChange') isMenuShow: boolean = false;
14880922886Sopenharmony_ci
14980922886Sopenharmony_ci  /**
15080922886Sopenharmony_ci   * Touch item index.
15180922886Sopenharmony_ci   */
15280922886Sopenharmony_ci  @State touchMenuItemIndex: number = -1;
15380922886Sopenharmony_ci
15480922886Sopenharmony_ci  /**
15580922886Sopenharmony_ci   * Picker state change callback.
15680922886Sopenharmony_ci   */
15780922886Sopenharmony_ci  private onStateChange?: (state: AVCastPickerState) => void;
15880922886Sopenharmony_ci
15980922886Sopenharmony_ci  /**
16080922886Sopenharmony_ci   * UIExtensionProxy.
16180922886Sopenharmony_ci   */
16280922886Sopenharmony_ci  private extensionProxy: UIExtensionProxy | null = null;
16380922886Sopenharmony_ci
16480922886Sopenharmony_ci  private pickerClickTime: number = -1;
16580922886Sopenharmony_ci
16680922886Sopenharmony_ci  /**
16780922886Sopenharmony_ci   * Custom builder from application.
16880922886Sopenharmony_ci   */
16980922886Sopenharmony_ci  @BuilderParam customPicker: (() => void)
17080922886Sopenharmony_ci
17180922886Sopenharmony_ci  /**
17280922886Sopenharmony_ci   * Configuration color mode.
17380922886Sopenharmony_ci   */
17480922886Sopenharmony_ci  @State configurationColorMode: number = ConfigurationColorMode.COLOR_MODE_NOT_SET;
17580922886Sopenharmony_ci
17680922886Sopenharmony_ci  @State deviceInfoType: string = '';
17780922886Sopenharmony_ci
17880922886Sopenharmony_ci  /**
17980922886Sopenharmony_ci   * Max Font and graphic magnification. 
18080922886Sopenharmony_ci   */
18180922886Sopenharmony_ci  private maxFonSizeScale: number = 2;
18280922886Sopenharmony_ci
18380922886Sopenharmony_ci  /**
18480922886Sopenharmony_ci   * Accessibility Strings
18580922886Sopenharmony_ci   */
18680922886Sopenharmony_ci  @State accessibilityConnectedStr: string = '已连接';
18780922886Sopenharmony_ci  @State accessibilityAudioControlStr: string = '音视频投播';
18880922886Sopenharmony_ci
18980922886Sopenharmony_ci  MenuStateChange() {
19080922886Sopenharmony_ci    if (this.extensionProxy != null) {
19180922886Sopenharmony_ci      this.extensionProxy.send({ 'isMenuShow': this.isMenuShow });
19280922886Sopenharmony_ci    }
19380922886Sopenharmony_ci  }
19480922886Sopenharmony_ci
19580922886Sopenharmony_ci  build() {
19680922886Sopenharmony_ci    Column() {
19780922886Sopenharmony_ci      if (this.customPicker === undefined) {
19880922886Sopenharmony_ci        this.buildDefaultPicker(false);
19980922886Sopenharmony_ci      } else {
20080922886Sopenharmony_ci        this.buildCustomPicker();
20180922886Sopenharmony_ci      }
20280922886Sopenharmony_ci    }.size({width: '100%', height: '100%'})
20380922886Sopenharmony_ci  }
20480922886Sopenharmony_ci
20580922886Sopenharmony_ci  @Builder
20680922886Sopenharmony_ci  buildIcon(item: AVCastPickerDeviceInfo, isSelected: boolean): void {
20780922886Sopenharmony_ci    if (this.deviceInfoType === 'true') {
20880922886Sopenharmony_ci      SymbolGlyph(!isSelected ? $r(item.deviceIconName) : $r(item.selectedIconName))
20980922886Sopenharmony_ci        .fontSize('24vp')
21080922886Sopenharmony_ci        .fontColor((isSelected && this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ?
21180922886Sopenharmony_ci          [$r('sys.color.comp_background_emphasize')] : [$r('sys.color.icon_primary')])
21280922886Sopenharmony_ci        .renderingStrategy(2)
21380922886Sopenharmony_ci    } else {
21480922886Sopenharmony_ci      Image(!isSelected ? $r(item.deviceIconName) : $r(item.selectedIconName))
21580922886Sopenharmony_ci        .width(24)
21680922886Sopenharmony_ci        .height(24)
21780922886Sopenharmony_ci        .fillColor((isSelected && this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ?
21880922886Sopenharmony_ci          $r('sys.color.comp_background_emphasize') : $r('sys.color.icon_primary'))
21980922886Sopenharmony_ci    }
22080922886Sopenharmony_ci  }
22180922886Sopenharmony_ci
22280922886Sopenharmony_ci  @Builder
22380922886Sopenharmony_ci  deviceMenu() {
22480922886Sopenharmony_ci    Column() {
22580922886Sopenharmony_ci      ForEach(this.deviceList, (item: AVCastPickerDeviceInfo, index) => {
22680922886Sopenharmony_ci        Flex({
22780922886Sopenharmony_ci          direction: FlexDirection.Column,
22880922886Sopenharmony_ci          justifyContent: FlexAlign.SpaceBetween,
22980922886Sopenharmony_ci          alignItems: ItemAlign.End
23080922886Sopenharmony_ci        }) {
23180922886Sopenharmony_ci          Flex({
23280922886Sopenharmony_ci            direction: FlexDirection.Row,
23380922886Sopenharmony_ci            justifyContent: FlexAlign.SpaceBetween,
23480922886Sopenharmony_ci            alignItems: ItemAlign.Center
23580922886Sopenharmony_ci          }) {
23680922886Sopenharmony_ci            Row() {
23780922886Sopenharmony_ci              this.buildIcon(item, false)
23880922886Sopenharmony_ci
23980922886Sopenharmony_ci              Text(item.deviceName)
24080922886Sopenharmony_ci                .fontSize($r('sys.float.ohos_id_text_size_body2'))
24180922886Sopenharmony_ci                .fontColor(item.isConnected ?
24280922886Sopenharmony_ci                  (this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK ?
24380922886Sopenharmony_ci                  $r('sys.color.font_emphasize') : $r('sys.color.font_primary')) :
24480922886Sopenharmony_ci                  (this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK ?
24580922886Sopenharmony_ci                  $r('sys.color.font_primary') : $r('sys.color.font_secondary')))
24680922886Sopenharmony_ci                .width(144)
24780922886Sopenharmony_ci                .padding({
24880922886Sopenharmony_ci                  left: 8,
24980922886Sopenharmony_ci                  top: 12,
25080922886Sopenharmony_ci                  right: 8,
25180922886Sopenharmony_ci                  bottom: 12
25280922886Sopenharmony_ci                })
25380922886Sopenharmony_ci                .textOverflow({ overflow: TextOverflow.Ellipsis })
25480922886Sopenharmony_ci                .maxLines(2)
25580922886Sopenharmony_ci                .wordBreak(WordBreak.BREAK_ALL)
25680922886Sopenharmony_ci                .maxFontScale(this.maxFonSizeScale)
25780922886Sopenharmony_ci            }
25880922886Sopenharmony_ci            .justifyContent(FlexAlign.Start)
25980922886Sopenharmony_ci            .alignItems(VerticalAlign.Center)
26080922886Sopenharmony_ci
26180922886Sopenharmony_ci            if (item.isConnected && item.selectedIconName !== null && item.selectedIconName !== undefined) {
26280922886Sopenharmony_ci              Row() {
26380922886Sopenharmony_ci                this.buildIcon(item, true)
26480922886Sopenharmony_ci              }
26580922886Sopenharmony_ci              .justifyContent(FlexAlign.Start)
26680922886Sopenharmony_ci              .alignItems(VerticalAlign.Center)
26780922886Sopenharmony_ci              .accessibilityLevel('yes')
26880922886Sopenharmony_ci              .accessibilityText(this.accessibilityConnectedStr)
26980922886Sopenharmony_ci            }
27080922886Sopenharmony_ci          }
27180922886Sopenharmony_ci          .constraintSize({ minHeight: 48 })
27280922886Sopenharmony_ci          .padding({ left: 12, right: 12 })
27380922886Sopenharmony_ci          .onTouch((event) => {
27480922886Sopenharmony_ci            if (event.type === TouchType.Down) {
27580922886Sopenharmony_ci              this.touchMenuItemIndex = index;
27680922886Sopenharmony_ci            } else if (event.type === TouchType.Up) {
27780922886Sopenharmony_ci              this.touchMenuItemIndex = -1;
27880922886Sopenharmony_ci            }
27980922886Sopenharmony_ci          })
28080922886Sopenharmony_ci          .backgroundColor(this.touchMenuItemIndex === index
28180922886Sopenharmony_ci            ? $r('sys.color.interactive_click') : '#00FFFFFF')
28280922886Sopenharmony_ci          .borderRadius(this.touchMenuItemIndex === index
28380922886Sopenharmony_ci            ? $r('sys.float.corner_radius_level8') : 0)
28480922886Sopenharmony_ci
28580922886Sopenharmony_ci          if (index != this.deviceList.length - 1) {
28680922886Sopenharmony_ci            Divider()
28780922886Sopenharmony_ci              .height(1)
28880922886Sopenharmony_ci              .width(172)
28980922886Sopenharmony_ci              .color($r('sys.color.comp_divider'))
29080922886Sopenharmony_ci              .padding({ right: 12 })
29180922886Sopenharmony_ci          }
29280922886Sopenharmony_ci        }
29380922886Sopenharmony_ci        .width('100%')
29480922886Sopenharmony_ci        .onClick(() => {
29580922886Sopenharmony_ci          if (this.extensionProxy != null && !item.isConnected) {
29680922886Sopenharmony_ci            this.extensionProxy.send({ 'selectedDeviceInfo': item })
29780922886Sopenharmony_ci          }
29880922886Sopenharmony_ci        })
29980922886Sopenharmony_ci      })
30080922886Sopenharmony_ci    }
30180922886Sopenharmony_ci    .width(216)
30280922886Sopenharmony_ci  }
30380922886Sopenharmony_ci
30480922886Sopenharmony_ci  @Builder
30580922886Sopenharmony_ci  private buildDefaultPicker(isCustomPicker: boolean) {
30680922886Sopenharmony_ci    UIExtensionComponent(
30780922886Sopenharmony_ci      {
30880922886Sopenharmony_ci        abilityName: 'UIExtAbility',
30980922886Sopenharmony_ci        bundleName: 'com.hmos.mediacontroller',
31080922886Sopenharmony_ci        parameters: {
31180922886Sopenharmony_ci          'normalColor': this.normalColor,
31280922886Sopenharmony_ci          'activeColor': this.activeColor,
31380922886Sopenharmony_ci          'pickerColorMode': this.colorMode,
31480922886Sopenharmony_ci          'avCastPickerStyle': this.pickerStyle,
31580922886Sopenharmony_ci          'ability.want.params.uiExtensionType': 'sysPicker/mediaControl',
31680922886Sopenharmony_ci          'isCustomPicker': isCustomPicker,
31780922886Sopenharmony_ci        }
31880922886Sopenharmony_ci      })
31980922886Sopenharmony_ci      .onRemoteReady((proxy: UIExtensionProxy) => {
32080922886Sopenharmony_ci        console.info(TAG, 'onRemoteReady');
32180922886Sopenharmony_ci        this.extensionProxy = proxy;
32280922886Sopenharmony_ci      })
32380922886Sopenharmony_ci      .onReceive((data) => {
32480922886Sopenharmony_ci        if (JSON.stringify(data['deviceInfoType']) !== undefined) {
32580922886Sopenharmony_ci          console.info(TAG, `deviceInfoType : ${JSON.stringify(data['deviceInfoType'])}`);
32680922886Sopenharmony_ci          this.deviceInfoType = data['deviceInfoType'] as string;
32780922886Sopenharmony_ci        }
32880922886Sopenharmony_ci
32980922886Sopenharmony_ci        if (JSON.stringify(data['pickerStyle']) !== undefined) {
33080922886Sopenharmony_ci          console.info(TAG, `picker style : ${JSON.stringify(data['pickerStyle'])}`);
33180922886Sopenharmony_ci          this.pickerStyleFromMediaController = data['pickerStyle'] as AVCastPickerStyle;
33280922886Sopenharmony_ci        }
33380922886Sopenharmony_ci
33480922886Sopenharmony_ci        if (JSON.stringify(data['deviceList']) !== undefined) {
33580922886Sopenharmony_ci          console.info(TAG, `picker device list : ${JSON.stringify(data['deviceList'])}`);
33680922886Sopenharmony_ci          this.deviceList = JSON.parse(JSON.stringify(data['deviceList']));
33780922886Sopenharmony_ci          let hasOnlySpeakerAndEarpiece: boolean = this.deviceList.length === 2 && !this.hasExtDevice(this.deviceList);
33880922886Sopenharmony_ci          let hasNoDevices: boolean = this.deviceList === null || this.deviceList.length === 0;
33980922886Sopenharmony_ci          let isCalling: boolean = this.sessionType === 'voice_call' || this.sessionType === 'video_call';
34080922886Sopenharmony_ci          let isExtMenuScene = isCalling && (hasNoDevices || hasOnlySpeakerAndEarpiece);
34180922886Sopenharmony_ci          let isPanelForMedia: boolean = !isCalling &&
34280922886Sopenharmony_ci            (this.pickerStyle === AVCastPickerStyle.STYLE_PANEL &&
34380922886Sopenharmony_ci            this.pickerStyleFromMediaController === AVCastPickerStyle.STYLE_PANEL);
34480922886Sopenharmony_ci          if (isExtMenuScene || isPanelForMedia) {
34580922886Sopenharmony_ci            this.isMenuShow = false;
34680922886Sopenharmony_ci            this.touchMenuItemIndex = -1;
34780922886Sopenharmony_ci          }
34880922886Sopenharmony_ci        }
34980922886Sopenharmony_ci
35080922886Sopenharmony_ci        if (JSON.stringify(data['state']) !== undefined) {
35180922886Sopenharmony_ci          console.info(TAG, `picker state change : ${JSON.stringify(data['state'])}`);
35280922886Sopenharmony_ci          let isCalling: boolean = (this.sessionType === 'voice_call' || this.sessionType === 'video_call');
35380922886Sopenharmony_ci          let isPanelForMedia: boolean = !isCalling &&
35480922886Sopenharmony_ci            (this.pickerStyle === AVCastPickerStyle.STYLE_PANEL &&
35580922886Sopenharmony_ci            this.pickerStyleFromMediaController === AVCastPickerStyle.STYLE_PANEL);
35680922886Sopenharmony_ci          if (this.onStateChange != null && isPanelForMedia) {
35780922886Sopenharmony_ci            if (parseInt(JSON.stringify(data['state'])) === AVCastPickerState.STATE_APPEARING) {
35880922886Sopenharmony_ci              this.onStateChange(AVCastPickerState.STATE_APPEARING);
35980922886Sopenharmony_ci            } else {
36080922886Sopenharmony_ci              this.onStateChange(AVCastPickerState.STATE_DISAPPEARING);
36180922886Sopenharmony_ci            }
36280922886Sopenharmony_ci          }
36380922886Sopenharmony_ci        }
36480922886Sopenharmony_ci
36580922886Sopenharmony_ci        if (JSON.stringify(data['sessionType']) !== undefined) {
36680922886Sopenharmony_ci          console.info(TAG, `session type : ${JSON.stringify(data['sessionType'])}`);
36780922886Sopenharmony_ci          this.sessionType = data['sessionType'] as string;
36880922886Sopenharmony_ci        }
36980922886Sopenharmony_ci
37080922886Sopenharmony_ci        if (JSON.stringify(data['isShowMenu']) !== undefined) {
37180922886Sopenharmony_ci          console.info(TAG, `isShowMenu : ${JSON.stringify(data['isShowMenu'])}`);
37280922886Sopenharmony_ci          this.isMenuShow = data['isShowMenu'] as boolean;
37380922886Sopenharmony_ci          if (!this.isMenuShow) {
37480922886Sopenharmony_ci            this.touchMenuItemIndex = -1;
37580922886Sopenharmony_ci          }
37680922886Sopenharmony_ci        }
37780922886Sopenharmony_ci
37880922886Sopenharmony_ci        if (JSON.stringify(data['configurationColorMode']) !== undefined) {
37980922886Sopenharmony_ci          console.info(TAG, `configurationColorMode : ${JSON.stringify(data['configurationColorMode'])}`);
38080922886Sopenharmony_ci          this.configurationColorMode = data['configurationColorMode'] as number;
38180922886Sopenharmony_ci        }
38280922886Sopenharmony_ci
38380922886Sopenharmony_ci        if (JSON.stringify(data['accessConnected']) !== undefined) {
38480922886Sopenharmony_ci          console.info(TAG, `accessConnected : ${JSON.stringify(data['accessConnected'])}`);
38580922886Sopenharmony_ci          this.accessibilityConnectedStr = data['accessConnected'] as string;
38680922886Sopenharmony_ci        }
38780922886Sopenharmony_ci
38880922886Sopenharmony_ci        if (JSON.stringify(data['accessAudioControl']) !== undefined) {
38980922886Sopenharmony_ci          console.info(TAG, `accessAudioControl : ${JSON.stringify(data['accessAudioControl'])}`);
39080922886Sopenharmony_ci          this.accessibilityAudioControlStr = data['accessAudioControl'] as string;
39180922886Sopenharmony_ci        }
39280922886Sopenharmony_ci      })
39380922886Sopenharmony_ci      .size({ width: '100%', height: '100%' })
39480922886Sopenharmony_ci      .bindMenu(this.isMenuShow, this.deviceMenu(), {
39580922886Sopenharmony_ci        placement: Placement.TopRight,
39680922886Sopenharmony_ci        onDisappear: () => {
39780922886Sopenharmony_ci          this.isMenuShow = false;
39880922886Sopenharmony_ci          this.touchMenuItemIndex = -1;
39980922886Sopenharmony_ci          this.menuShowStateCallback(this.isMenuShow);
40080922886Sopenharmony_ci        },
40180922886Sopenharmony_ci        onAppear: () => {
40280922886Sopenharmony_ci          if (this.extensionProxy != null && this.pickerClickTime !== -1) {
40380922886Sopenharmony_ci              this.extensionProxy.send({ 'timeCost': new Date().getTime() - this.pickerClickTime});
40480922886Sopenharmony_ci              this.pickerClickTime = -1;
40580922886Sopenharmony_ci          }
40680922886Sopenharmony_ci          this.menuShowStateCallback(this.isMenuShow);
40780922886Sopenharmony_ci        }
40880922886Sopenharmony_ci      })
40980922886Sopenharmony_ci      .onClick(() => {
41080922886Sopenharmony_ci        let hasOnlySpeakerAndEarpiece: boolean = this.deviceList.length === 2 && !this.hasExtDevice(this.deviceList);
41180922886Sopenharmony_ci        let hasNoDevices: boolean = this.deviceList === null || this.deviceList.length === 0;
41280922886Sopenharmony_ci        let isCalling: boolean = this.sessionType === 'voice_call' || this.sessionType === 'video_call';
41380922886Sopenharmony_ci        let isExtMenuScene: boolean = isCalling && (hasNoDevices || hasOnlySpeakerAndEarpiece);
41480922886Sopenharmony_ci        let isPanelForMedia: boolean = !isCalling &&
41580922886Sopenharmony_ci          (this.pickerStyle === AVCastPickerStyle.STYLE_PANEL &&
41680922886Sopenharmony_ci          this.pickerStyleFromMediaController === AVCastPickerStyle.STYLE_PANEL);        
41780922886Sopenharmony_ci        if (isExtMenuScene || isPanelForMedia) {
41880922886Sopenharmony_ci          if (this.extensionProxy != null) {
41980922886Sopenharmony_ci            this.extensionProxy.send({'clickEvent': true});
42080922886Sopenharmony_ci          }
42180922886Sopenharmony_ci          this.isMenuShow = false;
42280922886Sopenharmony_ci          this.touchMenuItemIndex = -1;
42380922886Sopenharmony_ci        } else {
42480922886Sopenharmony_ci          this.isMenuShow = !this.isMenuShow;
42580922886Sopenharmony_ci          if (this.isMenuShow) {
42680922886Sopenharmony_ci            this.pickerClickTime = new Date().getTime();
42780922886Sopenharmony_ci          } else {
42880922886Sopenharmony_ci            this.touchMenuItemIndex = -1;
42980922886Sopenharmony_ci          }
43080922886Sopenharmony_ci        }
43180922886Sopenharmony_ci      })
43280922886Sopenharmony_ci      .accessibilityLevel('yes')
43380922886Sopenharmony_ci      .accessibilityText(this.accessibilityAudioControlStr)
43480922886Sopenharmony_ci  }
43580922886Sopenharmony_ci
43680922886Sopenharmony_ci  private hasExtDevice(allDevice: Array<AVCastPickerDeviceInfo>): boolean {
43780922886Sopenharmony_ci    for (let i = 0; i < allDevice.length; i++) {
43880922886Sopenharmony_ci      if (allDevice[i].deviceType !== 1 && // 1 is audio.DeviceType.EARPIECE
43980922886Sopenharmony_ci        allDevice[i].deviceType !== 2) { // 2 is audio.DeviceType.SPEAKER
44080922886Sopenharmony_ci        return true;
44180922886Sopenharmony_ci      }
44280922886Sopenharmony_ci    }
44380922886Sopenharmony_ci    return false;
44480922886Sopenharmony_ci  }
44580922886Sopenharmony_ci
44680922886Sopenharmony_ci  private menuShowStateCallback(isMenuShow: boolean): void {
44780922886Sopenharmony_ci    if (this.onStateChange != null &&
44880922886Sopenharmony_ci      (this.pickerStyle === AVCastPickerStyle.STYLE_MENU ||
44980922886Sopenharmony_ci      this.pickerStyleFromMediaController === AVCastPickerStyle.STYLE_MENU)) {
45080922886Sopenharmony_ci      let menuShowState: AVCastPickerState = isMenuShow ?
45180922886Sopenharmony_ci        AVCastPickerState.STATE_APPEARING : AVCastPickerState.STATE_DISAPPEARING;
45280922886Sopenharmony_ci      this.onStateChange(menuShowState);
45380922886Sopenharmony_ci    }
45480922886Sopenharmony_ci  }
45580922886Sopenharmony_ci
45680922886Sopenharmony_ci  @Builder
45780922886Sopenharmony_ci  private buildCustomPicker() {
45880922886Sopenharmony_ci    Stack({ alignContent: Alignment.Center}) {
45980922886Sopenharmony_ci      Column() {
46080922886Sopenharmony_ci        this.customPicker();
46180922886Sopenharmony_ci      }
46280922886Sopenharmony_ci      .alignItems(HorizontalAlign.Center)
46380922886Sopenharmony_ci      .justifyContent(FlexAlign.Center)
46480922886Sopenharmony_ci      .size({ width: '100%', height: '100%' })
46580922886Sopenharmony_ci      .zIndex(0)
46680922886Sopenharmony_ci
46780922886Sopenharmony_ci      Column() {
46880922886Sopenharmony_ci        this.buildDefaultPicker(true);
46980922886Sopenharmony_ci      }
47080922886Sopenharmony_ci      .alignItems(HorizontalAlign.Center)
47180922886Sopenharmony_ci      .justifyContent(FlexAlign.Center)
47280922886Sopenharmony_ci      .size({ width: '100%', height: '100%' })
47380922886Sopenharmony_ci      .zIndex(1)
47480922886Sopenharmony_ci    }
47580922886Sopenharmony_ci    .size({ width: '100%', height: '100%' })
47680922886Sopenharmony_ci  }
47780922886Sopenharmony_ci}
478