• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { backBar } from "../common/components/backBar";
17import { alphabetIndexerComponent } from "../common/components/alphabeticalIndex";
18import { textInput } from "../common/components/search";
19import router from '@ohos.router';
20import bundle from "@ohos.bundle";
21import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
22import audio from '@ohos.multimedia.audio'
23import camera from '@ohos.multimedia.camera'
24import { groups, userGrantPermissions, permissionGroupPermissions, globalGroup } from "../common/model/permissionGroup";
25import { permissionGroups, permissionGroupIds, showSubpermissionsGrop } from "../common/model/permissionGroup";
26import { makePy } from "../common/utils/utils";
27import Constants from '../common/utils/constant';
28
29var TAG = 'PermissionManager_MainAbility:'
30
31@Extend(Image) function customizeImage(width: number, height: number) {
32  .objectFit(ImageFit.Contain)
33  .width(width)
34  .height(height)
35};
36
37interface applicationPermissions {
38  'bundleName': string,
39  'api': number,
40  'iconId': string,
41  'permissions': string[],
42  'labelId': string,
43  'tokenId': number,
44  'groupId': number[]
45};
46
47interface permissionApplications {
48  'permission': string,
49  'groupName': string,
50  'bundleNames': string[],
51  'icon': string
52};
53
54interface groupPermission {
55  'group': string,
56  'permissions': string[],
57  'groupName': string,
58  'icon': string,
59  'isShow':boolean
60};
61
62let textInput_placeholder: any = ''
63const FUZZY_LOCATION_PERMISSION = 'ohos.permission.APPROXIMATELY_LOCATION'
64const PRECISE_LOCATION_PERMISSION = 'ohos.permission.LOCATION'
65
66@Entry
67@Component
68struct authorityManagementPage {
69  @Builder ListItemLayout(item, index) {
70    ListItem() {
71      Row() {
72        Column() {
73          Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
74            Row() {
75              Image(item.icon)
76                .customizeImage(Constants.MANAGEMENT_IMAGE_WIDTH, Constants.MANAGEMENT_IMAGE_HEIGHT)
77                .margin({ right: Constants.MANAGEMENT_IMAGE_MARGIN_RIGHT })
78              Text(item.groupName)
79                .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
80                .fontWeight(FontWeight.Medium)
81                .fontColor($r('app.color.label_color'))
82                .flexGrow(Constants.FLEX_GROW)
83              Image($r('app.media.ic_public_arrow_right'))
84                .customizeImage(Constants.IMAGE_WIDTH, Constants.IMAGE_HEIGHT)
85            }
86            .width(Constants.FULL_WIDTH)
87            .height(Constants.MANAGEMENT_ROW_HEIGHT)
88          }
89          if (!index) {
90            Row() {
91              Flex() {
92                Column().width(Constants.MANAGEMENT_TEXT_DECORATION_MARGIN_LEFT)
93                Column()
94                  .backgroundColor($r('app.color.text_decoration_color'))
95                  .height(Constants.TEXT_DECORATION_HEIGHT)
96                  .flexGrow(Constants.FLEX_GROW)
97              }
98            }
99          }
100        }.onClick(() => {
101          if (item.group === 'OTHER' || showSubpermissionsGrop.indexOf(item.group) !== -1) {
102            router.pushUrl({
103              url: 'pages/authority-secondary',
104              params: { routerData: this.allPermissionApplications, backTitle: item.groupName, group: item.group }
105            })
106          } else {
107            var dataList = this.allPermissionApplications.filter((ele) => {
108              return ele.groupName === item.group
109            })
110
111            globalThis.currentPermissionGroup = item.group
112            if(globalGroup.indexOf(item.group) == -1) {
113              router.pushUrl({
114                url: 'pages/authority-tertiary-groups',
115                params: { routerData: dataList, backTitle: item.groupName  }
116              })
117            }else {
118              if(item.group == 'MICROPHONE') {
119                var audioManager = audio.getAudioManager();
120                audioManager.isMicrophoneMute().then(value => {
121                  router.pushUrl({
122                    url: 'pages/authority-tertiary-groups',
123                    params: { routerData: dataList, backTitle: item.groupName, globalIsOn: !value }
124                  })
125                })
126              }else {
127                let cameraManager = camera.getCameraManager(globalThis.context);
128                let mute = cameraManager.isCameraMuted()
129                router.pushUrl({
130                  url: 'pages/authority-tertiary-groups',
131                  params: { routerData: dataList, backTitle: item.groupName, globalIsOn: !mute }
132                })
133              }
134            }
135          }
136        })
137      }
138    }.padding({ left: Constants.DEFAULT_PADDING_START, right: Constants.DEFAULT_PADDING_END })
139  }
140
141  @State allPermissionApplications: permissionApplications [] = [] // All app permissions
142  @State allGroupPermission: groupPermission[] = [] // All group permissions
143  @State currentIndex: number = 0
144  @State @Watch("getLabelAndIcon") ready: boolean = false
145  @Builder TabBuilder(index: number) {
146    Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
147      Text(index ? $r('app.string.application') : $r('app.string.authority'))
148        .fontColor(this.currentIndex == index ? $r('app.color.button_color') : $r('app.color.label_color'))
149        .fontWeight(this.currentIndex == index ? FontWeight.Bold : FontWeight.Regular)
150        .lineHeight(Constants.TEXT_LINE_HEIGHT)
151      if(this.currentIndex == index) {
152        Row().width(Constants.FULL_WIDTH).height(Constants.TAB_DECORATION_HEIGHT)
153          .backgroundColor($r('app.color.button_color'))
154          .position({ y: Constants.TAB_DECORATION_POSITION_Y })
155      }
156    }.height(Constants.TAB_HEIGHT)
157  }
158
159  /**
160   * Convert the permission array into key, value key-value objects for easy sorting
161   * @param {Array} order User rights
162   * @return {Object} return the processed object
163   */
164  orderDict(order) {
165    let result = {};
166    for (let i = 0; i < order.length; i++) {
167      let key = order[i];
168      result[key] = i;
169    }
170    return result;
171  }
172
173  /**
174   * Compare and sort the permission array according to the permission key value
175   * @param {String} prop Sort by permission
176   * @param {Object} orderSort objects to be sorted
177   * @return {Array} Returns a sorted array of permissions
178   */
179  compare(prop, orderSort) {
180    return function(a, b) {
181      let aSortValue = orderSort[a[prop]];
182      let bSortValue = orderSort[b[prop]];
183      if (aSortValue == undefined) {
184        throw new Error('当前的字段不在排序列表里:' + a[prop]);
185      }
186      if (bSortValue == undefined) {
187        throw new Error('当前的字段不在排序列表里:' + b[prop]);
188      }
189      return aSortValue - bSortValue;
190    }
191  }
192
193  /**
194   * Get all app permission information
195   */
196  async getAllBundlePermissions() {
197      for (let i = 0; i < globalThis.initialGroups.length; i++) {
198        await this.deduplicationPermissions(globalThis.initialGroups[i]);
199      }
200      this.getAllGroupPermission();
201      this.getAllPermissionApplications();
202      let orderSort = this.orderDict(userGrantPermissions);
203      this.allPermissionApplications.sort(this.compare('permission', orderSort));
204      this.getPermissionLabel()
205  }
206
207  /**
208   * Get the corresponding permission group id according to the permission
209   * @param {String} permission app name id
210   * @return {Number} groupId
211   */
212  getPermissionGroupByPermission(permission: string) {
213    for (let i = 0; i < permissionGroups.length; i++) {
214      if (permissionGroups[i].permissionName == permission) {
215        return groups[permissionGroups[i].groupId];
216      }
217    }
218  }
219
220  /**
221   * Get all permission label
222   */
223  getPermissionLabel() {
224    globalThis.allUserPermissions.forEach(userPermission => {
225      permissionGroups.forEach(permissionInfo => {
226        if(userPermission == permissionInfo.permissionName) {
227          globalThis.context.resourceManager.getString(permissionInfo.label.id).then(val => {
228            globalThis.permissionLabels[userPermission] = val
229          })
230        }
231      })
232    })
233  }
234
235  /**
236   * Get all permission label
237   */
238  getLabelAndIcon() {
239    const this_ = this
240    setTimeout(function() {
241      globalThis.allBundleInfo.forEach(bundleInfo => {
242        let context = globalThis.context.createBundleContext(bundleInfo.bundleName)
243        this_.updateAppLabel(bundleInfo, context)
244        this_.updateAppIcon(bundleInfo, context)
245      })
246    }, 100)
247  }
248
249  /**
250   * Get all app permission information
251   */
252  getAllPermissionApplications() {
253    const this_ = this;
254    for (let i = 0; i < globalThis.allUserPermissions.length; i++) {
255      var permissionGroup = this_.getPermissionGroupByPermission(globalThis.allUserPermissions[i]);
256      var icon: string = permissionGroup.icon;
257      var bundleNames: string[] = [];
258      for (let j = 0; j < globalThis.allBundleInfo.length; j++) {
259        if (globalThis.allBundleInfo[j].permissions.indexOf(globalThis.allUserPermissions[i]) != -1) {
260          bundleNames.push(globalThis.allBundleInfo[j].bundleName);
261        }
262      }
263      var pa: permissionApplications = {
264        'permission': globalThis.allUserPermissions[i],
265        'groupName': permissionGroup.name,
266        'bundleNames': bundleNames,
267        'icon': icon
268      };
269      this_.allPermissionApplications.push(pa);
270    }
271  }
272
273  /**
274   * Get permission group information
275   */
276  getAllGroupPermission() {
277    const this_ = this;
278    groups.forEach((item) => {
279      if (item.isShow) {
280        globalThis.allGroups.push(item.name);
281      }
282    })
283    globalThis.allUserPermissions.forEach(userPermission => {
284      if (globalThis.allGroups.indexOf(groups[permissionGroupIds[userPermission]].name) == -1) {
285        globalThis.allGroups.push(groups[permissionGroupIds[userPermission]].name);
286      }
287    })
288    // Permission layout
289    for (let i = 0; i < globalThis.allGroups.length; i++) {
290      var permissions: string[] = permissionGroupPermissions[globalThis.allGroups[i]];
291      var gp: groupPermission = {
292        "group": globalThis.allGroups[i],
293        "permissions": permissions,
294        'groupName': '',
295        'icon': '',
296        'isShow': false
297      };
298      this_.allGroupPermission.push(gp);
299    }
300    this.allGroupPermission.forEach((ele) => {
301      groups.forEach((item) => {
302        if (ele.group === item.name) {
303          ele.groupName = item.groupName;
304          ele.icon = item.icon;
305          ele.isShow = item.isShow;
306        }
307      });
308    })
309  }
310
311  /**
312   * Deduplicate permission information and permission group information
313   * @param {Object} info bundleInfos Application Information
314   */
315  async deduplicationPermissions(info) {
316    var reqPermissionsLen = info.reqPermissions.length;
317    var reqUserPermissions: string[] = [];
318    var acManager = abilityAccessCtrl.createAtManager()
319    if (reqPermissionsLen > 0) {
320      for (let j = 0; j < info.reqPermissions.length; j++) {
321        var permission = info.reqPermissions[j];
322        if((info.targetVersion < Constants.API_VERSION_SUPPORT_STAGE) && (permission == FUZZY_LOCATION_PERMISSION)) {
323          continue
324        }
325        if((info.targetVersion >= Constants.API_VERSION_SUPPORT_STAGE) && (permission == PRECISE_LOCATION_PERMISSION) && !info.reqPermissions.includes(FUZZY_LOCATION_PERMISSION)) {
326          continue
327        }
328        try {
329          var flag = await acManager.getPermissionFlags(info.appInfo.accessTokenId, permission)
330          if(flag == Constants.PRE_AUTHORIZATION_NOT_MODIFIED) {
331            continue
332          }
333        }
334        catch(err) {
335          console.log(TAG + 'getPermissionFlags error: ' + JSON.stringify(err))
336        }
337        if (userGrantPermissions.indexOf(permission) != -1) {
338          reqUserPermissions.push(permission);
339          if (globalThis.allUserPermissions.indexOf(permission) == -1) {
340            globalThis.allUserPermissions.push(permission);
341          }
342        }
343      }
344    }
345    let groupIds = [];
346    for (let i = 0; i < reqUserPermissions.length; i++) {
347      if(groupIds.indexOf(permissionGroupIds[reqUserPermissions[i]]) == -1){
348        groupIds.push(permissionGroupIds[reqUserPermissions[i]]);
349      }
350    }
351
352    // adapt different api
353    if (info.compatibleVersion >= Constants.API_VERSION_SUPPORT_STAGE) {
354      info.appInfo.iconId = info.hapModuleInfos[0].abilityInfo[0].iconId;
355    }
356
357    var ap: applicationPermissions = {
358      'bundleName': info.name,
359      'api': info.targetVersion,
360      'tokenId': info.appInfo.accessTokenId,
361      'iconId': info.appInfo.iconId,
362      'labelId': info.appInfo.labelId,
363      'permissions': reqUserPermissions,
364      'groupId': groupIds
365    };
366    globalThis.allBundleInfo.push(ap)
367  }
368
369  /**
370   * Get app name resource
371   * @param {Number} index index of all app permissions array
372   * @param {String} bundleName Package names
373   * @param {String} labelName Application Name
374   */
375  updateAppLabel(info, context) {
376    context.resourceManager.getString(info.labelId, (error, value) => {
377        info.labelId = value;
378        if (!isNaN(info.labelId)) {
379          info.alphabeticalIndex = '';
380        } else {
381          info.alphabeticalIndex = makePy(info.labelId)[0].slice(0, 1); // Get the first letter in the returned initials array
382        }
383    })
384  }
385
386  /**
387   * Get app icon resources
388   * @param {Number} index index of all app permissions array
389   * @param {String} bundleName Package names
390   */
391  updateAppIcon(info, context) {
392    context.resourceManager.getMediaBase64(info.iconId, (error, value) => {
393      info.iconId = value;
394    })
395  }
396
397  /**
398   * Lifecycle function, executed when the page is initialized
399   */
400  aboutToAppear() {
401    console.log(TAG + 'on aboutToAppear, version 1.01');
402    this.getAllBundlePermissions();
403    var acManager = abilityAccessCtrl.createAtManager()
404    bundle.getApplicationInfo(Constants.BUNDLE_NAME, 0).then(data => {
405      acManager.grantUserGrantedPermission(data.accessTokenId, "ohos.permission.MICROPHONE", 2)
406    })
407    globalThis.context.resourceManager.getString($r("app.string.textInput_placeholder").id).then(val => {
408      textInput_placeholder = val
409    })
410  }
411
412  getPermissionGroup(allGroup, order) {
413    var fixedName: string[] = ['LOCATION', 'CAMERA', 'MICROPHONE']
414    var fixedGroup: any[] = []
415    var changeGroup: any[] = []
416    var otherGroup: any[] = []
417
418    allGroup.forEach(group => {
419      if(fixedName.indexOf(group.group) !== -1) {
420        fixedGroup.push(group)
421      }else if(group.group == 'OTHER') {
422        otherGroup.push(group)
423      }else {
424        changeGroup.push(group)
425      }
426    })
427
428    if(order == Constants.FIXED_GROUP){
429      return fixedGroup
430    }else if(order == Constants.CHANGE_GROUP) {
431      return changeGroup
432    }else if(order == Constants.OTHER_GROUP) {
433      return otherGroup
434    }
435  }
436
437  LoadLabelAndIcon() {
438    const this_ = this
439    setTimeout(function() { this_.ready = true }, 100)
440    return true
441  }
442
443  build() {
444    GridContainer({ gutter: Constants.GUTTER, margin: Constants.GRID_MARGIN }) {
445      Row() {
446        Row()
447          .useSizeType({
448            xs: { span: Constants.LEFT_XS_SPAN, offset: Constants.LEFT_XS_OFFSET },
449            sm: { span: Constants.LEFT_SM_SPAN, offset: Constants.LEFT_SM_OFFSET },
450            md: { span: Constants.LEFT_MD_SPAN, offset: Constants.LEFT_MD_OFFSET },
451            lg: { span: Constants.LEFT_LG_SPAN, offset: Constants.LEFT_LG_OFFSET }
452          })
453          .height(Constants.FULL_HEIGHT)
454        Row() {
455          Column() {
456            Row() {
457              backBar( { title: JSON.stringify($r('app.string.authority_management')), recordable: true })
458            }
459            Row() {
460              Column() {
461                Column() {
462                  Stack() {
463                    if(this.allGroupPermission.length) {
464                      Tabs() {
465                        TabContent() {
466                          Row() {
467                            Column() {
468                              Scroll() {
469                                Column() {
470                                  List() {
471                                    ListItem() {
472                                      List() {
473                                        ForEach(this.getPermissionGroup(this.allGroupPermission, Constants.FIXED_GROUP).slice(Constants.SLICE_START,
474                                          this.getPermissionGroup(this.allGroupPermission, Constants.FIXED_GROUP).length - 1), (item) => {
475                                          this.ListItemLayout(item, Constants.SLICE_START_INDEX)
476                                        }, item => item.toString())
477                                        ForEach(this.getPermissionGroup(this.allGroupPermission, Constants.FIXED_GROUP).slice(Constants.SLICE_END), (item) => {
478                                          this.ListItemLayout(item, Constants.SLICE_END_INDEX)
479                                        }, item => item.toString())
480                                      }.backgroundColor($r('app.color.default_background_color'))
481                                      .borderRadius(Constants.BORDER_RADIUS)
482                                      .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
483                                      .margin({ bottom: Constants.LIST_MARGIN_BOTTOM })
484                                    }
485
486                                    ListItem() {
487                                      List() {
488                                        ForEach(this.getPermissionGroup(this.allGroupPermission, Constants.CHANGE_GROUP).slice(Constants.SLICE_START,
489                                          this.getPermissionGroup(this.allGroupPermission, Constants.CHANGE_GROUP).length - 1), (item) => {
490                                          this.ListItemLayout(item, Constants.SLICE_START_INDEX)
491                                        }, item => item.toString())
492                                        ForEach(this.getPermissionGroup(this.allGroupPermission, Constants.CHANGE_GROUP).slice(Constants.SLICE_END), (item) => {
493                                          this.ListItemLayout(item, Constants.SLICE_END_INDEX)
494                                        }, item => item.toString())
495                                      }.backgroundColor($r('app.color.default_background_color'))
496                                      .borderRadius(Constants.BORDER_RADIUS)
497                                      .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
498                                      .margin({ bottom: Constants.LIST_MARGIN_BOTTOM })
499                                    }
500
501                                    ListItem() {
502                                      if(this.LoadLabelAndIcon()) {}
503                                      List() {
504                                        ForEach(this.getPermissionGroup(this.allGroupPermission, Constants.OTHER_GROUP), (item) => {
505                                          this.ListItemLayout(item, Constants.SLICE_END_INDEX)
506                                        }, item => item.toString())
507                                      }.backgroundColor($r('app.color.default_background_color'))
508                                      .borderRadius(Constants.BORDER_RADIUS)
509                                      .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
510                                    }
511                                  }.height(Constants.FULL_HEIGHT)
512                                  .borderRadius(Constants.BORDER_RADIUS)
513                                  .clip(true)
514                                }.padding({
515                                  left: Constants.MANAGEMENT_ROW_PADDING_LEFT,
516                                  right: Constants.MANAGEMENT_ROW_PADDING_RIGHT,
517                                })
518                              }.scrollBar(BarState.Off)
519                              .margin({ top: Constants.MANAGEMENT_ROW_PADDING_TOP })
520                            }.width(Constants.FULL_WIDTH)
521                          }
522                        }.tabBar(this.TabBuilder(0))
523                        TabContent() {
524                          applicationItem()
525                        }.tabBar(this.TabBuilder(1))
526                      }
527                      .barWidth(Constants.BAR_WIDTH)
528                      .barMode(BarMode.Fixed)
529                      .onChange((index) => {
530                        this.currentIndex = index
531                      })
532                    }else {
533                      LoadingProgress().width(Constants.LOADING_WIDTH)
534                    }
535                  }.height(Constants.FULL_HEIGHT)
536                }
537              }
538            }
539            .layoutWeight(Constants.LAYOUT_WEIGHT)
540          }
541        }
542        .useSizeType({
543          xs: { span: Constants.MIDDLE_XS_SPAN, offset: Constants.MIDDLE_XS_OFFSET },
544          sm: { span: Constants.MIDDLE_SM_SPAN, offset: Constants.MIDDLE_SM_OFFSET },
545          md: { span: Constants.MIDDLE_MD_SPAN, offset: Constants.MIDDLE_MD_OFFSET },
546          lg: { span: Constants.MIDDLE_LG_SPAN, offset: Constants.MIDDLE_LG_OFFSET }
547        })
548        .height(Constants.FULL_HEIGHT)
549        Row()
550          .useSizeType({
551            xs: { span: Constants.RIGHT_XS_SPAN, offset: Constants.RIGHT_XS_OFFSET },
552            sm: { span: Constants.RIGHT_SM_SPAN, offset: Constants.RIGHT_SM_OFFSET },
553            md: { span: Constants.RIGHT_MD_SPAN, offset: Constants.RIGHT_MD_OFFSET },
554            lg: { span: Constants.RIGHT_LG_SPAN, offset: Constants.RIGHT_LG_OFFSET }
555          })
556          .height(Constants.FULL_HEIGHT)
557      }
558      .height(Constants.FULL_HEIGHT)
559      .width(Constants.FULL_WIDTH)
560      .backgroundColor($r("sys.color.ohos_id_color_sub_background"))
561    }
562  }
563}
564
565@Component
566struct applicationItem {
567  @State applicationItem: any[] = globalThis.allBundleInfo // application info array
568  @State searchResult: boolean = true // search results
569
570  @Builder ListItemLayout(item, index) {
571    ListItem() {
572      Row() {
573        Column() {
574          Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
575            Row() {
576              Image(item.iconId)
577                .customizeImage(Constants.APPLICATION_IMAGE_WIDTH, Constants.APPLICATION_IMAGE_HEIGHT)
578                .margin({ right: Constants.APPLICATION_IMAGE_MARGIN_RIGHT })
579              Text(item.labelId)
580                .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
581                .fontWeight(FontWeight.Medium)
582                .fontColor($r('app.color.label_color'))
583                .flexGrow(Constants.FLEX_GROW)
584              Text(item.groupId.length + '项权限')
585                .fontSize(Constants.TEXT_SMAL_FONT_SIZE)
586                .fontColor($r('app.color.label_color_lighter'))
587                .margin({ right: Constants.APPLICATION_TEXT_MARGIN_RIGHT })
588              Image($r('app.media.ic_public_arrow_right'))
589                .customizeImage(Constants.IMAGE_WIDTH, Constants.IMAGE_HEIGHT)
590            }
591            .width(Constants.FULL_WIDTH)
592            .height(Constants.AUTHORITY_ROW_HEIGHT)
593            .constraintSize({ minHeight: Constants.AUTHORITY_CONSTRAINTSIZE_MINHEIGHT })
594          }
595          if (!index) {
596            Row() {
597              Flex() {
598                Column().width(Constants.APPLICATION_TEXT_DECORATION_MARGIN_LEFT)
599                Column()
600                  .backgroundColor($r('app.color.text_decoration_color'))
601                  .height(Constants.TEXT_DECORATION_HEIGHT)
602                  .flexGrow(Constants.FLEX_GROW)
603              }
604            }
605          }
606        }.onClick(() => {
607          router.pushUrl({
608            url: 'pages/application-secondary',
609            params: { routerData: item }
610          });
611        })
612      }
613    }.padding({
614      left: Constants.DEFAULT_PADDING_START,
615      right: Constants.DEFAULT_PADDING_END
616    })
617  }
618
619  build() {
620    Column() {
621      Row() {
622        textInput({
623          placeholder: String(textInput_placeholder),
624          applicationItem: $applicationItem,
625          searchResult: $searchResult
626        })
627      }.padding({
628        left: Constants.APPLICATION_TEXTINPUT_PADDING_LEFT,
629        top: Constants.APPLICATION_TEXTINPUT_PADDING_TOP,
630        right: Constants.APPLICATION_TEXTINPUT_PADDING_RIGHT
631      })
632      Row() {
633        Flex({ alignItems: ItemAlign.Start }) {
634          Column() {
635            Column() {
636              if (!this.applicationItem.length) {
637                Row() {
638                  Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
639                    Image($r('app.media.searchnoresult'))
640                      .customizeImage(Constants.SEARCHNORESULT_IMAGE_WIDTH, Constants.SEARCHNORESULT_IMAGE_HEIGHT)
641                  }
642                }.margin({ top: Constants.MANAGEMENT_ROW_MARGIN_TOP })
643                .padding({ left: Constants.MANAGEMENT_ROW_PADDING_LEFT })
644              } else {
645                Row() {
646                  Scroll() {
647                    List() {
648                      ForEach(this.applicationItem.slice(Constants.SLICE_START, this.applicationItem.length - 1),
649                        (item) => {
650                          this.ListItemLayout(item, Constants.SLICE_START_INDEX)
651                        }, item => item.toString())
652                      ForEach(this.applicationItem.slice(Constants.SLICE_END), (item) => {
653                        this.ListItemLayout(item, Constants.SLICE_END_INDEX)
654                      }, item => item.toString())
655                    }.backgroundColor($r('app.color.default_background_color'))
656                    .borderRadius(Constants.BORDER_RADIUS)
657                    .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
658                  }.scrollBar(BarState.Off)
659                }.margin({ left: Constants.MANAGEMENT_ROW_PADDING_LEFT })
660                .borderRadius(Constants.BORDER_RADIUS)
661                .clip(true)
662              }
663            }.backgroundColor($r('app.color.background_color'))
664            .height(Constants.FULL_HEIGHT)
665          }.margin({ top: Constants.MANAGEMENT_ROW_MARGIN_TOP, bottom: Constants.APPLICATION_LIST_MARGIN_BOTTOM })
666          Column() {
667            alphabetIndexerComponent({ applicationItem: $applicationItem })
668          }.margin({ top: Constants.APPLICATION_ALPHABETINDEX_MARGIN_TOP })
669          .width(Constants.APPLICATION_ALPHABETINDEX_WIDTH)
670        }
671      }
672    }
673  }
674}
675