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