1/* 2 * Copyright (c) 2021-2023 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 { backBar } from '../common/components/backBar'; 17import { alphabetIndexerComponent } from '../common/components/alphabeticalIndex'; 18import { textInput } from '../common/components/search'; 19import router from '@ohos.router'; 20import bundleManager from '@ohos.bundle.bundleManager'; 21import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; 22import { BusinessError } from '@ohos.base'; 23import audio from '@ohos.multimedia.audio' 24import camera from '@ohos.multimedia.camera' 25import { CustomContentDialog } from '@ohos.arkui.advanced.Dialog'; 26import { Log, verifyAccessToken, indexValue, sortByName } from '../common/utils/utils'; 27import { ApplicationObj, GroupInfo, RouterParams1, PermissionApplications, AppInfo } from '../common/model/typedef'; 28import { GlobalContext } from '../common/utils/globalContext'; 29import Constants from '../common/utils/constant'; 30import { polymorphismGroup, globalGroup, groups } from '../common/model/permissionGroup'; 31 32const CAMERA = 'CAMERA'; 33const MICROPHONE = 'MICROPHONE'; 34const FUZZY_LOCATION_PERMISSION = 'ohos.permission.APPROXIMATELY_LOCATION'; 35const PRECISE_LOCATION_PERMISSION = 'ohos.permission.LOCATION'; 36const BACKGROUND_LOCATION_PERMISSION = 'ohos.permission.LOCATION_IN_BACKGROUND'; 37const DOWNLOAD_PERMISSION = 'ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY'; 38const DESKTOP_PERMISSION = 'ohos.permission.READ_WRITE_DESKTOP_DIRECTORY'; 39const DOCUMENTS_PERMISSION = 'ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY'; 40const locationStatus: Resource[] = [ 41 $r('app.string.always_allow'), 42 $r('app.string.ban'), 43 $r('app.string.per_inquiry'), 44 $r('app.string.allowed_only_during_use') 45]; 46let globalIsOn: boolean = (router.getParams() as RouterParams1).globalIsOn; // return title name 47 48@Entry 49@Component 50struct locationInfoPage { 51 private backTitle: ResourceStr = (router.getParams() as RouterParams1).backTitle; 52 private list: PermissionApplications[] = (router.getParams() as RouterParams1).list; 53 @State currentGroup: string = GlobalContext.load('currentPermissionGroup'); 54 @State polymorphismIsOn: Array<number> = []; 55 @State folderStatusArray: Array<Array<boolean>> = [[]]; 56 57 build() { 58 GridRow({ gutter: Constants.GUTTER, columns: { 59 xs: Constants.XS_COLUMNS, sm: Constants.SM_COLUMNS, md: Constants.MD_COLUMNS, lg: Constants.LG_COLUMNS } }) { 60 GridCol({ 61 span: { xs: Constants.XS_SPAN, sm: Constants.SM_SPAN, md: Constants.MD_SPAN, lg: Constants.LG_SPAN }, 62 offset: { xs: Constants.XS_OFFSET, sm: Constants.SM_OFFSET, md: Constants.MD_OFFSET, lg: Constants.LG_OFFSET } 63 }) { 64 Row() { 65 Column() { 66 Row() { 67 backBar({ title: JSON.stringify(this.backTitle), recordable: false }) 68 } 69 Row() { 70 Column() { 71 applicationItem({ polymorphismIsOn: $polymorphismIsOn, folderStatusArray: $folderStatusArray }) 72 73 }.width(Constants.FULL_WIDTH) 74 } 75 .layoutWeight(Constants.LAYOUT_WEIGHT) 76 } 77 } 78 .height(Constants.FULL_HEIGHT) 79 .width(Constants.FULL_WIDTH) 80 .backgroundColor($r('sys.color.background_secondary')) 81 } 82 }.backgroundColor($r('sys.color.background_secondary')) 83 } 84 85 onPageShow() { 86 if (polymorphismGroup.indexOf(this.currentGroup) !== -1) { 87 let bundleNames: string[] = []; 88 this.list.forEach(permissionManager => { 89 permissionManager.bundleNames.forEach(bundleName => { 90 if (bundleNames.indexOf(bundleName) == -1) { 91 bundleNames.push(bundleName); 92 } 93 }) 94 }) 95 96 bundleNames.forEach((bundleName, index) => { 97 bundleManager.getBundleInfo( 98 bundleName, 99 bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION | 100 bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION 101 ).then(res => { 102 this.getGroupStatus(res, index); 103 }).catch((error: BusinessError) => { 104 Log.error(bundleName + 'onPageShow getBundleInfo failed, cause: ' + JSON.stringify(error)); 105 }) 106 }) 107 } 108 } 109 110 getGroupStatus(res: bundleManager.BundleInfo, index: number) { 111 this.polymorphismIsOn[index] = Constants.PERMISSION_BAN; 112 this.folderStatusArray[index] = [false, false, false]; 113 let reqPermissions: string[] = []; 114 res.reqPermissionDetails.forEach(item => { 115 reqPermissions.push(item.name); 116 }) 117 let acManager = abilityAccessCtrl.createAtManager(); 118 if (this.currentGroup === 'LOCATION' && reqPermissions.includes(FUZZY_LOCATION_PERMISSION)) { 119 try { 120 let fuzzyState = acManager.verifyAccessTokenSync(res.appInfo.accessTokenId, FUZZY_LOCATION_PERMISSION); 121 fuzzyState === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED ? 122 this.polymorphismIsOn[index] = Constants.PERMISSION_ALLOWED_ONLY_DURING_USE : null; 123 let backgroundState = 124 acManager.verifyAccessTokenSync(res.appInfo.accessTokenId, BACKGROUND_LOCATION_PERMISSION); 125 backgroundState === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED ? 126 this.polymorphismIsOn[index] = Constants.PERMISSION_ALLOW : null; 127 acManager.getPermissionFlags(res.appInfo.accessTokenId, FUZZY_LOCATION_PERMISSION ).then(flag => { 128 flag === Constants.PERMISSION_ALLOW_THIS_TIME ? 129 this.polymorphismIsOn[index] = Constants.PERMISSION_ONLY_THIS_TIME : null; 130 }) 131 } catch (err) { 132 Log.error('change location status error: ' + JSON.stringify(err)); 133 } 134 } 135 if (this.currentGroup === 'FOLDER') { 136 for (let j = 0; j < this.list.length; j++) { 137 if (reqPermissions.indexOf(this.list[j].permission) == -1) { 138 continue; 139 } 140 let access = acManager.verifyAccessTokenSync(res.appInfo.accessTokenId, this.list[j].permission); 141 if (Number(access) === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) { 142 this.updateFolderStatus(index, j); 143 } 144 } 145 } 146 } 147 148 updateFolderStatus(index: number, idx: number) { 149 switch (this.list[idx].permission) { 150 case DOWNLOAD_PERMISSION: 151 this.folderStatusArray[index][0] = true; 152 break; 153 case DESKTOP_PERMISSION: 154 this.folderStatusArray[index][1] = true; 155 break; 156 case DOCUMENTS_PERMISSION: 157 this.folderStatusArray[index][2] = true; 158 break; 159 } 160 } 161} 162 163@Component 164struct applicationItem { 165 private backTitle: ResourceStr = (router.getParams() as RouterParams1).backTitle; 166 private list: PermissionApplications[] = (router.getParams() as RouterParams1).list; 167 @State permissionNum: number = Constants.PERMISSION_NUM; // permission num 168 @State toggleIsOn: boolean[] = []; // toggle switch state array 169 @State isRisk: boolean[] = []; 170 @State isFirst: boolean[] = []; 171 @State applicationList: ApplicationObj[] = []; // application info array 172 @State searchResult: boolean = true; // search results 173 @Link polymorphismIsOn: Array<number>; 174 @Link folderStatusArray: Array<Array<boolean>>; 175 @State globalIsOn: boolean = true; 176 @State selectedIndex: number = 0; 177 @State isTouch: string = ''; 178 @State groupInfo: GroupInfo = new GroupInfo('', '', '', '', [], '', [], false); 179 @State currentGroup: string = GlobalContext.load('currentPermissionGroup'); 180 @State isMuteSupported: boolean = GlobalContext.load('isMuteSupported'); 181 @State allBundleInfo: AppInfo[] = GlobalContext.load('allBundleInfo'); 182 scroller: Scroller = new Scroller(); 183 184 dialogController: CustomDialogController | null = new CustomDialogController({ 185 builder: CustomContentDialog({ 186 contentBuilder: () => { 187 this.buildContent(); 188 }, 189 contentAreaPadding: { left: Constants.PADDING_24, right: Constants.PADDING_24 }, 190 buttons: [ 191 { 192 value: $r('app.string.cancel'), 193 buttonStyle: ButtonStyleMode.TEXTUAL, 194 action: () => { 195 Log.info('global cancel'); 196 this.dialogController?.close(); 197 } 198 }, 199 { 200 value: $r('app.string.close'), 201 buttonStyle: ButtonStyleMode.TEXTUAL, 202 action: () => { 203 Log.info('global accept'); 204 if (this.currentGroup == MICROPHONE) { 205 let audioManager = audio.getAudioManager(); 206 let audioVolumeManager = audioManager.getVolumeManager(); 207 audioVolumeManager.getVolumeGroupManager(audio.DEFAULT_VOLUME_GROUP_ID).then(audioVolumeGroupManager => { 208 audioVolumeGroupManager.setMicMutePersistent(true, audio.PolicyType.PRIVACY).then(() => { 209 this.dialogController?.close(); 210 }) 211 }) 212 } else { 213 let cameraManager = camera.getCameraManager(GlobalContext.load('context')); 214 cameraManager.muteCameraPersistent(true, camera.PolicyType.PRIVACY); 215 this.dialogController?.close(); 216 } 217 } 218 } 219 ], 220 }), 221 autoCancel: false 222 }); 223 224 @Builder 225 buildContent(): void { 226 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 227 Column() { 228 Text(this.currentGroup == 'CAMERA' ? $r('app.string.close_camera') : $r('app.string.close_microphone')) 229 .fontSize(Constants.TEXT_BIG_FONT_SIZE) 230 .fontColor($r('sys.color.font_primary')) 231 .fontWeight(FontWeight.Medium) 232 .lineHeight(Constants.TEXT_BIG_LINE_HEIGHT) 233 .width(Constants.FULL_WIDTH) 234 .padding({ top: Constants.PADDING_14, bottom: Constants.PADDING_14 }) 235 Text( 236 this.currentGroup == 'CAMERA' ? 237 $r('app.string.close_camera_desc') : 238 $r('app.string.close_microphone_desc') 239 ) 240 .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE) 241 .fontColor($r('sys.color.font_primary')) 242 .lineHeight(Constants.TEXT_LINE_HEIGHT) 243 } 244 .clip(true) 245 } 246 } 247 248 @Builder ListItemLayout(item: ApplicationObj) { 249 ListItem() { 250 Row() { 251 Column() { 252 Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { 253 Row() { 254 Image(item.icon) 255 .objectFit(ImageFit.Contain) 256 .width(Constants.AUTHORITY_IMAGE_WIDTH) 257 .height(Constants.AUTHORITY_IMAGE_HEIGHT) 258 .draggable(false) 259 .margin({ right: Constants.AUTHORITY_IMAGE_MARGIN_RIGHT }) 260 Column() { 261 Text(item.label) 262 .width(Constants.MAXIMUM_HEADER_WIDTH) 263 .maxLines(Constants.MAXIMUM_HEADER_LINES) 264 .textOverflow({ overflow: TextOverflow.Ellipsis }) 265 .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE) 266 .fontWeight(FontWeight.Medium) 267 .fontColor($r('sys.color.font_primary')) 268 if (this.isRisk[item.index]) { 269 Text($r('app.string.risk_warning')) 270 .fontSize(Constants.TEXT_SMALL_FONT_SIZE) 271 .fontColor($r('sys.color.font_secondary')) 272 } 273 }.flexGrow(Constants.FLEX_GROW) 274 .alignItems(HorizontalAlign.Start) 275 if (polymorphismGroup.indexOf(this.currentGroup) == -1) { 276 Toggle({ type: ToggleType.Switch, isOn: this.toggleIsOn[item.index] }) 277 .selectedColor($r('sys.color.icon_emphasize')) 278 .switchPointColor($r('sys.color.comp_background_primary_contrary')) 279 .padding({ right: 0 }) 280 .width(Constants.AUTHORITY_TOGGLE_WIDTH) 281 .height(Constants.AUTHORITY_TOGGLE_HEIGHT) 282 .onChange((isOn: boolean) => { 283 if (item.permission === undefined) { 284 return; 285 } 286 if (this.isFirst[item.index] && isOn) { 287 this.isFirst[item.index] = false; 288 return; 289 } 290 this.isFirst[item.index] = false; 291 let _this = this; 292 if (isOn) { 293 let promises = this.list.map(it => new Promise<number>((resolve) => { 294 _this.grantUserGrantedPermission(item.accessTokenId, it.permission, resolve); 295 })); 296 Promise.all(promises).then(() => { 297 _this.toggleIsOn[item.index] = true; 298 let num = _this.toggleIsOn.filter(item => item === true).length; 299 _this.permissionNum = num; 300 }); 301 } else { 302 let promises = this.list.map(it => new Promise<number>((resolve) => { 303 _this.revokeUserGrantedPermission(item.accessTokenId, it.permission, resolve); 304 })); 305 Promise.all(promises).then(() => { 306 _this.toggleIsOn[item.index] = false; 307 let num = _this.toggleIsOn.filter(item => item === true).length; 308 _this.permissionNum = num; 309 }); 310 } 311 }) 312 } else { 313 if (this.currentGroup === 'FOLDER') { 314 Text() { 315 if (this.folderStatusArray[item.index].includes(true)) { 316 ForEach(this.folderStatusArray[item.index], (status: boolean, index) =>{ 317 if (status) { 318 if (index !== this.folderStatusArray[item.index].indexOf(true)) { 319 Span($r('app.string.separator')) 320 } 321 Span(index === 0 ? $r('app.string.Download') : index === 1 ? $r('app.string.Desktop') : $r('app.string.Document')) 322 } 323 }) 324 } else { 325 Span($r('app.string.ban')) 326 } 327 } 328 .fontSize(Constants.TEXT_SMALL_FONT_SIZE) 329 .fontColor($r('sys.color.font_secondary')) 330 .margin({ right: Constants.AUTHORITY_IMAGE_MARGIN_RIGHT }) 331 } else { 332 Text(locationStatus[this.polymorphismIsOn[item.index]]) 333 .fontSize(Constants.TEXT_SMALL_FONT_SIZE) 334 .fontColor($r('sys.color.font_secondary')) 335 .margin({ right: Constants.AUTHORITY_IMAGE_MARGIN_RIGHT }) 336 } 337 SymbolGlyph($r('sys.symbol.chevron_forward')) 338 .width(Constants.IMAGE_WIDTH) 339 .height(Constants.IMAGE_HEIGHT) 340 .fontSize(Constants.FONT_SIZE_18_vp) 341 .fontColor([$r('sys.color.icon_tertiary')]) 342 .fontWeight(FontWeight.Medium) 343 } 344 } 345 .width(Constants.FULL_WIDTH) 346 .height(Constants.AUTHORITY_ROW_HEIGHT) 347 .constraintSize({ minHeight: Constants.AUTHORITY_CONSTRAINTSIZE_MINHEIGHT }) 348 } 349 }.onClick(() => { 350 if (polymorphismGroup.indexOf(this.currentGroup) !== -1) { 351 let permissions: string[] = []; 352 this.list.forEach(data => { 353 if (data.bundleNames.includes(item.bundleName as string)) { 354 permissions.push(data.permission); 355 } 356 }) 357 this.allBundleInfo.forEach(bundleInfo => { 358 if (bundleInfo.bundleName === item.bundleName) { 359 GlobalContext.store('applicationInfo', bundleInfo); 360 } 361 }) 362 GlobalContext.store('folderStatus', this.folderStatusArray[item.index]); 363 GlobalContext.store('locationStatus', this.polymorphismIsOn[item.index]); 364 router.pushUrl({ 365 url: 'pages/application-tertiary', 366 params: { 367 bundleName: item.bundleName, 368 backTitle: this.backTitle, 369 permission: permissions, 370 status: Constants.PERMISSION_BAN, 371 tokenId: item.accessTokenId 372 } 373 }); 374 } 375 }) 376 } 377 }.padding({ left: $r('sys.float.ohos_id_card_margin_start'), right: $r('sys.float.ohos_id_card_margin_end') }) 378 .enabled(!this.isRisk[item.index]) 379 .opacity(this.isRisk[item.index] ? $r('sys.float.ohos_id_alpha_disabled') : 1) 380 .borderRadius($r('sys.float.ohos_id_corner_radius_default_l')) 381 .linearGradient((this.isTouch === item.bundleName) ? { 382 angle: 90, 383 direction: GradientDirection.Right, 384 colors: [['#DCEAF9', 0.0], ['#FAFAFA', 1.0]] 385 } : { 386 angle: 90, 387 direction: GradientDirection.Right, 388 colors: [[$r('sys.color.comp_background_list_card'), 1], [$r('sys.color.comp_background_list_card'), 1]] 389 }) 390 .onTouch(event => { 391 if (event === undefined) { 392 return; 393 } 394 if (event.type === TouchType.Down && polymorphismGroup.indexOf(this.currentGroup) !== -1) { 395 this.isTouch = item.bundleName ? item.bundleName : ''; 396 } 397 if (event.type === TouchType.Up) { 398 this.isTouch = ''; 399 } 400 }) 401 } 402 403 /** 404 * Take the total number of access applications 405 */ 406 getGrantApplicationNumber() { 407 if (polymorphismGroup.indexOf(this.currentGroup) !== -1) { 408 if (this.currentGroup === 'FOLDER') { 409 let sum = this.folderStatusArray.filter(item => item.includes(true)); 410 return sum.length; 411 } else { 412 let sum = this.polymorphismIsOn.filter( 413 item => item !== Constants.PERMISSION_BAN && item !== Constants.PERMISSION_ONLY_THIS_TIME 414 ); 415 return sum.length; 416 } 417 } else { 418 return this.permissionNum; 419 } 420 } 421 422 /** 423 * Grant permissions to the app 424 * @param {Number} accessTokenId 425 * @param {String} permission permission name 426 * @param {Number} index Array index to modify permission status 427 */ 428 grantUserGrantedPermission(accessTokenId: number, permission: Permissions, resolve: (value: number) => void) { 429 abilityAccessCtrl.createAtManager().grantUserGrantedPermission(accessTokenId, permission, Constants.PERMISSION_FLAG) 430 .then(() => { 431 resolve(0); 432 }).catch((error: BusinessError) => { 433 resolve(-1); 434 Log.error('grantUserGrantedPermission failed. Cause: ' + JSON.stringify(error)); 435 }) 436 } 437 438 /** 439 * Deauthorize the app 440 * @param {Number} accessTokenId 441 * @param {String} permission permission name 442 * @param {Number} index Array index to modify permission status 443 */ 444 revokeUserGrantedPermission(accessTokenId: number, permission: Permissions, resolve: (value: number) => void) { 445 abilityAccessCtrl.createAtManager().revokeUserGrantedPermission( 446 accessTokenId, permission, Constants.PERMISSION_FLAG 447 ).then(() => { 448 resolve(0); 449 }).catch((error: BusinessError) => { 450 resolve(-1); 451 Log.error('revokeUserGrantedPermission failed. Cause: ' + JSON.stringify(error)); 452 }) 453 } 454 455 /** 456 * Lifecycle function, executed when the page is initialized 457 */ 458 aboutToAppear() { 459 let bundleNames: string[] = []; 460 this.applicationList = []; 461 this.list.forEach(permissionManager => { 462 permissionManager.bundleNames.forEach(bundleName => { 463 if (bundleNames.indexOf(bundleName) == -1) { 464 bundleNames.push(bundleName); 465 } 466 }) 467 }) 468 groups.forEach(group => { 469 if (group.name === this.currentGroup) { 470 this.groupInfo = group; 471 } 472 }) 473 474 for (let i = 0; i < bundleNames.length; i++) { 475 // Get BundleInfo based on bundle name 476 this.allBundleInfo.forEach(bundleInfo => { 477 if (bundleInfo.bundleName === bundleNames[i]) { 478 this.getApplicationList(bundleInfo, i); 479 } 480 }) 481 } 482 483 if (globalGroup.indexOf(this.currentGroup) !== -1) { 484 this.globalListen(); 485 } 486 } 487 488 aboutToDisappear() { 489 this.dialogController = null; 490 } 491 492 getApplicationList(bundleInfo: AppInfo, i: number) { 493 this.applicationList.push( 494 new ApplicationObj( 495 bundleInfo.label, 496 bundleInfo.icon, 497 i, 498 bundleInfo.tokenId, 499 this.list[0].permission, 500 bundleInfo.zhTag, 501 bundleInfo.indexTag, 502 bundleInfo.language, 503 bundleInfo.bundleName) // Get the first letter in the returned initials array 504 ); 505 this.isRisk[i] = false; 506 try { 507 abilityAccessCtrl.createAtManager().getPermissionFlags(bundleInfo.tokenId, this.list[0].permission) 508 .then(data => { 509 if (data == Constants.PERMISSION_POLICY_FIXED) { 510 this.isRisk[i] = true; 511 } 512 }) 513 } catch (err) { 514 Log.error('getPermissionFlags error: ' + JSON.stringify(err)); 515 } 516 // 0: have permission; -1: no permission 517 let boole = true; 518 this.permissionNum++; 519 for (let j = 0; j < this.list.length; j++) { 520 if (bundleInfo.permissions.indexOf(this.list[j].permission) == -1) { 521 continue; 522 } 523 verifyAccessToken(bundleInfo.tokenId, this.list[j].permission).then((access) => { 524 if (Number(access) === Constants.PERMISSION_INDEX) { 525 if (boole) { 526 this.toggleIsOn[i] = true; 527 this.isFirst[i] = true; 528 } 529 } else { 530 if (boole) { 531 this.permissionNum--; 532 } 533 boole = false; 534 this.toggleIsOn[i] = false; 535 this.isFirst[i] = false; 536 } 537 }); 538 } 539 } 540 541 globalListen() { 542 this.globalIsOn = globalIsOn; 543 if (this.currentGroup == 'CAMERA') { 544 let cameraManager = camera.getCameraManager(GlobalContext.load('context')); 545 cameraManager.on('cameraMute', (err, curMuted) => { 546 Log.info('curMuted: ' + JSON.stringify(curMuted) + ' err: ' + JSON.stringify(err)); 547 this.globalIsOn = !curMuted; 548 }) 549 } else { 550 let audioManager = audio.getAudioManager(); 551 let audioVolumeManager = audioManager.getVolumeManager(); 552 let groupId = audio.DEFAULT_VOLUME_GROUP_ID; 553 audioVolumeManager.getVolumeGroupManager(groupId).then(audioVolumeGroupManager => { 554 audioVolumeGroupManager.on('micStateChange', micStateChange => { 555 let muteState = audioVolumeGroupManager.isPersistentMicMute(); 556 Log.info('micStateChange: ' + JSON.stringify(muteState)); 557 this.globalIsOn = !muteState; 558 }) 559 }) 560 } 561 } 562 563 build() { 564 Column() { 565 Row() { 566 textInput({ 567 applicationItem: $applicationList, 568 searchResult: $searchResult 569 }) 570 }.padding({ 571 left: Constants.AUTHORITY_TEXTINPUT_PADDING_LEFT, 572 right: Constants.AUTHORITY_TEXTINPUT_PADDING_RIGHT 573 }) 574 Flex({ alignItems:ItemAlign.Start, justifyContent: FlexAlign.Start }) { 575 Column() { 576 if (globalGroup.indexOf(this.currentGroup) !== -1 && this.isMuteSupported === true) { 577 Row() { 578 Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { 579 Text(this.currentGroup == 'CAMERA' ? $r('app.string.camera') : $r('app.string.microphone')) 580 .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE).fontColor($r('sys.color.font_primary')) 581 .fontWeight(FontWeight.Medium) 582 Row() { 583 Toggle({ type: ToggleType.Switch, isOn: this.globalIsOn }) 584 .selectedColor($r('sys.color.icon_emphasize')) 585 .switchPointColor($r('sys.color.comp_background_primary_contrary')) 586 .padding({ right: 0 }) 587 .onChange((isOn: boolean) => { 588 if (isOn) { 589 if (this.currentGroup == 'CAMERA') { 590 let cameraManager = camera.getCameraManager(GlobalContext.load('context')); 591 cameraManager.muteCameraPersistent(false, camera.PolicyType.PRIVACY); 592 } else { 593 let audioManager = audio.getAudioManager(); 594 let audioVolumeManager = audioManager.getVolumeManager(); 595 let groupId = audio.DEFAULT_VOLUME_GROUP_ID; 596 audioVolumeManager.getVolumeGroupManager(groupId).then(audioVolumeGroupManager => { 597 audioVolumeGroupManager.setMicMutePersistent(false, audio.PolicyType.PRIVACY); 598 }) 599 } 600 } 601 }) 602 Row().onClick(() => { 603 this.dialogController?.open(); 604 }) 605 .width(Constants.DEFAULT_SLIDER_WIDTH).height(Constants.DEFAULT_SLIDER_HEIGHT) 606 .position({ x: this.globalIsOn ? 0 : Constants.OFFSET, y: 0 }) 607 }.clip(true) 608 }.height(Constants.LISTITEM_ROW_HEIGHT) 609 .padding({ left: Constants.DEFAULT_PADDING_START, right: Constants.DEFAULT_PADDING_END }) 610 }.padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM }) 611 .backgroundColor($r('sys.color.comp_background_list_card')) 612 .borderRadius($r('sys.float.ohos_id_corner_radius_card')) 613 .margin({ top: Constants.TERTIARY_ROW_MARGIN_TOP }) 614 } 615 Flex({ justifyContent: FlexAlign.Start }) { 616 if (this.globalIsOn) { 617 if (this.getGrantApplicationNumber() > 0) { 618 Text( 619 this.groupInfo.enableDescription ? 620 $r(this.groupInfo.enableDescription, String(this.getGrantApplicationNumber())) : 621 '' 622 ) 623 .fontSize(Constants.TEXT_SMALL_FONT_SIZE) 624 .fontColor($r('sys.color.font_secondary')) 625 .margin({ top: Constants.AUTHORITY_TEXT_MARGIN_TOP }) 626 } else { 627 Text(this.groupInfo.forbiddenDescription) 628 .fontSize(Constants.TEXT_SMALL_FONT_SIZE) 629 .fontColor($r('sys.color.font_secondary')) 630 .margin({ top: Constants.AUTHORITY_TEXT_MARGIN_TOP }) 631 } 632 } else { 633 Text( 634 this.currentGroup == 'CAMERA' ? 635 $r('app.string.camera_is_off') : 636 $r('app.string.microphone_is_off') 637 ) 638 .fontSize(Constants.TEXT_SMALL_FONT_SIZE) 639 .fontColor($r('sys.color.font_secondary')) 640 .margin({ top: Constants.AUTHORITY_TEXT_MARGIN_TOP }) 641 } 642 }.padding({ left: Constants.DEFAULT_PADDING_START, right: Constants.DEFAULT_PADDING_END }) 643 .margin({ bottom: Constants.AUTHORITY_ROW_MARGIN_BOTTOM }) 644 Row() { 645 Column() { 646 if (!this.applicationList.length) { 647 if (this.searchResult) { 648 Row() {} 649 } else { 650 Row() { 651 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 652 Image($r('app.media.searchnoresult')) 653 .objectFit(ImageFit.Contain) 654 .width(Constants.SEARCHNORESULT_IMAGE_WIDTH) 655 .height(Constants.SEARCHNORESULT_IMAGE_HEIGHT) 656 .draggable(false) 657 } 658 } 659 } 660 } else { 661 Row() { 662 List({ scroller: this.scroller }) { 663 ForEach(sortByName(this.applicationList), (item: ApplicationObj) => { 664 this.ListItemLayout(item) 665 }, (item: ApplicationObj) => JSON.stringify(item)) 666 } 667 .backgroundColor($r('sys.color.comp_background_list_card')) 668 .borderRadius($r('sys.float.ohos_id_corner_radius_card')) 669 .padding(Constants.LIST_PADDING_TOP) 670 .divider({ 671 strokeWidth: Constants.DIVIDER, 672 color: $r('sys.color.comp_divider'), 673 startMargin: Constants.DIVIDER_MARGIN_RIGHT_APPLICATION, 674 endMargin: Constants.DEFAULT_MARGIN_END 675 }) 676 .onScrollIndex((start, end) => { 677 GlobalContext.getContext().set('scroller', this.scroller); 678 if (this.applicationList.length > 0) { 679 let alphabeticalIndex: string = sortByName(this.applicationList)[start].indexTag; 680 let index = indexValue.indexOf(alphabeticalIndex); 681 this.selectedIndex = index >= 0 ? index : 0; 682 } 683 }) 684 } 685 } 686 }.width(Constants.FULL_WIDTH) 687 .margin({ 688 bottom: globalGroup.includes(this.currentGroup) && this.isMuteSupported === true ? 689 Constants.AUTHORITY_LIST_MARGIN_BOTTOM_GLOBAL : 690 Constants.AUTHORITY_LIST_MARGIN_BOTTOM 691 }) 692 } 693 }.padding({ left: Constants.AUTHORITY_LISTITEM_PADDING_LEFT }) 694 Column() { 695 alphabetIndexerComponent({ applicationItem: $applicationList, index: $selectedIndex }) 696 }.width(Constants.AUTHORITY_ALPHABETINDEX_WIDTH) 697 .padding({ top: Constants.AUTHORITY_ALPHABETINDEX_PADDING_TOP }) 698 .margin({ bottom: Constants.APPLICATION_LIST_MARGIN_BOTTOM }) 699 }.flexGrow(Constants.FLEX_GROW) 700 }.height(Constants.FULL_HEIGHT) 701 } 702} 703