1/** 2 * Copyright (c) 2022 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 16import Method from '../utils/Method'; 17import FuncBtn from './FuncBtn'; 18import CallStateConst from '../constant/CallStateConst'; 19import CallServiceProxy from '../../model/CallServiceProxy'; 20import Clone from '../utils/Clone'; 21import BtnGroupConfig from '../configs/BtnGroupConfig'; 22import LogUtils from '../utils/LogUtils'; 23import screenLock from '@ohos.screenLock'; 24import DefaultCallData from '../struct/TypeUtils' 25import CallListStruct from '../struct/CallListStruct' 26import FunctonBtnVM from '../../viewmodel/FunctonBtnVIewModel'; 27 28const TAG = 'FuncBtnGroup'; 29 30class BtnStruct { 31 public type 32 public iconDisableUrl 33 public iconDefaultUrl 34 public iconActiveUrl 35 public isDisable 36 public isActive 37 public iconText 38} 39const textMap = 40 { 41 'record': $r('app.string.recording'), 42 'keep': $r('app.string.keep'), 43 'add': $r('app.string.addCall'), 44 'video': $r('app.string.videoCall'), 45 'mute': $r('app.string.mute'), 46 'contact': $r('app.string.contactPerson'), 47 'exchange': $r('app.string.exchange'), 48 'merge': $r('app.string.mergeCall'), 49 }; 50 51@Component 52export default struct FuncBtnGroup { 53 @Link @Watch('updateBtnList') callData: DefaultCallData; 54 @Link @Watch('updateBtnList') callList: Array<CallListStruct>; 55 @State count: number = 0; 56 @State btnList: Array<BtnStruct> = []; 57 @State m: number = 0; 58 @State n: number = 0; 59 @State oldCallState: number = CallStateConst.CALL_STATUS_IDLE; 60 @State mFunctonBtnVM: FunctonBtnVM = FunctonBtnVM.getInstance(); 61 private mCallServiceProxy: CallServiceProxy; 62 private mBtnGroupConfig = BtnGroupConfig; 63 private timer: number = null; 64 private mClone: Clone; 65 private btnListCall; 66 private btnListDialing; 67 private btnListMulti; 68 69 aboutToAppear() { 70 this.mClone = Clone.getInstance() 71 this.mCallServiceProxy = CallServiceProxy.getInstance(); 72 this.mBtnGroupConfig.btnGroupList.forEach((v) => { 73 v.iconText = textMap[v.type]; 74 }); 75 this.mBtnGroupConfig.threePartyList.forEach((v) => { 76 v.iconText = textMap[v.type]; 77 }); 78 this.btnListCall = this.mClone.clone(this.mBtnGroupConfig.btnGroupList); 79 this.getBtnListCall(); 80 this.btnList = this.btnListCall; 81 this.getBtnListMulti(); 82 this.updateBtnList(); 83 LogUtils.i(TAG, 'aboutToAppear :'); 84 } 85 86 /** 87 * Switching BtnList Based on CallStatus 88 */ 89 updateBtnList() { 90 if (this.callData.callState === CallStateConst.CALL_STATUS_DIALING || 91 this.callData.callState === CallStateConst.CALL_STATUS_ALERTING) { 92 this.btnList = this.btnListDialing; 93 } else if (this.callList.length > 1) { 94 this.btnList = this.btnListMulti; 95 } else { 96 this.btnList = this.btnListCall; 97 } 98 this.onCallStateChange(this.callData.callState); 99 } 100 101 /** 102 * Get BtnList Based on CallStatus 103 */ 104 getBtnListCall() { 105 this.btnListDialing = this.mClone.clone(this.mBtnGroupConfig.btnGroupList); 106 this.btnListDialing[1].isDisable = true 107 this.btnListDialing[2].isDisable = true 108 } 109 110 /** 111 * Get BtnList for Multi Calls 112 */ 113 getBtnListMulti() { 114 this.btnListMulti = this.mClone.clone(this.mBtnGroupConfig.btnGroupList); 115 this.btnListMulti[1] = this.mClone.clone(this.mBtnGroupConfig.threePartyList[0]); 116 this.btnListMulti[2] = this.mClone.clone(this.mBtnGroupConfig.threePartyList[1]); 117 } 118 119 /** 120 * update state of group buttons 121 * 122 * @param {Object} callData - call data 123 */ 124 onCallStateChange(newVal) { 125 const btnName = ['video', 'record', 'add', 'contact', 'merge']; 126 if (newVal === CallStateConst.CALL_STATUS_ACTIVE || newVal === CallStateConst.CALL_STATUS_HOLDING) { 127 this.btnList.forEach((item) => { 128 if (!Method.includes(btnName, (item.type))) { 129 item.isDisable = false; 130 item.isActive = false; 131 } 132 }); 133 if (newVal === CallStateConst.CALL_STATUS_HOLDING) { 134 this.btnList[1].isActive = true; 135 this.btnList[4].isDisable = true; 136 } 137 } else { 138 this.btnList.forEach((item) => { 139 if (item.type === 'contact') { 140 item.isDisable = false; 141 } 142 }); 143 } 144 } 145 146 /** 147 * Display the buttons of the button group 148 * 149 * @param {Object} obj - object 150 */ 151 btnClick(obj) { 152 LogUtils.i(TAG, 'btnClick get icon type : ' + JSON.stringify(obj)); 153 const btnName = ['record', 'video', 'mute']; 154 const type = obj.type; 155 const { callId } = this.callData; 156 if (Method.includes(btnName, type)) { 157 this.btnList.forEach((item) => { 158 if (item.type === type) { 159 item.isActive = !item.isActive; 160 } 161 }); 162 if (type === 'record') { 163 if (this.btnList[0].isActive) { 164 } else { 165 this.count = 0; 166 clearInterval(this.timer); 167 this.btnList[0].iconText = $r('app.string.recording'); 168 } 169 } 170 } 171 172 switch (type) { 173 case 'record': 174 break; 175 case 'keep': 176 this.keepHandle('keep'); 177 break; 178 case 'exchange': 179 LogUtils.i(TAG, 'exchange button clicked, callid: ' + callId); 180 this.callList.forEach((item) => { 181 if (item.callState === CallStateConst.CALL_STATUS_HOLDING) { 182 this.mCallServiceProxy.unHoldCall(item.callId); 183 return; 184 } 185 }); 186 break; 187 case 'add': 188 this.startContact('page_flag_dialer') 189 break; 190 case 'video': 191 break; 192 case 'mute': 193 this.muteHandle('mute'); 194 break; 195 case 'contact': 196 this.startContact('page_flag_choose_contacts') 197 break; 198 case 'merge': 199 this.mCallServiceProxy.combineConference(callId); 200 break; 201 default: 202 break; 203 } 204 } 205 206 startContact(pageFlag) { 207 if (screenLock.isLocked()) { 208 screenLock.unlock((err, isUnlock) => { 209 if (isUnlock) { 210 this.startContactAbility(pageFlag) 211 } else { 212 LogUtils.i(TAG, 'startContact screen isLocked') 213 } 214 }); 215 } else { 216 this.startContactAbility(pageFlag) 217 } 218 } 219 220 startContactAbility(pageFlag) { 221 globalThis.calluiAbilityContext?.startAbility({ 222 bundleName: 'com.ohos.contacts', 223 abilityName: 'com.ohos.contacts.MainAbility', 224 parameters: { 225 pageFlag: pageFlag 226 } 227 }); 228 } 229 230 /** 231 * Call hold interface 232 * 233 * @param {string} type - Click the hold button 234 */ 235 keepHandle(type) { 236 const awaitIsActive = this.btnList.find((v) => v.type === type).isActive; 237 LogUtils.i(TAG, 'keep handle awaitIsActive : ' + !awaitIsActive); 238 !awaitIsActive ? this.mCallServiceProxy.holdCall(this.callData.callId) : 239 this.mCallServiceProxy.unHoldCall(this.callData.callId); 240 } 241 242 /** 243 * Call hold mute 244 * 245 * @param {string} type - Click the hold button 246 */ 247 muteHandle(type) { 248 const awaitIsActive = this.btnList.find((v) => v.type === type).isActive; 249 LogUtils.i(TAG, 'mute Handle awaitIsActive : ' + awaitIsActive); 250 awaitIsActive ? this.mCallServiceProxy.setMuted() : this.mCallServiceProxy.cancelMuted(); 251 } 252 253 /** 254 * Clear timer 255 */ 256 onDestroy() { 257 LogUtils.i(TAG, 'onDestroy'); 258 this.timer && clearInterval(this.timer); 259 } 260 261 build() { 262 GridRow({ columns: { sm: 4, md: 8, lg: 12 }, gutter: 0 }) { 263 GridCol({ span: { sm: 4, md: 6, lg: 6 }, offset: { md: 1, lg: 3 } }) { 264 Grid() { 265 ForEach(this.btnList, (item) => { 266 GridItem() { 267 FuncBtn({ 268 btnType: item.type, 269 isDisable: item.isDisable, 270 isActive: item.isActive, 271 iconText: item.iconText, 272 iconDisableUrl: item.iconDisableUrl, 273 iconDefaultUrl: item.iconDefaultUrl, 274 iconActiveUrl: item.iconActiveUrl, 275 btnClick: () => { 276 this.btnClick(item) 277 } 278 }) 279 } 280 .height(51.5) 281 }) 282 } 283 .columnsGap(24) 284 .rowsGap(29.5) 285 .height(132.5) 286 .columnsTemplate('1fr 1fr 1fr') 287 .rowsTemplate('1fr 1fr') 288 } 289 } 290 .margin(24) 291 } 292}