• 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, end) {
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 (!end) {
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 extraName: string[] = ['ADS']
415    var fixedGroup: any[] = []
416    var extraGroup: any[] = []
417    var changeGroup: any[] = []
418    var otherGroup: any[] = []
419
420    allGroup.forEach(group => {
421      if(fixedName.indexOf(group.group) !== -1) {
422        fixedGroup.push(group)
423      }else if(extraName.includes(group.group)) {
424        extraGroup.push(group)
425      }else if(group.group == 'OTHER') {
426        otherGroup.push(group)
427      }else {
428        changeGroup.push(group)
429      }
430    })
431
432    if(order == Constants.FIXED_GROUP){
433      return fixedGroup
434    }else if(order == Constants.CHANGE_GROUP) {
435      return changeGroup
436    }else if(order == Constants.OTHER_GROUP) {
437      return otherGroup
438    }else if(order == Constants.EXTRA_GROUP) {
439      return extraGroup
440    }
441  }
442
443  LoadLabelAndIcon() {
444    const this_ = this
445    setTimeout(function() { this_.ready = true }, 100)
446    return true
447  }
448
449  build() {
450    GridContainer({ gutter: Constants.GUTTER, margin: Constants.GRID_MARGIN }) {
451      Row() {
452        Row()
453          .useSizeType({
454            xs: { span: Constants.LEFT_XS_SPAN, offset: Constants.LEFT_XS_OFFSET },
455            sm: { span: Constants.LEFT_SM_SPAN, offset: Constants.LEFT_SM_OFFSET },
456            md: { span: Constants.LEFT_MD_SPAN, offset: Constants.LEFT_MD_OFFSET },
457            lg: { span: Constants.LEFT_LG_SPAN, offset: Constants.LEFT_LG_OFFSET }
458          })
459          .height(Constants.FULL_HEIGHT)
460        Row() {
461          Column() {
462            Row() {
463              backBar( { title: JSON.stringify($r('app.string.authority_management')), recordable: true })
464            }
465            Row() {
466              Column() {
467                Column() {
468                  Stack() {
469                    if(this.allGroupPermission.length) {
470                      Tabs() {
471                        TabContent() {
472                          Row() {
473                            Column() {
474                              Scroll() {
475                                Column() {
476                                  List() {
477                                    ListItem() {
478                                      List() {
479                                        ForEach(this.getPermissionGroup(this.allGroupPermission, Constants.FIXED_GROUP), (item, index) => {
480                                          this.ListItemLayout(item, index == (this.getPermissionGroup(this.allGroupPermission, Constants.FIXED_GROUP).length - 1))
481                                        }, item => item.toString())
482                                      }.backgroundColor($r('app.color.default_background_color'))
483                                      .borderRadius(Constants.BORDER_RADIUS)
484                                      .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
485                                      .margin({ bottom: Constants.LIST_MARGIN_BOTTOM })
486                                    }
487
488                                    ListItem() {
489                                      List() {
490                                        ForEach(this.getPermissionGroup(this.allGroupPermission, Constants.CHANGE_GROUP), (item, index) => {
491                                          this.ListItemLayout(item, index == (this.getPermissionGroup(this.allGroupPermission, Constants.CHANGE_GROUP).length - 1))
492                                        }, item => item.toString())
493                                      }.backgroundColor($r('app.color.default_background_color'))
494                                      .borderRadius(Constants.BORDER_RADIUS)
495                                      .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
496                                      .margin({ bottom: Constants.LIST_MARGIN_BOTTOM })
497                                    }
498
499                                    if(this.getPermissionGroup(this.allGroupPermission, Constants.EXTRA_GROUP).length) {
500                                      ListItem() {
501                                        List() {
502                                          ForEach(this.getPermissionGroup(this.allGroupPermission, Constants.EXTRA_GROUP), (item, index) => {
503                                            this.ListItemLayout(item, index == (this.getPermissionGroup(this.allGroupPermission, Constants.EXTRA_GROUP).length - 1))
504                                          }, item => item.toString())
505                                        }.backgroundColor($r('app.color.default_background_color'))
506                                        .borderRadius(Constants.BORDER_RADIUS)
507                                        .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
508                                        .margin({ bottom: Constants.LIST_MARGIN_BOTTOM })
509                                      }
510                                    }
511
512                                    ListItem() {
513                                      if(this.LoadLabelAndIcon()) {}
514                                      List() {
515                                        ForEach(this.getPermissionGroup(this.allGroupPermission, Constants.OTHER_GROUP), (item) => {
516                                          this.ListItemLayout(item, Constants.SLICE_END_INDEX)
517                                        }, item => item.toString())
518                                      }.backgroundColor($r('app.color.default_background_color'))
519                                      .borderRadius(Constants.BORDER_RADIUS)
520                                      .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
521                                    }
522                                  }.height(Constants.FULL_HEIGHT)
523                                  .borderRadius(Constants.BORDER_RADIUS)
524                                  .clip(true)
525                                }.padding({
526                                  left: Constants.MANAGEMENT_ROW_PADDING_LEFT,
527                                  right: Constants.MANAGEMENT_ROW_PADDING_RIGHT,
528                                })
529                              }.scrollBar(BarState.Off)
530                              .margin({ top: Constants.MANAGEMENT_ROW_PADDING_TOP })
531                            }.width(Constants.FULL_WIDTH)
532                          }
533                        }.tabBar(this.TabBuilder(0))
534                        TabContent() {
535                          applicationItem()
536                        }.tabBar(this.TabBuilder(1))
537                      }
538                      .barWidth(Constants.BAR_WIDTH)
539                      .barMode(BarMode.Fixed)
540                      .onChange((index) => {
541                        this.currentIndex = index
542                      })
543                    }else {
544                      LoadingProgress().width(Constants.LOADING_WIDTH)
545                    }
546                  }.height(Constants.FULL_HEIGHT)
547                }
548              }
549            }
550            .layoutWeight(Constants.LAYOUT_WEIGHT)
551          }
552        }
553        .useSizeType({
554          xs: { span: Constants.MIDDLE_XS_SPAN, offset: Constants.MIDDLE_XS_OFFSET },
555          sm: { span: Constants.MIDDLE_SM_SPAN, offset: Constants.MIDDLE_SM_OFFSET },
556          md: { span: Constants.MIDDLE_MD_SPAN, offset: Constants.MIDDLE_MD_OFFSET },
557          lg: { span: Constants.MIDDLE_LG_SPAN, offset: Constants.MIDDLE_LG_OFFSET }
558        })
559        .height(Constants.FULL_HEIGHT)
560        Row()
561          .useSizeType({
562            xs: { span: Constants.RIGHT_XS_SPAN, offset: Constants.RIGHT_XS_OFFSET },
563            sm: { span: Constants.RIGHT_SM_SPAN, offset: Constants.RIGHT_SM_OFFSET },
564            md: { span: Constants.RIGHT_MD_SPAN, offset: Constants.RIGHT_MD_OFFSET },
565            lg: { span: Constants.RIGHT_LG_SPAN, offset: Constants.RIGHT_LG_OFFSET }
566          })
567          .height(Constants.FULL_HEIGHT)
568      }
569      .height(Constants.FULL_HEIGHT)
570      .width(Constants.FULL_WIDTH)
571      .backgroundColor($r("sys.color.ohos_id_color_sub_background"))
572    }
573  }
574}
575
576@Component
577struct applicationItem {
578  @State applicationItem: any[] = globalThis.allBundleInfo // application info array
579  @State searchResult: boolean = true // search results
580
581  @Builder ListItemLayout(item, end) {
582    ListItem() {
583      Row() {
584        Column() {
585          Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
586            Row() {
587              Image(item.iconId)
588                .customizeImage(Constants.APPLICATION_IMAGE_WIDTH, Constants.APPLICATION_IMAGE_HEIGHT)
589                .margin({ right: Constants.APPLICATION_IMAGE_MARGIN_RIGHT })
590              Text(item.labelId)
591                .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
592                .fontWeight(FontWeight.Medium)
593                .fontColor($r('app.color.label_color'))
594                .flexGrow(Constants.FLEX_GROW)
595              Text(item.groupId.length + '项权限')
596                .fontSize(Constants.TEXT_SMAL_FONT_SIZE)
597                .fontColor($r('app.color.label_color_lighter'))
598                .margin({ right: Constants.APPLICATION_TEXT_MARGIN_RIGHT })
599              Image($r('app.media.ic_public_arrow_right'))
600                .customizeImage(Constants.IMAGE_WIDTH, Constants.IMAGE_HEIGHT)
601            }
602            .width(Constants.FULL_WIDTH)
603            .height(Constants.AUTHORITY_ROW_HEIGHT)
604            .constraintSize({ minHeight: Constants.AUTHORITY_CONSTRAINTSIZE_MINHEIGHT })
605          }
606          if (!end) {
607            Row() {
608              Flex() {
609                Column().width(Constants.APPLICATION_TEXT_DECORATION_MARGIN_LEFT)
610                Column()
611                  .backgroundColor($r('app.color.text_decoration_color'))
612                  .height(Constants.TEXT_DECORATION_HEIGHT)
613                  .flexGrow(Constants.FLEX_GROW)
614              }
615            }
616          }
617        }.onClick(() => {
618          globalThis.applicationInfo = item
619          router.pushUrl({ url: 'pages/application-secondary' });
620        })
621      }
622    }.padding({
623      left: Constants.DEFAULT_PADDING_START,
624      right: Constants.DEFAULT_PADDING_END
625    })
626  }
627
628  build() {
629    Column() {
630      Row() {
631        textInput({
632          placeholder: String(textInput_placeholder),
633          applicationItem: $applicationItem,
634          searchResult: $searchResult
635        })
636      }.padding({
637        left: Constants.APPLICATION_TEXTINPUT_PADDING_LEFT,
638        top: Constants.APPLICATION_TEXTINPUT_PADDING_TOP,
639        right: Constants.APPLICATION_TEXTINPUT_PADDING_RIGHT
640      })
641      Row() {
642        Flex({ alignItems: ItemAlign.Start }) {
643          Column() {
644            Column() {
645              if (!this.applicationItem.length) {
646                Row() {
647                  Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
648                    Image($r('app.media.searchnoresult'))
649                      .customizeImage(Constants.SEARCHNORESULT_IMAGE_WIDTH, Constants.SEARCHNORESULT_IMAGE_HEIGHT)
650                  }
651                }.margin({ top: Constants.MANAGEMENT_ROW_MARGIN_TOP })
652                .padding({ left: Constants.MANAGEMENT_ROW_PADDING_LEFT })
653              } else {
654                Row() {
655                  Scroll() {
656                    List() {
657                      ForEach(this.applicationItem, (item, index) => {
658                        this.ListItemLayout(item, index == (this.applicationItem.length - 1))
659                        }, item => item.toString())
660                    }.backgroundColor($r('app.color.default_background_color'))
661                    .borderRadius(Constants.BORDER_RADIUS)
662                    .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
663                  }.scrollBar(BarState.Off)
664                }.margin({ left: Constants.MANAGEMENT_ROW_PADDING_LEFT })
665                .borderRadius(Constants.BORDER_RADIUS)
666                .clip(true)
667              }
668            }.backgroundColor($r('app.color.background_color'))
669            .height(Constants.FULL_HEIGHT)
670          }.margin({ top: Constants.MANAGEMENT_ROW_MARGIN_TOP, bottom: Constants.APPLICATION_LIST_MARGIN_BOTTOM })
671          Column() {
672            alphabetIndexerComponent({ applicationItem: $applicationItem })
673          }.margin({ top: Constants.APPLICATION_ALPHABETINDEX_MARGIN_TOP })
674          .width(Constants.APPLICATION_ALPHABETINDEX_WIDTH)
675        }
676      }
677    }
678  }
679}
680