/*
* Copyright (c) 2023-2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import image from '@ohos.multimedia.image';
import { hdsMaterial } from '@hms.hds.hdsMaterial';
const TAG = 'avcastpicker_component ';
const castPlusAudioType = 8;
const MAX_PICKER_LIMIT = 20;
const HIGH_QUALITY_MAX_SCALE = 1.5;
const ZONE_ABNORMAL = 1;
const ZONE_ABNORMAL_OPACITY = 0.4;
const _isSupportHds = hdsMaterial.getSystemMaterialTypes().length > 0;
console.info(TAG, `isSupportHds: ${_isSupportHds}`);
interface MaterialUtil {
isSupportHds: () => boolean;
getMaterialStroke: (isDarkMode?: boolean) => hdsMaterial.Material | undefined;
}
const materialUtil: MaterialUtil = {
isSupportHds: () => {
return _isSupportHds;
},
getMaterialStroke: (isDarkMode?: boolean) => {
try {
if (_isSupportHds) {
return;
}
return new hdsMaterial.Material({
backgroundMaterial: {
type: hdsMaterial.MaterialType.ADAPTIVE,
scenario: hdsMaterial.ScenarioType.THICK,
darkMode: isDarkMode === undefined ? undefined :
(isDarkMode ? hdsMaterial.DarkMode.ALWAYS_DARK : hdsMaterial.DarkMode.ALWAYS_LIGHT),
}
});
} catch (e) {
console.info(TAG, `getMaterialStroke err: ${e?.code}, ${e?.message}`);
}
}
}
/**
* Definition of av cast picker state.
*/
export enum AVCastPickerState {
/**
* The picker starts showing.
*/
STATE_APPEARING,
/**
* The picker finishes presenting.
*/
STATE_DISAPPEARING
}
/**
* Definition of av cast picker state.
*/
export enum AVCastPickerStyle {
/**
* The picker shows in a panel style.
*/
STYLE_PANEL,
/**
* The picker shows in a menu style.
*/
STYLE_MENU
}
enum DeviceSource {
/**
* local device
*/
LOCAL,
/**
* cast device
*/
CAST
}
enum ConfigurationColorMode {
/**
* the color mode is not set.
*/
COLOR_MODE_NOT_SET = -1,
/**
* Dark mode.
*/
COLOR_MODE_DARK = 0,
/**
* Light mode.
*/
COLOR_MODE_LIGHT = 1
}
enum AVCastPickerColorMode {
/**
* the color mode of picker is not set.
*/
AUTO = 0,
/**
* Dark mode of picker.
*/
DARK = 1,
/**
* Light mode of picker.
*/
LIGHT = 2
}
enum HiPlayCastMode {
DEVICE_LEVEL = 1,
APP_LEVEL = 2
}
enum KeyInputCode {
KEYCODE_VOLUME_UP = 16,
KEYCODE_VOLUME_DOWN = 17
}
interface HighQualityParams {
iconLeft: string,
iconRight: string,
}
export interface ShowingBundleTS {
pixelData?: image.PixelMap | undefined;
appName?: string | undefined;
isShowBadge: boolean | undefined;
}
interface TextParams {
currentApp?: string,
allMediaAudio?: string,
playingNow?: string,
accessCastMode?: string,
accessPlayingNow?: string,
accessNewPoint?: string,
}
/**
* menuItem device info
*/
export interface AVCastPickerDeviceInfo {
deviceId: number | String,
deviceType: number,
deviceName: string,
deviceIconName: string,
isConnected: boolean,
selectedIconName: string,
deviceSource: DeviceSource,
networkId: string,
supportedProtocols?: number,
highQualityParams?: HighQualityParams,
fromCall?: boolean,
deviceSubName?: string,
supportCastMode?: number,
castMode?: number,
castUid?: number,
bundleInfo?: ShowingBundleTS,
}
/**
* 全屋音乐分区信息
*/
export interface HomeMusicServicesData {
bassWeight: number;
playTask: string;
acousticsMode: number;
volumePercentage: number;
description: number;
supportMusicLed: boolean;
label: string;
type: number;
roomId: string;
limitedVolume: number;
volume: number;
faultCode: number;
supportStereo: number;
playState: number;
speakerList: string;
enable: number;
name: string;
zoneId: string;
};
export interface HomeMusicServices {
st: string;
ts: string;
sid: string;
data: HomeMusicServicesData;
}
export type AnyType = string | boolean | number | bigint | null | object | undefined;
export interface HomeMusic {
devId: string;
devName: string;
homeId: string;
homeName: string;
roomId: string;
roomName: string;
status: string;
devInfo: Record<string, AnyType>;
services: HomeMusicServices[];
}
@Component
export struct AVCastPicker {
/**
* Assigns the color of picker component at normal state.
*/
@State normalColor: Color | number | string | undefined = undefined;
/**
* Assigns the color of picker component at active state.
*/
@State activeColor: Color | number | string | undefined = undefined;
/**
* Definition of color mode of picker.
*/
@State colorMode: AVCastPickerColorMode = AVCastPickerColorMode.AUTO;
/**
* The device that is displayed in the menu.
*/
@State deviceList: Array<AVCastPickerDeviceInfo> = [];
/**
* The scale of font size.
*/
@State fontSizeScale: number = 1;
/**
* Session type transferred by the application.
*/
@State sessionType: string = 'audio';
/**
* Display form of application transfer.
*/
@State pickerStyle: AVCastPickerStyle = AVCastPickerStyle.STYLE_PANEL;
/**
* Display form mediaController.
*/
@State pickerStyleFromMediaController: AVCastPickerStyle = AVCastPickerStyle.STYLE_PANEL;
/**
* Whether to display the menu.
*/
@State @Watch('MenuStateChange') isMenuShow: boolean = false;
/**
* Touch item index.
*/
@State touchMenuItemIndex: number = -1;
/**
* Text params.
*/
@State textParams: TextParams = {};
/**
* whether it is an ANCO session
*/
@State isAncoSession: boolean = false;
/**
* Picker state change callback.
*/
private onStateChange?: (state: AVCastPickerState) => void;
/**
* UIExtensionProxy.
*/
private extensionProxy: UIExtensionProxy | null = null;
private pickerClickTime: number = -1;
/**
* Custom builder from application.
*/
@BuilderParam customPicker: (() => void)
/**
* Configuration color mode.
*/
@State configurationColorMode: number = ConfigurationColorMode.COLOR_MODE_NOT_SET;
@State deviceInfoType: string = '';
/**
* Max Font and graphic magnification.
*/
@State maxFontSizeScale: number = 1;
/**
* Accessibility Strings
*/
@State accessibilityAudioControlStr: string = '音视频投播';
// 标题和全屋播放按钮
@State houseMusicTitle: string = '';
@State houseMusicPlay: string = '';
@State houseMusicPlayCancel: string = '';
// 房间信息
@State @Watch('roomListChange') roomListService: HomeMusicServices[] = [];
// 是否全选
@State isAllSelecting: boolean = false;
// 房间勾选
@State timeoutIds: number[] = [];
@State isSelectProcessing: boolean = false;
@State isAllCancel: boolean = false;
@State @Watch('scanDelayChange') scanDelay: boolean = false;
@State @Watch('homeMusicPlayTaskIdChange') playTaskIdStr: string = '';
@State roomIsSelect: boolean[] = [];
@State isSelectRoomListService: HomeMusicServices[] = [];
@State roomSelectStatusPending: boolean[] = [];
@State @Watch('selectHomeMusicSys') houseMusicIsSelect: boolean = false;
@State @Watch('homeMusicScanStatusChange') scanStatus: number = -1;
// 房间音量
@State roomVolumeVisible: Visibility[] = [];
@State roomCurrVolume: number[] = [];
@State roomMaxVolume: number = 0;
// 房间信息组件高度
@State roomItemHeight: number = 0;
@State isShowHomeAudio: boolean = false;
@State isPc: boolean = false;
@State isRTL: boolean = false;
@State restartUECMessage: number = 1;
private needToRestart: boolean = false;
@State isShowLoadingProgress: boolean = false;
private pickerCountOnCreation: number = 0;
@State isDisabledByPickerLimit: boolean = false;
@State isDeviceLevel: boolean = true;
@State @Watch('MenuStateChange') isSubMenuExpanded: boolean = false;
@State hasReceivedDeviceList: boolean = false;
@State deviceModelType: string = '';
@State isHdsThin: boolean = false;
private static currentPickerCount: number = 0;
aboutToAppear(): void {
AVCastPicker.currentPickerCount += 1;
this.pickerCountOnCreation = AVCastPicker.currentPickerCount;
if (this.pickerCountOnCreation > MAX_PICKER_LIMIT) {
console.info(TAG, 'disable picker');
this.isDisabledByPickerLimit = true;
}
this.isSelectProcessing = false;
this.isAllCancel = false;
}
aboutToDisappear(): void {
AVCastPicker.currentPickerCount -= 1;
this.clearTimer();
this.isSelectProcessing = false;
this.isAllCancel = false;
}
MenuStateChange() {
if (this.extensionProxy != null) {
this.extensionProxy.send({ 'isMenuShow': this.isMenuShow });
this.extensionProxy.send({ 'isSubMenuExpanded': this.isSubMenuExpanded });
let needListenKeyInput = (this.isMenuShow && this.houseMusicIsSelect);
this.extensionProxy.send({ 'isSelectHomeMusicSys': needListenKeyInput });
}
}
private createNullRoomService(): HomeMusicServices[] {
return [{'st':'','ts':'','sid':'','data':{'bassWeight':0,'playTask':'','acousticsMode':0,'volumePercentage':0,'description':0,
'supportMusicLed':false,'label':'','type':0,'roomId':'','limitedVolume':0,'volume':0,'faultCode':0,'supportStereo':0,
'playState':0,'speakerList':'','enable':0,'name':'','zoneId':''}}];
}
refreshShowHomeAudioStatus() {
this.isShowHomeAudio = ((this.sessionType !== 'voice_call') && (this.sessionType !== 'video_call') &&
(this.roomListService.length > 0));
}
refreshHomeMusicSelectStatus() {
if ((this.sessionType === 'voice_call') || (this.sessionType === 'video_call')) {
this.houseMusicIsSelect = false;
return;
}
let roomListTemp: HomeMusicServices[] = this.roomListService;
for (let i = 0; i < roomListTemp.length; i++) {
if ((roomListTemp[i].data.playTask === this.playTaskIdStr) && (this.playTaskIdStr !== '')) {
this.houseMusicIsSelect = true;
return;
}
}
this.houseMusicIsSelect = false;
}
refreshRoomList() {
if (!this.isAllCancel) {
this.clearTimer();
}
let roomListTemp: HomeMusicServices[] = this.roomListService;
let isAllRoomSelect: boolean = true;
let hasRoomIsSelect: boolean = false;
let maxVolumeNum: number = 0;
this.refreshShowHomeAudioStatus();
for (let i = 0; i < roomListTemp.length; i++) {
if (!this.isAllCancel) {
this.roomSelectStatusPending[i] = false;
}
this.roomIsSelect[i] = ((roomListTemp[i].data.playTask === this.playTaskIdStr) &&
(this.playTaskIdStr !== '')) ? true : false;
this.roomCurrVolume[i] = roomListTemp[i].data.volume;
this.roomVolumeVisible[i] = this.roomIsSelect[i] ? Visibility.Visible : Visibility.None;
if (!this.roomIsSelect[i]) {
isAllRoomSelect = false;
} else {
hasRoomIsSelect = true;
if (maxVolumeNum < roomListTemp[i].data.volume) {
maxVolumeNum = roomListTemp[i].data.volume;
}
}
}
if (!this.isAllCancel) {
this.isSelectProcessing = false;
}
if (isAllRoomSelect && roomListTemp.length > 0) {
this.isAllSelecting = true;
} else {
this.isAllSelecting = false;
}
this.houseMusicIsSelect = (hasRoomIsSelect && (this.sessionType !== 'voice_call') &&
(this.sessionType !== 'video_call'));
if (hasRoomIsSelect) {
this.roomMaxVolume = maxVolumeNum;
this.roomMaxVolumeChange();
}
}
homeMusicPlayTaskIdChange() {
this.refreshRoomList();
}
roomListChange() {
this.refreshRoomList();
}
selectHomeMusicSys() {
if (this.extensionProxy != null) {
let needListenKeyInput = (this.isMenuShow && this.houseMusicIsSelect);
this.extensionProxy.send({ 'isSelectHomeMusicSys': needListenKeyInput });
}
}
homeMusicScanStatusChange() {
if (this.scanStatus === 0) {
this.clearTimer();
// 全屋播控扫描中,现有房间显示全部需要pending,等待房间扫描刷新即可
this.setAllRoomSelectStatusPending();
this.isAllCancel = true;
this.scanDelay = false;
const timeId = setTimeout(() => {
this.scanDelay = true;
}, 13000);
if (typeof timeId === 'number') {
this.timeoutIds.push(timeId);
}
if (this.extensionProxy != null) {
this.extensionProxy.send({ 'getHomeMusicInfo': 1 });
}
} else {
this.scanDelayChange();
}
}
scanDelayChange() {
if (this.scanStatus !== 0 && this.scanDelay) {
this.roomSelectStatusPendingInit();
this.isAllCancel = false;
this.scanDelay = false;
}
}
roomMaxVolumeChange() {
if (this.extensionProxy != null) {
this.extensionProxy.send({ 'homeMusicMaxVolumeSync': this.roomMaxVolume });
}
}
findRoomMaxVolume() : number {
let maxVolumeNum: number = 0;
for (let i = 0; i < this.roomListService.length; i++) {
if ((maxVolumeNum < this.roomListService[i].data.volume) && this.checkRoomIsSelect(i)) {
maxVolumeNum = this.roomListService[i].data.volume;
}
}
return maxVolumeNum;
}
checkRoomIsSelect(index: number): boolean {
if((this.roomListService[index].data.playTask === this.playTaskIdStr) &&
(this.playTaskIdStr !== '')){
return true;
}
return false;
}
getCurrIsAllSelectStatus() {
let isAllSelect: boolean = true;
for(let i = 0; i < this.roomListService.length; i++) {
if (!this.checkRoomIsSelect(i)) {
isAllSelect = false;
break;
}
}
if (isAllSelect && (this.roomListService.length > 0)) {
return true;
}
return false;
}
clearTimer() {
this.timeoutIds.forEach((id) => {
clearTimeout(id);
});
this.timeoutIds = [];
}
roomSelectStatusPendingInit() {
for (let i = 0; i < this.roomListService.length; i++) {
this.roomSelectStatusPending[i] = false;
this.roomVolumeVisible[i] = this.checkRoomIsSelect(i) ? Visibility.Visible : Visibility.None;
}
this.isSelectProcessing = false;
}
setAllRoomSelectStatusPending() {
this.isSelectProcessing = true;
for (let i = 0; i < this.roomListService.length; i++) {
//全选时处理所有勾选状态转为pending,等待播控中心返回结果
this.roomSelectStatusPending[i] = true;
if (this.roomVolumeVisible[i] !== Visibility.None) {
this.roomVolumeVisible[i] = Visibility.None;
}
}
}
getCurrSelectRoom(index: number, selectStatus: boolean) {
// 先清除勾选的房间信息,再处理每个房间的勾选情况
this.isSelectRoomListService.length = 0;
for(let i = 0; i < this.roomListService.length; i++) {
if (i === index) {
if (selectStatus) {
this.isSelectRoomListService.push(this.roomListService[index]);
}
continue;
}
if (this.checkRoomIsSelect(i)) {
this.isSelectRoomListService.push(this.roomListService[i]);
}
}
}
onSliderValueChange(index: number, value: number, mode: SliderChangeMode) {
switch(mode) {
case SliderChangeMode.Begin:
case SliderChangeMode.Moving:
break;
case SliderChangeMode.End:
console.info(TAG, `Slider index:${index} Mode.End value:${value}`);
if (index < this.roomListService.length && this.extensionProxy != null) {
this.roomListService[index].data.description = index + 1;
this.extensionProxy.send({ 'roomVolumeChange': this.roomListService[index] });
this.roomMaxVolume = this.findRoomMaxVolume();
this.roomMaxVolumeChange();
}
break;
default:
break;
}
}
syncToRoomVolume(input: number) {
let volumeMin = 0;
let volumeStep = 10;
let volumeMax = 15;
for (let i = 0; i < this.roomListService.length; i++) {
if (!this.checkRoomIsSelect(i)) {
continue;
}
let currRoomVolume = Math.round(this.roomListService[i].data.volume * 3 / 2 / volumeStep);
let settingVolume = (input === KeyInputCode.KEYCODE_VOLUME_UP) ? currRoomVolume + 1 : currRoomVolume - 1;
if (settingVolume <= volumeMin) {
settingVolume = volumeMin;
} else if (settingVolume < volumeMin + 1) {
settingVolume = volumeMin + 1;
} else if (settingVolume >= volumeMax) {
settingVolume = volumeMax;
} else if (settingVolume > volumeMax - 1) {
settingVolume = volumeMax - 1;
} else {
settingVolume = Math.round(settingVolume);
}
this.roomListService[i].data.volume = Math.round(settingVolume * volumeStep * 2 / 3);
this.roomCurrVolume[i] = this.roomListService[i].data.volume;
}
}
sendAllRoomVolumeToController() {
if (this.extensionProxy != null) {
for (let i = 0; i < this.roomListService.length; i++) {
this.roomListService[i].data.description = i + 1;
this.extensionProxy.send({ 'roomVolumeChange': this.roomListService[i] });
}
}
}
allSelectOnClickEven() {
if (this.isSelectProcessing) {
return;
}
this.setAllRoomSelectStatusPending();
const timeId = setTimeout(() => {
this.roomSelectStatusPendingInit();
}, 3000);
if (typeof timeId === 'number') {
this.timeoutIds.push(timeId);
}
if (this.extensionProxy != null) {
if (!this.getCurrIsAllSelectStatus()) {
this.extensionProxy.send({ 'roomSelectChange': this.roomListService });
this.extensionProxy.send({ 'roomIsSelectAll': true });
} else {
this.extensionProxy.send({ 'roomSelectChange': this.createNullRoomService() });
this.extensionProxy.send({ 'roomIsSelectAll': false });
}
}
}
/**
* 全屋音乐播放标题 '全屋音乐系统' '全屋播放' / '取消全屋播放'
*/
@Builder HomeMusicSystemTitleBuilder() {
Row() {
Text(this.houseMusicTitle)
.fontColor($r('sys.color.font_primary'))
.fontSize($r('sys.float.Subtitle_M'))
.fontWeight(FontWeight.Medium)
.constraintSize({ maxWidth: '65%' })
Text(this.isAllSelecting ? this.houseMusicPlayCancel : this.houseMusicPlay)
.fontColor((this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ?
'#FF0A59F7' : '#FF317AF7')
.fontSize($r('sys.float.Body_M'))
.fontWeight(FontWeight.Medium)
.constraintSize({ maxWidth: '35%' })
.onClick(() => {
this.allSelectOnClickEven();
})
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.padding({top: '12vp', right: '16vp', bottom: '4vp', left: '16vp'})
.borderRadius({topLeft: '32vp', topRight: '32vp'})
}
/**
* 适配大字体(1.75倍以上)全屋音乐播放标题 '全屋音乐系统' '全屋播放' / '取消全屋播放'
*/
@Builder BigFontHomeMusicSystemTitleBuilder() {
Column() {
Text(this.houseMusicTitle)
.fontColor($r('sys.color.font_primary'))
.fontSize($r('sys.float.Subtitle_M'))
.fontWeight(FontWeight.Medium)
Text(this.isAllSelecting ? this.houseMusicPlayCancel : this.houseMusicPlay)
.fontColor((this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ?
'#FF0A59F7' : '#FF317AF7')
.fontSize($r('sys.float.Body_M'))
.fontWeight(FontWeight.Medium)
.onClick(() => {
this.allSelectOnClickEven();
})
}
.width('100%')
.alignItems(HorizontalAlign.Start)
.padding({top: '12vp', right: '16vp', bottom: '4vp', left: '16vp'})
.borderRadius({topLeft: '32vp', topRight: '32vp'})
}
/**
* 全屋音乐播放列表
*/
@Builder HomeMusicSystemRoomListBuilder() {
Column() {
ForEach(this.roomListService, (item: HomeMusicServices, index) => {
Stack({alignContent: Alignment.Start}) {
// 构建一行横向排列的全屋音乐 图标,房间名,音量条,勾选按钮
this.RoomItemBuilder(item, index)
}
.constraintSize({ minHeight: 64 })
.width('100%')
if (index !== this.roomListService.length - 1) {
// 构建行间分割线
this.DividerBuilder()
}
})
}
.padding({top: '4vp', right: '16vp', bottom: '4vp', left: '16vp'})
.width('100%')
.constraintSize({ minHeight: this.roomItemHeight })
.align(Alignment.Start)
.borderRadius({bottomLeft: '32vp', bottomRight: '32vp'})
}
/**
* 全屋音乐信息 - 横向排列 房间图标,房间名,音量条,勾选按钮
* @param item
* @param index
*/
@Builder RoomItemBuilder(item: HomeMusicServices, index: number) {
Column() {
Flex({alignItems: ItemAlign.Center}) {
this.RoomHouseBuilder();
this.RoomNameAndVolumeBuilder(item, index);
this.RoomCheckBuilder(item, index);
}
}
.opacity(item.data.faultCode === ZONE_ABNORMAL ? ZONE_ABNORMAL_OPACITY : 1)
.enabled(item.data.faultCode === ZONE_ABNORMAL ? false : true)
.onClick(() => {
if (this.isSelectProcessing) {
return;
}
this.roomSelectStatusPending[index] = true;
this.isSelectProcessing = true;
const timeId = setTimeout(() => {
this.roomSelectStatusPendingInit();
}, 3000);
if (typeof timeId === 'number') {
this.timeoutIds.push(timeId);
}
this.getCurrSelectRoom(index, !this.roomIsSelect[index]);
if (this.isSelectRoomListService.length > 0) {
if (this.extensionProxy != null) {
this.extensionProxy.send({ 'roomSelectChange': this.isSelectRoomListService });
}
} else {
if (this.extensionProxy != null) {
this.extensionProxy.send({ 'roomSelectChange': this.createNullRoomService() });
}
}
})
}
/**
* 全屋音乐播放列表
* - 房间图标构建
*/
@Builder RoomHouseBuilder() {
SymbolGlyph($r('sys.symbol.music_house_fill'))
.fontSize('24vp')
.fontColor((this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ?
[$r('sys.color.font_secondary')] : [$r('sys.color.icon_primary')])
.margin({
right: $r('sys.float.ohos_id_elements_margin_horizontal_l'),
left: 0
})
.draggable(false)
.flexGrow(0)
.flexShrink(0)
.flexBasis('auto')
.renderingStrategy(SymbolRenderingStrategy.SINGLE)
}
/**
* 全屋音乐播放列表
* - 房间名+音量条
*/
@Builder RoomNameAndVolumeBuilder(item: HomeMusicServices, index: number) {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start }) {
Text(item.data.name)
.fontWeight('sys.string.ohos_id_text_font_family_medium')
.fontSize($r('sys.float.ohos_id_text_size_body1'))
.textOverflow({ overflow: TextOverflow.Ellipsis })
.wordBreak(WordBreak.BREAK_ALL)
.width('100%')
.constraintSize({ minHeight: 16 })
Slider({
value: this.roomCurrVolume[index],
min: 0,
max: 100,
step: 1,
style: SliderStyle.NONE,
direction: Axis.Horizontal
})
.visibility(this.roomVolumeVisible[index])
.blockColor(Color.Transparent)
.showSteps(false)
.showTips(false)
.blockStyle({
type: SliderBlockType.SHAPE,
shape: new Path({ commands: 'M60 60 M30 30 L15 56 L45 56 Z' })
})
.responseRegion({
x: '0',
y: '-50%',
width: '100%',
height: '200%'
})
.zIndex(1)
.height(16)
.onChange((value: number, mode: SliderChangeMode) => {
console.info(TAG, `YuBeL room slider onChange: ${value}, mode=${mode}, index=${index}`);
this.roomListService[index].data.volume = value;
this.roomCurrVolume[index] = value;
this.onSliderValueChange(index, value, mode);
})
}
}
/**
* 全屋音乐播放列表
* - 勾选按钮
*/
@Builder RoomCheckBuilder(item: HomeMusicServices, index: number) {
//点击勾选按钮触发状态pending状态,等待播控中心下发勾选控制结果
if (!this.roomSelectStatusPending[index]) {
Checkbox()
.select(this.roomIsSelect[index])
.shape(CheckBoxShape.CIRCLE)
.onClick(() => {
this.roomSelectStatusPending[index] = true;
this.isSelectProcessing = true;
const timeId = setTimeout(() => {
this.roomSelectStatusPendingInit();
}, 3000);
if (typeof timeId === 'number') {
this.timeoutIds.push(timeId);
}
this.getCurrSelectRoom(index, !this.roomIsSelect[index]);
if (this.isSelectRoomListService.length > 0) {
if (this.extensionProxy != null) {
this.extensionProxy.send({ 'roomSelectChange': this.isSelectRoomListService });
}
} else {
if (this.extensionProxy != null) {
this.extensionProxy.send({ 'roomSelectChange': this.createNullRoomService() });
}
}
})
.width(30)
.margin({
left: '16vp'
})
.visibility(item.data.faultCode === ZONE_ABNORMAL ? Visibility.Hidden : Visibility.Visible)
} else {
LoadingProgress()
.width(36)
.margin({
left: '16vp'
})
.visibility(item.data.faultCode === ZONE_ABNORMAL ? Visibility.Hidden : Visibility.Visible)
}
}
/**
* 分割线构建
* - param prefix
* - param index
*/
@Builder DividerBuilder() {
Row() {
Divider()
.color($r('sys.color.comp_divider'))
.opacity(0.5)
.margin({
left: $r('sys.float.ohos_id_elements_margin_horizontal_l'),
right: 0
})
}
.margin({ left: '24vp' })
.zIndex(1)
}
@Builder
houseMusicSys() {
if (this.roomListService.length > 0) {
Column(){
if (this.fontSizeScale > 1.75) {
this.BigFontHomeMusicSystemTitleBuilder()
} else {
this.HomeMusicSystemTitleBuilder()
}
this.HomeMusicSystemRoomListBuilder()
}
.onTouch((event?: TouchEvent) => {
event?.stopPropagation();
})
.backgroundColor($r('sys.color.background_primary'))
.borderRadius(this.isPc ? 8 : 20)
}
}
@Builder
deviceAndHouseMusicSys() {
Column({ space: 8 }) {
this.deviceMenu()
if (this.sessionType !== 'voice_call' && this.sessionType !== 'video_call') {
this.houseMusicSys()
}
}
.width(this.isPc ? 326 : 216)
.borderRadius(this.isPc ? 8 : 20)
}
build() {
Column() {
if (this.isDisabledByPickerLimit) {
this.buildDisabledPicker();
} else if (this.customPicker === undefined) {
this.buildDefaultPicker(false);
} else {
this.buildCustomPicker();
}
}.size({width: '100%', height: '100%'})
}
@Builder
iconBuilder(item: AVCastPickerDeviceInfo, isSelected: boolean): void {
if (this.deviceInfoType === 'true') {
SymbolGlyph(!isSelected ? $r(item.deviceIconName) : $r(item.selectedIconName))
.fontSize('24vp')
.fontColor((isSelected && this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ?
[$r('sys.color.comp_background_emphasize')] : [$r('sys.color.icon_primary')])
.renderingStrategy(item.fromCall && item.deviceType === 2 ?
SymbolRenderingStrategy.SINGLE : SymbolRenderingStrategy.MULTIPLE_OPACITY)
} else {
Image(!isSelected ? $r(item.deviceIconName) : $r(item.selectedIconName))
.width(24)
.height(24)
.fillColor((isSelected && this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ?
$r('sys.color.comp_background_emphasize') : $r('sys.color.icon_primary'))
}
}
@Builder
textBuilder(item: AVCastPickerDeviceInfo) {
Text(item.deviceName)
.fontSize($r('sys.float.ohos_id_text_size_body2'))
.fontColor((item.isConnected && !this.houseMusicIsSelect) ?
(this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK ?
$r('sys.color.font_emphasize') : $r('sys.color.font_primary')) :
(this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK ?
$r('sys.color.font_primary') : $r('sys.color.font_secondary')))
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(2)
.wordBreak(WordBreak.BREAK_WORD)
.maxFontScale(this.maxFontSizeScale)
.direction(this.isRTL ? Direction.Rtl : Direction.Ltr)
}
@Builder
subTextBuilder(item: AVCastPickerDeviceInfo) {
Row() {
Text(item.deviceSubName || '')
.fontSize($r('sys.float.ohos_id_text_size_body2'))
.fontColor((item.isConnected && !this.houseMusicIsSelect) ?
(this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK ?
$r('sys.color.font_emphasize') : $r('sys.color.font_primary')) :
(this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK ?
$r('sys.color.font_primary') : $r('sys.color.font_secondary')))
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(1)
.maxFontScale(this.maxFontSizeScale)
.direction(this.isRTL ? Direction.Rtl : Direction.Ltr)
}
.width('100%')
}
@Builder
highQualityIconBuilder(params: HighQualityParams) {
Row() {
Text(params.iconLeft)
.highQualityStyles(Math.min(HIGH_QUALITY_MAX_SCALE, this.maxFontSizeScale))
Text(params.iconRight)
.highQualityStyles(Math.min(HIGH_QUALITY_MAX_SCALE, this.maxFontSizeScale))
.margin({left: 2 * (Math.min(HIGH_QUALITY_MAX_SCALE, this.fontSizeScale))})
}
.direction(Direction.Ltr)
}
@Builder
deviceMenu() {
Column() {
ForEach(this.deviceList, (item: AVCastPickerDeviceInfo, index) => {
Flex({
direction: FlexDirection.Column,
justifyContent: FlexAlign.SpaceBetween,
alignItems: ItemAlign.End
}) {
Flex({
direction: FlexDirection.Row,
justifyContent: FlexAlign.SpaceBetween,
alignItems: ItemAlign.Center
}) {
Row() {
this.iconBuilder(item, false)
Flex({direction: FlexDirection.Column, justifyContent: FlexAlign.Start}) {
this.textBuilder(item)
if (item.fromCall) {
this.subTextBuilder(item)
} else if (item.highQualityParams !== undefined && item.isHiPlay) {
Flex() {
this.highQualityIconBuilder(item.highQualityParams)
}
.borderRadius(4)
.border({
width: Math.min(HIGH_QUALITY_MAX_SCALE, this.fontSizeScale),
color: $r('sys.color.font_secondary')
})
.padding({top: 2.5, right: 4, bottom: 2.5, left: 4})
.margin({top: 4})
.width('auto')
if ((item.isConnected || item.castUid !== 0) &&
item.supportCastMode === HiPlayCastMode.DEVICE_LEVEL) {
Flex({direction:FlexDirection.Row, alignItems:ItemAlign.Center}) {
Row() {
if (item.castMode === HiPlayCastMode.DEVICE_LEVEL) {
SymbolGlyph($r('sys.symbol.speaker_wave_2'))
.fontSize(`16vp`)
.fontColor([$r('sys.color.font_secondary')])
} else {
this.SmallPicIcon(item.bundleInfo?.pixelData)
}
}
.margin({
right: this.isRTL ? 0 : 4,
left: this.isRTL ? 4 : 0
})
.direction(Direction.Ltr)
Row() {
if (item.castMode === HiPlayCastMode.DEVICE_LEVEL) {
Text(this.textParams?.allMediaAudio)
.fontWeight('sys.string.ohos_id_text_font_family_regular')
.fontSize($r('sys.float.ohos_id_text_size_body3'))
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxFontScale(this.maxFontSizeScale)
.wordBreak(WordBreak.BREAK_ALL)
.maxLines(1)
} else {
Text(this.textParams?.playingNow)
.fontWeight('sys.string.ohos_id_text_font_family_regular')
.fontSize($r('sys.float.ohos_id_text_size_body3'))
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxFontScale(this.maxFontSizeScale)
.wordBreak(WordBreak.BREAK_ALL)
.maxLines(1)
}
}
.direction(Direction.Ltr)
if (item.isConnected && !this.isAncoSession) {
if (item.bundleInfo?.isShowBadge) {
Row(){
Badge({
value: '',
style: { badgeSize: 6, badgeColor: $r('sys.color.warning') }
}) {
SymbolGlyph($r('sys.symbol.arrowtriangle_down_fill'))
.fontSize('16vp')
.fontColor([$r('sys.color.font_secondary')])
}
.width(18)
.height(16)
}
.onDisAppear(() => {
if (item.bundleInfo?.isShowBadge && item?.deviceState === 0){
if (this.extensionProxy != null) {
this.extensionProxy.send({'isShowBadge': false});
}
}
})
.margin({left :8, right: 8})
.direction(Direction.Ltr)
} else {
Row() {
SymbolGlyph($r('sys.symbol.arrowtriangle_down_fill'))
.fontSize('16vp')
.fontColor([$r('sys.color.font_secondary')])
}
.margin({left :8, right: 8})
.direction(Direction.Ltr)
}
}
}
.onClick(() => {
if (item.isConnected && !this.isAncoSession) {
this.isDeviceLevel = (item.castMode === HiPlayCastMode.DEVICE_LEVEL)
if (this.extensionProxy != null) {
this.extensionProxy.send({'isShowBadge': false});
}
if (!this.isSubMenuExpanded) {
this.isMenuShow = false;
this.isSubMenuExpanded = true;
}
}
})
.accessibilityLevel('yes')
.accessibilityText(`${this.textParams?.accessCastMode}` +
`${item?.castMode === HiPlayCastMode.DEVICE_LEVEL
? this.textParams?.allMediaAudio
: this.textParams?.accessPlayingNow}` +
`${this.textParams?.accessNewPoint}`)
.padding({top: 2.5, bottom: 2.5})
.margin({top: 4})
.width('auto')
}
}
}
.width(this.isPc ? 254 : 144)
.padding({
left: 8,
top: this.isPc ? 11 : (item.isHiPlay ? 7 : 17),
right: 8,
bottom: this.isPc ? 11 : (item.isHiPlay ? 7 : 17),
})
}
.alignItems(VerticalAlign.Center)
if (item.isConnected && item.selectedIconName !== null && item.selectedIconName !== undefined &&
!this.houseMusicIsSelect) {
Row() {
this.iconBuilder(item, true)
}
.alignItems(VerticalAlign.Center)
}
}
.constraintSize({ minHeight: this.isPc ? 40 : 48 })
.padding({ left: 12, right: 12 })
.onTouch((event) => {
if (event.type === TouchType.Down) {
this.touchMenuItemIndex = index;
} else if (event.type === TouchType.Up) {
this.touchMenuItemIndex = -1;
}
})
.backgroundColor(this.touchMenuItemIndex === index ?
$r('sys.color.interactive_click') : '#00FFFFFF')
.borderRadius(this.touchMenuItemIndex === index ?
(this.isPc ? $r('sys.float.corner_radius_level2') : $r('sys.float.corner_radius_level8')) : 0)
if (!this.isPc && (index != this.deviceList.length - 1)) {
Divider()
.opacity(0.5)
.color($r('sys.color.comp_divider'))
.padding({ right: (this.isRTL ? 44 : 12), left: (this.isRTL ? 12 : 44) })
} else if (this.isPc && (index != this.deviceList.length - 1)) {
Row()
.width('100%')
.height(2)
}
}
.width('100%')
.onClick(() => {
if (this.extensionProxy !== null && this.houseMusicIsSelect) {
this.setAllRoomSelectStatusPending();
const timeId = setTimeout(() => {
this.roomSelectStatusPendingInit();
}, 3000);
if (typeof timeId === 'number') {
this.timeoutIds.push(timeId);
}
this.extensionProxy.send({ 'roomSelectChange': this.createNullRoomService() });
}
if (this.extensionProxy != null && !item.isConnected) {
this.extensionProxy.send({ 'selectedDeviceInfo': item })
}
})
.accessibilityGroup(true)
.accessibilitySelected(item.isConnected)
})
}
.width(this.isPc ? 326 : 216)
.borderRadius(this.isPc ? 8 : 20)
.backgroundColor(this.isShowHomeAudio ? $r('sys.color.background_primary') : '#00000000')
}
@Builder
castModeMenu() {
Column() {
Flex() {
Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
Flex({ alignItems: ItemAlign.Center}){
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center}) {
Text(this.textParams?.allMediaAudio)
.fontWeight('sys.string.ohos_id_text_font_family_medium')
.fontSize($r('sys.float.ohos_id_text_size_body1'))
.width('100%')
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxFontScale(this.maxFontSizeScale)
.wordBreak(WordBreak.BREAK_ALL)
.maxLines(1)
}
Row() {
if (this.isDeviceLevel) {
SymbolGlyph($r('sys.symbol.checkmark'))
.fontSize('24vp')
.fontColor((this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ?
[$r('sys.color.comp_background_emphasize')] : [$r('sys.color.icon_primary')])
}
}
.width(48)
.height(48)
.justifyContent(FlexAlign.End)
}
.margin({ left: 12, right: 12 })
}
.margin({ left: 4, right: 4 })
}
.width(224)
.height(48)
.accessibilityLevel('yes')
.accessibilitySelected(this.isDeviceLevel ? true : false)
.accessibilityRole(AccessibilityRoleType.MENU_ITEM)
.onClick(() => {
this.isDeviceLevel = true
if (this.extensionProxy != null) {
this.extensionProxy.send({'castMode': HiPlayCastMode.DEVICE_LEVEL});
}
if (!this.isMenuShow) {
this.isSubMenuExpanded = false;
this.isMenuShow = true;
}
})
Divider().width(192)
Flex() {
Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems:ItemAlign.Center }) {
Flex({ alignItems:ItemAlign.Center }) {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center}) {
Text(this.textParams?.currentApp)
.fontWeight('sys.string.ohos_id_text_font_family_medium')
.fontSize($r('sys.float.ohos_id_text_size_body1'))
.width('100%')
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxFontScale(this.maxFontSizeScale)
.wordBreak(WordBreak.BREAK_ALL)
.maxLines(1)
}
Row() {
if (!this.isDeviceLevel) {
SymbolGlyph($r('sys.symbol.checkmark'))
.fontSize('24vp')
.fontColor((this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ?
[$r('sys.color.comp_background_emphasize')] : [$r('sys.color.icon_primary')])
}
}
.width(48)
.height(48)
.justifyContent(FlexAlign.End)
}
.margin({ left: 12, right: 12 })
}
.margin({ left: 4, right: 4 })
}
.width(224)
.height(48)
.accessibilityLevel('yes')
.accessibilitySelected(!this.isDeviceLevel ? true : false)
.accessibilityRole(AccessibilityRoleType.MENU_ITEM)
.onClick(() => {
this.isDeviceLevel = false
if (this.extensionProxy != null) {
this.extensionProxy.send({'castMode': HiPlayCastMode.APP_LEVEL});
}
if (!this.isMenuShow) {
this.isSubMenuExpanded = false;
this.isMenuShow = true;
}
})
}
.padding({ top: 4, bottom: 4})
}
@Builder SmallPicIcon(appIcon : image.PixelMap | undefined) {
Column() {
Image(appIcon)
.syncLoad(true)
.size({ width: '100%', height: '100%' })
.backgroundColor('#00ffffff')
.draggable(false)
.interpolation(ImageInterpolation.Medium)
.autoResize(false);
}
.clip(true)
.size({
width: '16vp',
height: '16vp'
})
.backgroundColor('#00ffffff')
.borderRadius($r('sys.float.ohos_id_corner_radius_default_xs'))
}
@Builder
private buildDisabledPicker() {
Column();
}
@Builder
private buildDefaultPicker(isCustomPicker: boolean) {
Button() {
Column() {
UIExtensionComponent(
{
abilityName: 'UIExtAbility',
bundleName: 'com.hmos.mediacontroller',
parameters: {
'normalColor': this.normalColor,
'activeColor': this.activeColor,
'pickerColorMode': this.colorMode,
'avCastPickerStyle': this.pickerStyle,
'ability.want.params.uiExtensionType': 'sysPicker/mediaControl',
'isCustomPicker': isCustomPicker,
'message': this.restartUECMessage,
'currentPickerCount': this.pickerCountOnCreation,
'sessionType': this.sessionType,
}
})
.onRemoteReady((proxy: UIExtensionProxy) => {
console.info(TAG, 'onRemoteReady');
this.extensionProxy = proxy;
})
.onReceive((data) => {
if (data['deviceInfoType'] !== undefined) {
console.info(TAG, `deviceInfoType : ${JSON.stringify(data['deviceInfoType'])}`);
this.deviceInfoType = data['deviceInfoType'] as string;
}
if (data['pickerStyle'] !== undefined) {
console.info(TAG, `picker style : ${JSON.stringify(data['pickerStyle'])}`);
this.pickerStyleFromMediaController = data['pickerStyle'] as AVCastPickerStyle;
}
if (data['deviceList'] !== undefined) {
console.info(TAG, `picker device list : ${JSON.stringify(data['deviceList'])}`);
this.deviceList = JSON.parse(JSON.stringify(data['deviceList']));
if (this.isMenuShow && !this.hasReceivedDeviceList) {
this.hasReceivedDeviceList = true;
}
let hasOnlySpeakerAndEarpiece: boolean = this.deviceList.length === 2 &&
!this.hasExtDevice(this.deviceList);
let hasNoDevices: boolean = this.deviceList === null || this.deviceList.length === 0;
let isCalling: boolean = this.sessionType === 'voice_call' || this.sessionType === 'video_call';
let isExtMenuScene = isCalling && (hasNoDevices || hasOnlySpeakerAndEarpiece);
let isPanelForMedia: boolean = !isCalling &&
(this.pickerStyle === AVCastPickerStyle.STYLE_PANEL &&
this.pickerStyleFromMediaController === AVCastPickerStyle.STYLE_PANEL);
if (isExtMenuScene || isPanelForMedia) {
this.isMenuShow = false;
this.touchMenuItemIndex = -1;
}
}
if (data['fontSizeScale'] !== undefined) {
console.info(TAG, `font size scale : ${JSON.stringify(data['fontSizeScale'])}`);
this.fontSizeScale = data['fontSizeScale'] as number;
}
if (data['state'] !== undefined) {
console.info(TAG, `picker state change : ${JSON.stringify(data['state'])}`);
let isCalling: boolean = (this.sessionType === 'voice_call' || this.sessionType === 'video_call');
let isPanelForMedia: boolean = !isCalling &&
(this.pickerStyle === AVCastPickerStyle.STYLE_PANEL &&
this.pickerStyleFromMediaController === AVCastPickerStyle.STYLE_PANEL);
if (this.onStateChange != null && (isPanelForMedia || this.isWatch())) {
if (parseInt(JSON.stringify(data['state'])) === AVCastPickerState.STATE_APPEARING) {
this.onStateChange(AVCastPickerState.STATE_APPEARING);
} else {
this.onStateChange(AVCastPickerState.STATE_DISAPPEARING);
}
}
}
if (data['sessionType'] !== undefined) {
console.info(TAG, `session type : ${JSON.stringify(data['sessionType'])}`);
this.sessionType = data['sessionType'] as string;
this.refreshShowHomeAudioStatus();
this.refreshHomeMusicSelectStatus();
}
if (data['isShowMenu'] !== undefined) {
console.info(TAG, `isShowMenu : ${JSON.stringify(data['isShowMenu'])}`);
this.isMenuShow = data['isShowMenu'] as boolean;
if (!this.isMenuShow) {
this.touchMenuItemIndex = -1;
}
}
if (data['isSubMenuExpanded'] !== undefined) {
console.info(TAG, `isSubMenuExpanded : ${JSON.stringify(data['isSubMenuExpanded'])}`);
this.isSubMenuExpanded = data['isSubMenuExpanded'] as boolean;
if (!this.isSubMenuExpanded) {
this.touchMenuItemIndex = -1;
}
}
if (data['configurationColorMode'] !== undefined) {
console.info(TAG, `configurationColorMode : ${JSON.stringify(data['configurationColorMode'])}`);
this.configurationColorMode = data['configurationColorMode'] as number;
}
if (data['accessAudioControl'] !== undefined) {
console.info(TAG, `accessAudioControl : ${JSON.stringify(data['accessAudioControl'])}`);
this.accessibilityAudioControlStr = data['accessAudioControl'] as string;
}
if (data['isPc'] !== undefined) {
console.info(TAG, `isPc : ${JSON.stringify(data['isPc'])}`);
this.isPc = data['isPc'] as boolean;
}
if (data['isRTL'] !== undefined) {
console.info(TAG, `isRTL : ${JSON.stringify(data['isRTL'])}`);
this.isRTL = data['isRTL'] as boolean;
}
if (data['maxFontSizeScale'] !== undefined) {
console.info(TAG, `maxFontSizeScale : ${JSON.stringify(data['maxFontSizeScale'])}`);
this.maxFontSizeScale = data['maxFontSizeScale'] as number;
}
if (data['isShowLoadingProgress'] !== undefined) {
console.info(TAG, `isShowLoadingProgress : ${JSON.stringify(data['isShowLoadingProgress'])}`);
this.isShowLoadingProgress = data['isShowLoadingProgress'] as boolean;
}
if (data['textParams'] !== undefined) {
console.info(TAG, `textParams : ${JSON.stringify(data['textParams'])}`);
this.textParams = data['textParams'] as TextParams;
}
if (data['isAncoSession'] !== undefined) {
console.info(TAG, `isAncoSession : ${JSON.stringify(data['isAncoSession'])}`);
this.isAncoSession = data['isAncoSession'] as boolean;
}
if (data['roomList'] !== undefined) {
console.info(TAG, `roomlist : ${JSON.stringify(data['roomList'])}`);
this.roomListService = JSON.parse(JSON.stringify(data['roomList']));
}
if (data['HomeMusicPlayTaskId'] !== undefined) {
console.info(TAG, `playTaskId : ${JSON.stringify(data['HomeMusicPlayTaskId'])}`);
this.playTaskIdStr = data['HomeMusicPlayTaskId'] as string;
}
if (data['keyInputEven'] !== undefined) {
console.info(TAG, `keyInputEven : ${JSON.stringify(data['keyInputEven'])}`);
let keyInputOpt: number = data['keyInputEven'] as number;
this.syncToRoomVolume(keyInputOpt);
this.sendAllRoomVolumeToController();
this.roomMaxVolume = this.findRoomMaxVolume();
this.roomMaxVolumeChange();
}
if (data['houseMusicTitleGroup'] !== undefined) {
console.info(TAG, `houseMusicTitleGroup : ${JSON.stringify(data['houseMusicTitleGroup'])}`);
let houseMusicTitleGroup: string[] = JSON.parse(JSON.stringify(data['houseMusicTitleGroup']));
this.houseMusicTitle = houseMusicTitleGroup[0];
this.houseMusicPlay = houseMusicTitleGroup[1];
this.houseMusicPlayCancel = houseMusicTitleGroup[2];
}
if (data['HomeMusicScanStatus'] !== undefined) {
console.info(TAG, `HomeMusicScanStatus : ${JSON.stringify(data['HomeMusicScanStatus'])}`);
this.scanStatus = data['HomeMusicScanStatus'] as number;
}
if (data['deviceModelType'] !== undefined) {
console.info(TAG, `deviceModelType : ${JSON.stringify(data['deviceModelType'])}`);
this.deviceModelType = data['deviceModelType'] as string;
}
if (data['isHdsThin'] !== undefined) {
console.info(TAG, `isHdsThin : ${JSON.stringify(data['isHdsThin'])}`);
this.isHdsThin = data['isHdsThin'] as boolean;
}
})
.size({ width: '100%', height: '100%' })
.bindMenu(
this.isMenuShow && this.hasReceivedDeviceList,
this.deviceAndHouseMusicSys(),
{
backgroundBlurStyle: ((this.isShowHomeAudio || materialUtil.isSupportHds()) ?
BlurStyle.NONE : BlurStyle.BACKGROUND_ULTRA_THICK),
backgroundColor: (this.isShowHomeAudio ? '#00000000': materialUtil.isSupportHds() ? undefined :
(this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ?
$r('sys.color.background_primary') : '#00FFFFFF'),
systemMaterial: this.isShowHomeAudio ? undefined : materialUtil.getMaterialStroke(
(this.configurationColorMode !== ConfigurationColorMode.COLOR_MODE_DARK) ? undefined : true
),
placement: Placement.BottomRight,
showInSubWindow: false,
enableHoverMode: true,
onDisappear: () => {
this.isMenuShow = false;
this.hasReceivedDeviceList = false;
this.touchMenuItemIndex = -1;
this.menuShowStateCallback(this.isMenuShow);
if (this.extensionProxy !== null) {
this.extensionProxy.send({ 'clearAVPickerRoomList': 1 });
}
},
onAppear: () => {
if (this.extensionProxy != null && this.pickerClickTime !== -1) {
this.extensionProxy.send({ 'timeCost': new Date().getTime() - this.pickerClickTime });
this.pickerClickTime = -1;
}
if (this.extensionProxy !== null && this.roomListService.length > 0) {
this.extensionProxy.send({ 'getHomeMusicInfo': 1 });
}
this.menuShowStateCallback(this.isMenuShow);
this.refreshShowHomeAudioStatus();
}
})
.onRelease((releaseCode) => {
console.error(TAG, `onRelease code ${releaseCode}`);
if (releaseCode === 1) {
this.needToRestart = true;
}
})
.onError(() => {
console.error(TAG, 'onError ready to restart');
this.needToRestart = true;
})
.focusable(false)
}
.bindMenu (
this.isSubMenuExpanded,
this.castModeMenu(),
{
placement: Placement.BottomRight,
showInSubWindow: false,
enableHoverMode: true,
onDisappear: () => {
this.isSubMenuExpanded = false;
this.touchMenuItemIndex = -1;
},
onAppear: () => {
if (this.extensionProxy != null && this.pickerClickTime !== -1) {
this.extensionProxy.send({ 'timeCost': new Date().getTime() - this.pickerClickTime });
this.pickerClickTime = -1;
}
},
systemMaterial: materialUtil.getMaterialStroke(),
})
.accessibilityLevel('no-hide-descendants')
.size({ width: '100%', height: '100%' })
}
.hoverEffect(HoverEffect.None)
.backgroundColor('#00000000')
.stateEffect(false)
.size({ width: '100%', height: '100%' })
.accessibilityLevel('yes')
.accessibilityText(`${this.accessibilityAudioControlStr}${this.textParams?.accessNewPoint}`)
.onClick(() => {
if (this.needToRestart) {
this.needToRestart = false;
this.restartUECMessage += 1;
return;
}
let hasOnlySpeakerAndEarpiece: boolean = this.deviceList.length === 2 && !this.hasExtDevice(this.deviceList);
let hasNoDevices: boolean = this.deviceList === null || this.deviceList.length === 0;
let isCalling: boolean = this.sessionType === 'voice_call' || this.sessionType === 'video_call';
let isExtMenuScene: boolean = isCalling && (hasNoDevices || hasOnlySpeakerAndEarpiece);
let isPanelForMedia: boolean = !isCalling &&
(this.pickerStyle === AVCastPickerStyle.STYLE_PANEL &&
this.pickerStyleFromMediaController === AVCastPickerStyle.STYLE_PANEL);
if (this.isWatch()) {
if (this.extensionProxy != null) {
this.extensionProxy.send({'clickEvent': true});
}
} else if (isExtMenuScene || isPanelForMedia) {
this.isMenuShow = false;
this.touchMenuItemIndex = -1;
if (this.extensionProxy != null) {
this.extensionProxy.send({'clickEvent': true});
}
} else {
this.isMenuShow = !this.isMenuShow;
if (!this.isMenuShow && !this.hasReceivedDeviceList) {
console.info(TAG, 'hasReceivedDeviceList empty on previous isMenuShow');
this.isMenuShow = true;
}
if (this.isMenuShow) {
this.refreshShowHomeAudioStatus();
this.pickerClickTime = new Date().getTime();
} else {
this.touchMenuItemIndex = -1;
}
}
})
.onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => {
console.info(TAG, `onVisibleAreaChange visible: ${isVisible}, cRatio: ${currentRatio}, dMType: ${this.deviceModelType}, restart: ${this.needToRestart}`);
if (this.isWatch() && this.needToRestart && isVisible && currentRatio >= 1.0) {
console.info(TAG, `restart uix ${this.restartUECMessage}`);
this.needToRestart = false;
this.restartUECMessage += 1;
}
})
}
private isWatch() {
return this.deviceModelType === 'wearable';
}
private hasExtDevice(allDevice: Array<AVCastPickerDeviceInfo>): boolean {
for (let i = 0; i < allDevice.length; i++) {
let isEarpieceOrSpeaker: boolean = (allDevice[i].deviceType === 1 || allDevice[i].deviceType === 2) &&
allDevice[i].networkId === 'LocalDevice';
if (!isEarpieceOrSpeaker) {
return true;
}
}
return false;
}
private menuShowStateCallback(isMenuShow: boolean): void {
if (this.onStateChange != null &&
(this.pickerStyle === AVCastPickerStyle.STYLE_MENU ||
this.pickerStyleFromMediaController === AVCastPickerStyle.STYLE_MENU)) {
let menuShowState: AVCastPickerState = isMenuShow ?
AVCastPickerState.STATE_APPEARING : AVCastPickerState.STATE_DISAPPEARING;
this.onStateChange(menuShowState);
}
}
private getLoadingColor() {
console.info(TAG, `loading activeColor: ${this.activeColor}`);
if (this.activeColor === 'activeLightColor') {
return '#99FFFFFF';
}
if (this.activeColor === 'activeDarkColor') {
return '#99000000';
}
return $r('sys.color.icon_secondary');
}
@Builder
private buildCustomPicker() {
Stack({ alignContent: Alignment.Center}) {
Column() {
if (this.isShowLoadingProgress) {
LoadingProgress()
.color(this.activeColor === 'liveCardLoadingColor' || this.isHdsThin ? '#FFFFFFFF' : $r('sys.color.icon_secondary'))
.width('20vp')
.height('20vp')
} else {
this.customPicker();
}
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.size({ width: '100%', height: '100%' })
.zIndex(0)
Column() {
this.buildDefaultPicker(true);
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.size({ width: '100%', height: '100%' })
.zIndex(1)
}
.size({ width: '100%', height: '100%' })
}
}
@Extend(Text) function highQualityStyles(maxScale: number) {
.fontFamily('HarmonyOS Sans SC 2025')
.fontSize(10)
.fontWeight(FontWeight.Medium)
.fontColor($r('sys.color.font_secondary'))
.maxFontScale(maxScale)
}