• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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