• 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 router from '@ohos.router';
20import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
21import audio from '@ohos.multimedia.audio'
22import camera from '@ohos.multimedia.camera'
23import display from '@ohos.display';
24import common from '@ohos.app.ability.common';
25import { groups, userGrantPermissions, globalGroup, permissionGroups, showSubPermissionsGroup } from '../common/model/permissionGroup';
26import { Log, indexValue, getPermissionGroupByName, getGroupIdByPermission, addLocalTag, sortByName } from '../common/utils/utils';
27import { AppInfo, PermissionApplications, GroupPermission, GroupInfo } from '../common/utils/typedef';
28import { GlobalContext } from '../common/utils/globalContext';
29import Constants from '../common/utils/constant';
30import bundleManager from '@ohos.bundle.bundleManager';
31
32const FUZZY_LOCATION_PERMISSION = 'ohos.permission.APPROXIMATELY_LOCATION';
33const PRECISE_LOCATION_PERMISSION = 'ohos.permission.LOCATION';
34let storage = LocalStorage.getShared();
35
36@Extend(Image)function customizeImage(width: number, height: number) {
37  .objectFit(ImageFit.Contain)
38  .width(width)
39  .height(height)
40  .draggable(false)
41};
42
43@Entry(storage)
44@Component
45struct authorityManagementPage {
46  @Builder ListItemLayout(item: GroupPermission) {
47    ListItem() {
48      Row() {
49        Column() {
50          Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
51            Row() {
52              Image(item.icon)
53                .fillColor($r('sys.color.icon_secondary'))
54                .customizeImage(Constants.MANAGEMENT_IMAGE_WIDTH, Constants.MANAGEMENT_IMAGE_HEIGHT)
55                .margin({ right: Constants.MANAGEMENT_IMAGE_MARGIN_RIGHT })
56              Text(item.groupName)
57                .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
58                .fontWeight(FontWeight.Medium)
59                .fontColor($r('sys.color.font_primary'))
60                .flexGrow(Constants.FLEX_GROW)
61              Image($r('app.media.ic_public_arrow_right'))
62                .fillColor($r('sys.color.icon_tertiary'))
63                .customizeImage(Constants.IMAGE_WIDTH, Constants.IMAGE_HEIGHT)
64            }
65            .width(Constants.FULL_WIDTH)
66            .height(Constants.MANAGEMENT_ROW_HEIGHT)
67          }
68        }.onClick(() => {
69          if (item.group === 'OTHER' || showSubPermissionsGroup.indexOf(item.group) !== -1) {
70            router.pushUrl({
71              url: 'pages/authority-secondary',
72              params: { list: this.allPermissionApplications, backTitle: item.groupName, group: item.group }
73            })
74          } else {
75            let dataList = this.allPermissionApplications.filter((ele) => {
76              return ele.groupName === item.group;
77            })
78
79            GlobalContext.store('currentPermissionGroup', item.group);
80            if (globalGroup.indexOf(item.group) == -1) {
81              router.pushUrl({
82                url: 'pages/authority-tertiary-groups',
83                params: { list: dataList, backTitle: item.groupName }
84              })
85            } else {
86              if (item.group == 'MICROPHONE') {
87                let audioManager = audio.getAudioManager();
88                let audioVolumeManager = audioManager.getVolumeManager();
89                let groupId = audio.DEFAULT_VOLUME_GROUP_ID;
90                audioVolumeManager.getVolumeGroupManager(groupId).then(audioVolumeGroupManager => {
91                  let muteState = audioVolumeGroupManager.isPersistentMicMute();
92                  GlobalContext.store('isMuteSupported', true);
93                  router.pushUrl({
94                    url: 'pages/authority-tertiary-groups',
95                    params: { list: dataList, backTitle: item.groupName, globalIsOn: !muteState }
96                  })
97                })
98              } else {
99                let cameraManager = camera.getCameraManager(GlobalContext.load('context'));
100                let mute = cameraManager.isCameraMuted();
101                GlobalContext.store('isMuteSupported', cameraManager.isCameraMuteSupported());
102                router.pushUrl({
103                  url: 'pages/authority-tertiary-groups',
104                  params: { list: dataList, backTitle: item.groupName, globalIsOn: !mute }
105                })
106              }
107            }
108          }
109        })
110      }
111    }.padding({ left: $r('sys.float.ohos_id_card_margin_start'), right: $r('sys.float.ohos_id_card_margin_end') })
112    .borderRadius($r('sys.float.ohos_id_corner_radius_default_l'))
113    .linearGradient((this.isTouch === item.group) ? {
114        angle: 90,
115        direction: GradientDirection.Right,
116        colors: [['#DCEAF9', 0.0], ['#FAFAFA', 1.0]]
117      } : {
118        angle: 90,
119        direction: GradientDirection.Right,
120        colors: [[$r('sys.color.comp_background_list_card'), 1], [$r('sys.color.comp_background_list_card'), 1]]
121      })
122    .onTouch(event => {
123      if (event === undefined) {
124        return;
125      }
126      if (event.type === TouchType.Down) {
127        this.isTouch = item.group;
128      }
129      if (event.type === TouchType.Up) {
130        this.isTouch = '';
131      }
132    })
133  }
134
135  private context = getContext(this) as common.UIAbilityContext;
136  @LocalStorageLink('initialGroups') initialGroups: bundleManager.BundleInfo[] = [];
137  @State allPermissionApplications: PermissionApplications [] = []; // All app permissions
138  @State allGroupPermission: GroupPermission[] = []; // All group permissions
139  @State allUserPermissions: Permissions[] = [];
140  @State allBundleInfo: AppInfo[] = [];
141  @State allGroups: string[] = [];
142  @State currentIndex: number = 0;
143  @State isTouch: string = '';
144  @State isVertical: boolean = true;
145  @Builder TabBuilder(index: number) {
146    Flex({
147      alignItems: index ? ItemAlign.Start : ItemAlign.End,
148      justifyContent: FlexAlign.Center, direction: FlexDirection.Column
149    }) {
150      Text(index ? $r('app.string.application') : $r('app.string.permission'))
151        .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
152        .fontColor(
153          this.currentIndex == index ?
154          $r('sys.color.ohos_id_color_subtab_text_on') :
155          $r('sys.color.icon_secondary')
156        )
157        .fontWeight(this.currentIndex == index ? FontWeight.Bold : FontWeight.Regular)
158        .lineHeight(Constants.TEXT_LINE_HEIGHT)
159        .baselineOffset(Constants.TAB_DECORATION_POSITION_Y)
160      if (this.currentIndex == index) {
161        Text(index ? $r('app.string.application') : $r('app.string.permission'))
162          .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
163          .fontWeight(FontWeight.Bold)
164          .lineHeight(Constants.TAB_LINE_HEIGHT)
165          .height(Constants.TAB_DECORATION_HEIGHT)
166          .fontColor($r('sys.color.ohos_id_color_subtab_text_on'))
167          .backgroundColor($r('sys.color.ohos_id_color_subtab_text_on'))
168      }
169    }.height(Constants.TAB_HEIGHT)
170    .width(Constants.FULL_WIDTH)
171    .padding({ left: this.isVertical ? Constants.TAB_INNER_PADDING : Constants.DEFAULT_PADDING_START,
172      right: this.isVertical ? Constants.TAB_INNER_PADDING : Constants.DEFAULT_PADDING_END })
173  }
174
175  /**
176   * Get all app permission information
177   */
178  async getAllBundlePermissions() {
179    for (let i = 0; i < this.initialGroups.length; i++) {
180      await this.deduplicationPermissions(this.initialGroups[i]);
181    }
182    this.getAllGroupPermission();
183    this.getAllPermissionApplications();
184    this.getLabelAndIcon();
185    GlobalContext.store('allBundleInfo', this.allBundleInfo);
186  }
187
188  /**
189   * Get the corresponding permission group id according to the permission
190   * @param {String} permission app name id
191   * @return {Number} groupId
192   */
193  getPermissionGroupByPermission(permission: string): GroupInfo {
194    for (let i = 0; i < permissionGroups.length; i++) {
195      if (permissionGroups[i].permissionName == permission) {
196        return groups[permissionGroups[i].groupId];
197      }
198    }
199    return groups[0];
200  }
201
202  /**
203   * Get all permission label
204   */
205  getLabelAndIcon() {
206    this.allBundleInfo.forEach((bundleInfo: AppInfo) => {
207      this.updateAppLabel(bundleInfo);
208      this.updateAppIcon(bundleInfo);
209    })
210  }
211
212  /**
213   * Get all app permission information
214   */
215  getAllPermissionApplications() {
216    for (let i = 0; i < this.allUserPermissions.length; i++) {
217      let permission: Permissions = this.allUserPermissions[i];
218      let permissionGroup: GroupInfo = this.getPermissionGroupByPermission(permission);
219      let icon: ResourceStr = permissionGroup.icon;
220      let bundleNames: string[] = [];
221      for (let j = 0; j < this.allBundleInfo.length; j++) {
222        if (this.allBundleInfo[j].permissions.indexOf(permission) != -1) {
223          bundleNames.push(this.allBundleInfo[j].bundleName);
224        }
225      }
226      let pa: PermissionApplications = new PermissionApplications(permission, permissionGroup.name, bundleNames, icon);
227      this.allPermissionApplications.push(pa);
228    }
229  }
230
231  /**
232   * Get permission group information
233   */
234  getAllGroupPermission() {
235    groups.forEach((item) => {
236      if (item.isShow) {
237        this.allGroups.push(item.name);
238      }
239    })
240    this.allUserPermissions.forEach((userPermission: Permissions) => {
241      let groupId = getGroupIdByPermission(userPermission)
242      if (this.allGroups.indexOf(groups[groupId].name) == -1) {
243        this.allGroups.push(groups[groupId].name);
244      }
245    })
246    // Permission layout
247    for (let i = 0; i < this.allGroups.length; i++) {
248      let group = getPermissionGroupByName(this.allGroups[i]);
249      let gp: GroupPermission = new GroupPermission(
250        this.allGroups[i], group.permissions, group.groupName, group.icon, group.isShow
251      );
252      this.allGroupPermission.push(gp);
253    }
254  }
255
256  /**
257   * Deduplicate permission information and permission group information
258   * @param {Object} info bundleInfos Application Information
259   */
260  async deduplicationPermissions(info: bundleManager.BundleInfo) {
261    Log.info('allBundleInfo start: ' + info.name);
262    let reqPermissions: Permissions[] = [];
263    info.reqPermissionDetails.forEach(item => {
264      reqPermissions.push(item.name as Permissions);
265    })
266    let reqPermissionsLen = reqPermissions.length;
267    let reqUserPermissions: Permissions[] = [];
268    let acManager = abilityAccessCtrl.createAtManager()
269    if (reqPermissionsLen > 0) {
270      for (let j = 0; j < reqPermissions.length; j++) {
271        let permission = reqPermissions[j];
272        if ((permission == PRECISE_LOCATION_PERMISSION) && !reqPermissions.includes(FUZZY_LOCATION_PERMISSION)) {
273          continue;
274        }
275        try {
276          let flag = await acManager.getPermissionFlags(info.appInfo.accessTokenId, permission);
277          if (flag == Constants.PERMISSION_SYSTEM_FIXED) {
278            continue;
279          }
280        } catch (err) {
281          Log.error('getPermissionFlags error: ' + JSON.stringify(err));
282        }
283        if (userGrantPermissions.indexOf(permission) != -1) {
284          reqUserPermissions.push(permission);
285          if (this.allUserPermissions.indexOf(permission) == -1) {
286            this.allUserPermissions.push(permission);
287          }
288        }
289      }
290    }
291    this.getAllBundleInfo(info, reqUserPermissions);
292  }
293
294  getAllBundleInfo(info: bundleManager.BundleInfo, reqUserPermissions: Permissions[]) {
295    let groupIds: number[] = [];
296    for (let i = 0; i < reqUserPermissions.length; i++) {
297      let groupId = getGroupIdByPermission(reqUserPermissions[i])
298      if (groupIds.indexOf(groupId) == -1) {
299        groupIds.push(groupId);
300      }
301    }
302
303    let ap: AppInfo = new AppInfo(
304      info.name,
305      info.targetVersion,
306      info.appInfo.accessTokenId,
307      '',
308      info.appInfo.iconId,
309      info.appInfo.iconResource,
310      info.appInfo.label,
311      info.appInfo.labelId,
312      info.appInfo.labelResource,
313      reqUserPermissions,
314      groupIds,
315      '',
316      '',
317      ''
318    );
319    Log.info('allBundleInfo.push: ' + info.name);
320    this.allBundleInfo.push(ap);
321  }
322
323  /**
324   * Get app name resource
325   * @param {Number} index index of all app permissions array
326   * @param {String} bundleName Package names
327   * @param {String} labelName Application Name
328   */
329  async updateAppLabel(info: AppInfo) {
330    Log.info(
331      'bundleName: ' + info.bundleName +
332      ` labelResource: ` + JSON.stringify(info.labelResource) +
333      ' labelId: ' + info.labelId
334    );
335
336    try {
337      if (info.labelResource.id !== 0) {
338        info.label = await this.context.resourceManager.getStringValue(info.labelResource);
339      } else {
340        let resourceManager = this.context.createBundleContext(info.bundleName).resourceManager;
341        info.label = await resourceManager.getStringValue(info.labelId);
342      }
343    } catch (error) {
344      Log.error('getStringValue promise error is ' + error);
345    }
346    addLocalTag(info);
347  }
348
349  /**
350   * Get app icon resources
351   * @param {Number} index index of all app permissions array
352   * @param {String} bundleName Package names
353   */
354  async updateAppIcon(info: AppInfo) {
355    Log.info(
356      'bundleName: ' + info.bundleName +
357      ` iconResource: ` + JSON.stringify(info.iconResource) +
358      ' iconId: ' + info.iconId
359    );
360
361    try {
362      if (info.iconResource.id !== 0) {
363        let iconDescriptor = this.context.resourceManager.getDrawableDescriptor(info.iconResource);
364        info.icon = iconDescriptor?.getPixelMap();
365      } else {
366        let resourceManager = this.context.createBundleContext(info.bundleName).resourceManager;
367        let iconDescriptor = resourceManager.getDrawableDescriptor(info.iconId);
368        info.icon = iconDescriptor?.getPixelMap();
369      }
370    } catch (error) {
371      Log.error(`getDrawableDescriptor failed, error code: ${error.code}, message: ${error.message}.`);
372    }
373
374    if (!info.icon) {
375      info.icon = $r('app.media.icon');
376    }
377  }
378
379  /**
380   * Lifecycle function, executed when the page is initialized
381   */
382  aboutToAppear() {
383    this.getAllBundlePermissions();
384    let dis = display.getDefaultDisplaySync();
385    this.isVertical = dis.height > dis.width ? true : false;
386    GlobalContext.store('isVertical', dis.height > dis.width ? true : false);
387  }
388
389  getPermissionGroup(allGroup: GroupPermission[], order: number): GroupPermission[] {
390    let fixedName: string[] = ['LOCATION', 'CAMERA', 'MICROPHONE'];
391    let extraName: string[] = ['ADS'];
392    let fixedGroup: GroupPermission[] = [];
393    let extraGroup: GroupPermission[] = [];
394    let changeGroup: GroupPermission[] = [];
395    let otherGroup: GroupPermission[] = [];
396
397    allGroup.forEach(group => {
398      if (fixedName.indexOf(group.group) !== -1) {
399        fixedGroup.push(group);
400      } else if (extraName.includes(group.group)) {
401        extraGroup.push(group);
402      } else if (group.group == 'OTHER') {
403        otherGroup.push(group);
404      } else {
405        changeGroup.push(group);
406      }
407    })
408
409    if (order == Constants.FIXED_GROUP) {
410      return fixedGroup;
411    } else if (order == Constants.CHANGE_GROUP) {
412      return changeGroup;
413    } else if (order == Constants.OTHER_GROUP) {
414      return otherGroup;
415    } else if (order == Constants.EXTRA_GROUP) {
416      return extraGroup;
417    }
418    return [];
419  }
420
421  build() {
422    GridRow({ gutter: Constants.GUTTER, columns: {
423      xs: Constants.XS_COLUMNS, sm: Constants.SM_COLUMNS, md: Constants.MD_COLUMNS, lg: Constants.LG_COLUMNS } }) {
424      GridCol({
425        span: { xs: Constants.XS_SPAN, sm: Constants.SM_SPAN, md: Constants.MD_SPAN, lg: Constants.LG_SPAN },
426        offset: { xs: Constants.XS_OFFSET, sm: Constants.SM_OFFSET, md: Constants.MD_OFFSET, lg: Constants.LG_OFFSET }
427      }) {
428        Row() {
429          Column() {
430            Row() {
431              backBar( { title: JSON.stringify($r('app.string.permission_manager')), recordable: true })
432            }
433            Row() {
434              Column() {
435                Column() {
436                  Stack() {
437                    if (this.allGroupPermission.length) {
438                      Tabs() {
439                        TabContent() {
440                          Row() {
441                            Column() {
442                              Scroll() {
443                                Column() {
444                                  List() {
445                                    ListItem() {
446                                      List() {
447                                        ForEach(
448                                          this.getPermissionGroup(this.allGroupPermission, Constants.FIXED_GROUP),
449                                          (item: GroupPermission) => { this.ListItemLayout(item) },
450                                          (item: GroupPermission) => JSON.stringify(item)
451                                        )
452                                      }.backgroundColor($r('sys.color.comp_background_list_card'))
453                                      .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
454                                      .padding(Constants.LIST_PADDING_TOP)
455                                      .margin({ bottom: Constants.LIST_MARGIN_BOTTOM })
456                                      .divider({
457                                        strokeWidth: Constants.DIVIDER,
458                                        color: $r('sys.color.comp_divider'),
459                                        startMargin: Constants.DIVIDER_MARGIN_RIGHT_PERMISSION,
460                                        endMargin: Constants.DEFAULT_MARGIN_END
461                                      })
462                                    }
463
464                                    ListItem() {
465                                      List() {
466                                        ForEach(
467                                          this.getPermissionGroup(this.allGroupPermission, Constants.CHANGE_GROUP),
468                                          (item: GroupPermission) => { this.ListItemLayout(item) },
469                                          (item: GroupPermission) => JSON.stringify(item)
470                                        )
471                                      }.backgroundColor($r('sys.color.comp_background_list_card'))
472                                      .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
473                                      .padding(Constants.LIST_PADDING_TOP)
474                                      .margin({ bottom: Constants.LIST_MARGIN_BOTTOM })
475                                      .divider({
476                                        strokeWidth: Constants.DIVIDER,
477                                        color: $r('sys.color.comp_divider'),
478                                        startMargin: Constants.DIVIDER_MARGIN_RIGHT_PERMISSION,
479                                        endMargin: Constants.DEFAULT_MARGIN_END
480                                      })
481                                    }
482
483                                    if (
484                                      this.getPermissionGroup(this.allGroupPermission, Constants.EXTRA_GROUP).length
485                                    ) {
486                                      ListItem() {
487                                        List() {
488                                          ForEach(
489                                            this.getPermissionGroup(this.allGroupPermission, Constants.EXTRA_GROUP),
490                                            (item: GroupPermission) => { this.ListItemLayout(item) },
491                                            (item: GroupPermission) => JSON.stringify(item)
492                                          )
493                                        }.backgroundColor($r('sys.color.comp_background_list_card'))
494                                        .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
495                                        .padding(Constants.LIST_PADDING_TOP)
496                                        .margin({ bottom: Constants.LIST_MARGIN_BOTTOM })
497                                        .divider({
498                                          strokeWidth: Constants.DIVIDER,
499                                          color: $r('sys.color.comp_divider'),
500                                          startMargin: Constants.DIVIDER_MARGIN_RIGHT_PERMISSION,
501                                          endMargin: Constants.DEFAULT_MARGIN_END
502                                        })
503                                      }
504                                    }
505
506                                    ListItem() {
507                                      List() {
508                                        ForEach(
509                                          this.getPermissionGroup(this.allGroupPermission, Constants.OTHER_GROUP),
510                                          (item: GroupPermission) => { this.ListItemLayout(item) },
511                                          (item: GroupPermission) => JSON.stringify(item)
512                                        )
513                                      }.backgroundColor($r('sys.color.comp_background_list_card'))
514                                      .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
515                                      .padding(Constants.LIST_PADDING_TOP)
516                                      .divider({
517                                        strokeWidth: Constants.DIVIDER,
518                                        color: $r('sys.color.comp_divider'),
519                                        startMargin: Constants.DIVIDER_MARGIN_RIGHT_PERMISSION,
520                                        endMargin: Constants.DEFAULT_MARGIN_END
521                                      })
522                                    }.margin({ bottom: Constants.AUTHORITY_ROW_MARGIN_BOTTOM })
523                                  }.height(Constants.FULL_HEIGHT)
524                                  .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
525                                  .clip(true)
526                                }.padding({
527                                  left: Constants.MANAGEMENT_ROW_PADDING_LEFT,
528                                  right: Constants.MANAGEMENT_ROW_PADDING_RIGHT,
529                                })
530                              }.scrollBar(BarState.Off)
531                              .margin({ top: Constants.MANAGEMENT_ROW_PADDING_TOP })
532                            }.width(Constants.FULL_WIDTH)
533                          }
534                        }.tabBar(this.TabBuilder(0))
535                        TabContent() {
536                          applicationItem()
537                        }.tabBar(this.TabBuilder(1))
538                      }
539                      .barMode(BarMode.Fixed)
540                      .barWidth(Constants.BAR_WIDTH)
541                      .onChange((index) => {
542                        this.currentIndex = index
543                      })
544                    } else {
545                      LoadingProgress().width(Constants.LOADING_WIDTH)
546                    }
547                  }.height(Constants.FULL_HEIGHT)
548                }
549              }
550            }
551            .layoutWeight(Constants.LAYOUT_WEIGHT)
552          }
553        }
554        .height(Constants.FULL_HEIGHT)
555        .width(Constants.FULL_WIDTH)
556        .backgroundColor($r('sys.color.background_secondary'))
557      }
558    }.backgroundColor($r('sys.color.background_secondary'))
559  }
560}
561
562@Component
563struct applicationItem {
564  @State applicationItem: AppInfo[] = GlobalContext.load('allBundleInfo'); // application info array
565  @State searchResult: boolean = true; // search results
566  @State selectedIndex: number = 0;
567  @State isTouch: string = '';
568  scroller: Scroller = new Scroller();
569
570  @Builder ListItemLayout(item: AppInfo) {
571    ListItem() {
572      Row() {
573        Column() {
574          Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
575            Row() {
576              Image(item.icon)
577                .customizeImage(Constants.APPLICATION_IMAGE_WIDTH, Constants.APPLICATION_IMAGE_HEIGHT)
578                .margin({ right: Constants.APPLICATION_IMAGE_MARGIN_RIGHT })
579              Text(item.label)
580                .width(Constants.OFFSET)
581                .maxLines(Constants.MAXIMUM_HEADER_LINES)
582                .textOverflow({ overflow: TextOverflow.Ellipsis })
583                .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
584                .fontWeight(FontWeight.Medium)
585                .fontColor($r('sys.color.font_primary'))
586                .flexGrow(Constants.FLEX_GROW)
587              Text(String(item.groupId.length))
588                .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
589                .fontColor($r('sys.color.font_secondary'))
590              Text($r('app.string.right'))
591                .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
592                .fontColor($r('sys.color.font_secondary'))
593                .margin({ right: Constants.APPLICATION_TEXT_MARGIN_RIGHT })
594              Image($r('app.media.ic_public_arrow_right'))
595                .fillColor($r('sys.color.icon_tertiary'))
596                .customizeImage(Constants.IMAGE_WIDTH, Constants.IMAGE_HEIGHT)
597            }
598            .width(Constants.FULL_WIDTH)
599            .height(Constants.AUTHORITY_ROW_HEIGHT)
600            .constraintSize({ minHeight: Constants.AUTHORITY_CONSTRAINTSIZE_MINHEIGHT })
601          }
602        }.onClick(() => {
603          GlobalContext.store('applicationInfo', item);
604          router.pushUrl({ url: 'pages/application-secondary' });
605        })
606      }
607    }.padding({ left: $r('sys.float.ohos_id_card_margin_start'), right: $r('sys.float.ohos_id_card_margin_end') })
608    .borderRadius($r('sys.float.ohos_id_corner_radius_default_l'))
609    .linearGradient((this.isTouch === item.bundleName) ? {
610         angle: 90,
611         direction: GradientDirection.Right,
612         colors: [['#DCEAF9', 0.0], ['#FAFAFA', 1.0]]
613       } : {
614         angle: 90,
615         direction: GradientDirection.Right,
616         colors: [[$r('sys.color.comp_background_list_card'), 1], [$r('sys.color.comp_background_list_card'), 1]]
617       })
618    .onTouch(event => {
619      if (event === undefined) {
620        return;
621      }
622      if (event.type === TouchType.Down) {
623        this.isTouch = item.bundleName;
624      }
625      if (event.type === TouchType.Up) {
626        this.isTouch = '';
627      }
628    })
629  }
630
631  build() {
632    Column() {
633      Row() {
634        textInput({
635          applicationItem: $applicationItem,
636          searchResult: $searchResult
637        })
638      }.padding({
639        left: Constants.APPLICATION_TEXTINPUT_PADDING_LEFT,
640        top: Constants.APPLICATION_TEXTINPUT_PADDING_TOP,
641        right: Constants.APPLICATION_TEXTINPUT_PADDING_RIGHT
642      })
643      Row() {
644        Flex({ alignItems: ItemAlign.Start }) {
645          Column() {
646            Column() {
647              if (!this.applicationItem.length) {
648                Row() {
649                  Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
650                    Image($r('app.media.searchnoresult'))
651                      .customizeImage(Constants.SEARCHNORESULT_IMAGE_WIDTH, Constants.SEARCHNORESULT_IMAGE_HEIGHT)
652                  }
653                }.margin({ top: Constants.MANAGEMENT_ROW_MARGIN_TOP })
654                .padding({ left: Constants.MANAGEMENT_ROW_PADDING_LEFT })
655              } else {
656                Row() {
657                  List({ scroller: this.scroller }) {
658                    ForEach(sortByName(this.applicationItem), (item: AppInfo) => {
659                      this.ListItemLayout(item)
660                    }, (item: AppInfo) => JSON.stringify(item))
661                  }.backgroundColor($r('sys.color.comp_background_list_card'))
662                  .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
663                  .padding(Constants.LIST_PADDING_TOP)
664                  .divider({
665                    strokeWidth: Constants.DIVIDER,
666                    color: $r('sys.color.comp_divider'),
667                    startMargin: Constants.DIVIDER_MARGIN_RIGHT_APPLICATION,
668                    endMargin: Constants.DEFAULT_MARGIN_END
669                  })
670                  .onScrollIndex((start, end) => {
671                    GlobalContext.getContext().set('scroller', this.scroller);
672                    if (this.applicationItem.length > 0) {
673                      let alphabeticalIndex = sortByName(this.applicationItem)[start].indexTag;
674                      let index = indexValue.indexOf(alphabeticalIndex);
675                      this.selectedIndex = index >= 0 ? index : 0;
676                    }
677                  })
678                }.margin({ left: Constants.MANAGEMENT_ROW_PADDING_LEFT })
679                .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
680                .clip(true)
681              }
682            }.height(Constants.FULL_HEIGHT)
683          }.margin({ top: Constants.MANAGEMENT_ROW_MARGIN_TOP, bottom: Constants.APPLICATION_LIST_MARGIN_BOTTOM })
684          Column() {
685            alphabetIndexerComponent({ applicationItem: $applicationItem, index: $selectedIndex })
686          }
687          .margin({
688            top: Constants.APPLICATION_ALPHABETINDEX_MARGIN_TOP,
689            bottom: Constants.APPLICATION_LIST_MARGIN_BOTTOM
690          })
691          .width(Constants.APPLICATION_ALPHABETINDEX_WIDTH)
692        }
693      }
694    }
695  }
696}