• 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 { BusinessError } from '@ohos.base';
22import { Log, verifyAccessToken, indexValue, sortByName } from '../common/utils/utils';
23import { ApplicationObj, PermissionInfo, RouterParams2, PermissionApplications, AppInfo } from '../common/utils/typedef';
24import { GlobalContext } from '../common/utils/globalContext';
25import Constants from '../common/utils/constant';
26import { permissionGroups } from '../common/model/permissionGroup';
27
28@Extend(Image)function customizeImage(width: number, height: number) {
29  .objectFit(ImageFit.Contain)
30  .width(width)
31  .height(height)
32}
33
34@Entry
35@Component
36struct locationInfoPage {
37  private backTitle: ResourceStr = (router.getParams() as RouterParams2).backTitle;
38
39  build() {
40    GridRow({ gutter: Constants.GUTTER, columns: {
41      xs: Constants.XS_COLUMNS, sm: Constants.SM_COLUMNS, md: Constants.MD_COLUMNS, lg: Constants.LG_COLUMNS } }) {
42      GridCol({
43        span: { xs: Constants.XS_SPAN, sm: Constants.SM_SPAN, md: Constants.MD_SPAN, lg: Constants.LG_SPAN },
44        offset: { xs: Constants.XS_OFFSET, sm: Constants.SM_OFFSET, md: Constants.MD_OFFSET, lg: Constants.LG_OFFSET }
45      }) {
46        Row() {
47          Column() {
48            Row() {
49              backBar({ title: JSON.stringify(this.backTitle), recordable: false })
50            }
51            Row() {
52              Column() {
53                applicationItem()
54
55              }.width(Constants.FULL_WIDTH)
56            }
57            .layoutWeight(Constants.LAYOUT_WEIGHT)
58          }
59        }
60        .height(Constants.FULL_HEIGHT)
61        .width(Constants.FULL_WIDTH)
62        .backgroundColor($r('sys.color.background_secondary'))
63      }
64    }.backgroundColor($r('sys.color.background_secondary'))
65  }
66}
67
68@Component
69struct applicationItem {
70  private list: PermissionApplications[] = (router.getParams() as RouterParams2).list;
71  private permissionName: string = (router.getParams() as RouterParams2).permissionName;
72  @State permissionNum: number = Constants.PERMISSION_NUM; // permission num
73  @State toggleIsOn: boolean[] = []; // toggle switch state array
74  @State isRisk: boolean[] = [];
75  @State isFirst: boolean[] = [];
76  @State applicationList: ApplicationObj[] = []; // application info array
77  @State searchResult: boolean = true; // search results
78  @State selectedIndex: number = 0;
79  @State permissionInfo: PermissionInfo = new PermissionInfo('', '', '', 0);
80  @State allBundleInfo: AppInfo[] = GlobalContext.load('allBundleInfo');
81  scroller: Scroller = new Scroller();
82
83  @Builder ListItemLayout(item: ApplicationObj) {
84    ListItem() {
85      Row() {
86        Column() {
87          Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
88            Row() {
89              Image(item.icon)
90                .customizeImage(Constants.AUTHORITY_IMAGE_WIDTH, Constants.AUTHORITY_IMAGE_HEIGHT)
91                .margin({ right: Constants.AUTHORITY_IMAGE_MARGIN_RIGHT })
92              Column() {
93                Text(item.label)
94                  .width(Constants.MAXIMUM_HEADER_WIDTH)
95                  .maxLines(Constants.MAXIMUM_HEADER_LINES)
96                  .textOverflow({ overflow: TextOverflow.Ellipsis })
97                  .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
98                  .fontWeight(FontWeight.Medium)
99                  .fontColor($r('sys.color.font_primary'))
100                if (this.isRisk[item.index]) {
101                  Text($r('app.string.risk_warning'))
102                    .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
103                    .fontColor($r('sys.color.font_secondary'))
104                }
105              }.flexGrow(Constants.FLEX_GROW)
106              .alignItems(HorizontalAlign.Start)
107              Toggle({ type: ToggleType.Switch, isOn: this.toggleIsOn[item.index] })
108                .selectedColor($r('sys.color.icon_emphasize'))
109                .switchPointColor($r('sys.color.comp_background_primary_contrary'))
110                .padding({ right: 0 })
111                .width(Constants.AUTHORITY_TOGGLE_WIDTH)
112                .height(Constants.AUTHORITY_TOGGLE_HEIGHT)
113                .onChange((isOn: boolean) => {
114                  if (item.permission === undefined) {
115                    return;
116                  }
117                  if (this.isFirst[item.index] && isOn) {
118                    this.isFirst[item.index] = false;
119                    return;
120                  }
121                  this.isFirst[item.index] = false;
122                  if (isOn) {
123                    this.grantUserGrantedPermission(item.accessTokenId, item.permission, item.index);
124                  } else {
125                    this.revokeUserGrantedPermission(item.accessTokenId, item.permission, item.index);
126                  }
127                })
128            }
129            .width(Constants.FULL_WIDTH)
130            .height(Constants.AUTHORITY_ROW_HEIGHT)
131            .constraintSize({ minHeight: Constants.AUTHORITY_CONSTRAINTSIZE_MINHEIGHT })
132          }
133        }.onClick(() => {
134        })
135      }
136    }.padding({ left: Constants.DEFAULT_PADDING_START, right: Constants.DEFAULT_PADDING_END })
137    .enabled(!this.isRisk[item.index])
138    .opacity(this.isRisk[item.index] ? $r('sys.float.ohos_id_alpha_disabled') : 1)
139  }
140
141  /**
142   * Grant permissions to the app
143   * @param {Number} accessTokenId
144   * @param {String} permission permission name
145   * @param {Number} index Array index to modify permission status
146   */
147  grantUserGrantedPermission(accessTokenId: number, permission: Permissions, index: number) {
148    abilityAccessCtrl.createAtManager().grantUserGrantedPermission(
149      accessTokenId, permission, Constants.PERMISSION_FLAG).then(() => {
150      // result: 0 Authorization succeeded; result: -1 Authorization failed
151      this.toggleIsOn[index] = true;
152      let num = this.toggleIsOn.filter(item => item === true).length;
153      this.permissionNum = num;
154    }).catch((error: BusinessError) => {
155      this.toggleIsOn[index] = false;
156      Log.error('grantUserGrantedPermission failed. Cause: ' + JSON.stringify(error));
157    })
158  }
159
160  /**
161   * Deauthorize the app
162   * @param {Number} accessTokenId
163   * @param {String} permission permission name
164   * @param {Number} index Array index to modify permission status
165   */
166  revokeUserGrantedPermission(accessTokenId: number, permission: Permissions, index: number) {
167    abilityAccessCtrl.createAtManager().revokeUserGrantedPermission(
168      accessTokenId, permission, Constants.PERMISSION_FLAG).then(() => {
169      // result: 0 successfully cancel the authorization; result: -1 cancel the authorization failed
170      this.toggleIsOn[index] = false;
171      let num = this.toggleIsOn.filter(item => item === true).length;
172      this.permissionNum = num;
173    }).catch(() => {
174      this.toggleIsOn[index] = true;
175    })
176  }
177
178  /**
179   * Lifecycle function, executed when the page is initialized
180   */
181  aboutToAppear() {
182    let bundleNames = this.list.length > 0 ? this.list[0].bundleNames : this.list;
183    permissionGroups.forEach(permission => {
184      if (permission.permissionName === this.permissionName) {
185        this.permissionInfo = permission;
186      }
187    })
188
189    let atManager = abilityAccessCtrl.createAtManager();
190    for (let i = 0; i < bundleNames.length; i++) {
191      // Get BundleInfo based on bundle name
192      this.allBundleInfo.forEach(bundleInfo => {
193        if (bundleInfo.bundleName === bundleNames[i]) {
194          this.applicationList.push(
195            new ApplicationObj(
196              bundleInfo.label,
197              bundleInfo.icon,
198              i,
199              bundleInfo.tokenId,
200              this.list[0].permission,
201              bundleInfo.zhTag,
202              bundleInfo.indexTag,
203              bundleInfo.language) // Get the first letter in the returned initials array
204          );
205          verifyAccessToken(bundleInfo.tokenId, this.list[0].permission).then(data => {
206            // 0: have permission; -1: no permission
207            if (data === Constants.PERMISSION_INDEX) {
208              this.toggleIsOn[i] = true;
209              this.isFirst[i] = true;
210              this.permissionNum++;
211            } else {
212              this.toggleIsOn[i] = false;
213              this.isFirst[i] = false;
214            }
215          })
216          this.isRisk[i] = false;
217          try {
218            atManager.getPermissionFlags(bundleInfo.tokenId, this.list[0].permission).then(data => {
219              if (data == Constants.PERMISSION_POLICY_FIXED) {
220                this.isRisk[i] = true;
221              }
222            })
223          } catch (err) {
224            Log.error('getPermissionFlags error: ' + JSON.stringify(err));
225          }
226        }
227      })
228    }
229  }
230
231  build() {
232    Column() {
233      Row() {
234        textInput({
235          applicationItem: $applicationList,
236          searchResult: $searchResult
237        })
238      }.padding({
239        left: Constants.AUTHORITY_TEXTINPUT_PADDING_LEFT,
240        right: Constants.AUTHORITY_TEXTINPUT_PADDING_RIGHT
241      })
242      Flex({ alignItems:ItemAlign.Start, justifyContent: FlexAlign.Start }) {
243        Column() {
244          Flex({ justifyContent: FlexAlign.Start }) {
245            if (this.permissionNum > 0) {
246              Text(
247                this.permissionInfo.enableDescription ?
248                $r(this.permissionInfo.enableDescription, String(this.permissionNum)) :
249                ''
250              )
251                .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
252                .fontColor($r('sys.color.font_secondary'))
253                .margin({ top: Constants.AUTHORITY_TEXT_MARGIN_TOP })
254            } else {
255              Text(this.permissionInfo.forbiddenDescription)
256                .fontSize(Constants.TEXT_SMALL_FONT_SIZE)
257                .fontColor($r('sys.color.font_secondary'))
258                .margin({ top: Constants.AUTHORITY_TEXT_MARGIN_TOP })
259            }
260          }.padding({ left: Constants.DEFAULT_PADDING_START, right: Constants.DEFAULT_PADDING_END })
261          .margin({ bottom: Constants.AUTHORITY_ROW_MARGIN_BOTTOM })
262          Row() {
263            Column() {
264              if (!this.applicationList.length) {
265                if (this.searchResult) {
266                  Row() {}
267                } else {
268                  Row() {
269                    Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
270                      Image($r('app.media.searchnoresult'))
271                        .customizeImage(Constants.SEARCHNORESULT_IMAGE_WIDTH, Constants.SEARCHNORESULT_IMAGE_HEIGHT)
272                    }
273                  }
274                }
275              } else {
276                Row() {
277                  List({ scroller: this.scroller }) {
278                    ForEach(sortByName(this.applicationList), (item: ApplicationObj) => {
279                      this.ListItemLayout(item)
280                    }, (item: ApplicationObj) => JSON.stringify(item))
281                  }
282                  .backgroundColor($r('sys.color.comp_background_list_card'))
283                  .borderRadius($r('sys.float.ohos_id_corner_radius_card'))
284                  .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
285                  .divider({
286                    strokeWidth: Constants.DIVIDER,
287                    color: $r('sys.color.comp_divider'),
288                    startMargin: Constants.DIVIDER_MARGIN_RIGHT_APPLICATION,
289                    endMargin: Constants.DEFAULT_MARGIN_END
290                  })
291                  .onScrollIndex((start, end) => {
292                    GlobalContext.getContext().set('scroller', this.scroller);
293                    if (this.applicationList.length > 0) {
294                      let alphabeticalIndex = sortByName(this.applicationList)[start].indexTag;
295                      let index = indexValue.indexOf(alphabeticalIndex);
296                      this.selectedIndex = index >= 0 ? index : 0;
297                    }
298                  })
299                }
300              }
301            }.width(Constants.FULL_WIDTH)
302            .margin({ bottom: Constants.AUTHORITY_LIST_MARGIN_BOTTOM })
303          }
304        }.padding({ left: Constants.AUTHORITY_LISTITEM_PADDING_LEFT })
305        Column() {
306          alphabetIndexerComponent({ applicationItem: $applicationList, index: $selectedIndex })
307        }.width(Constants.AUTHORITY_ALPHABETINDEX_WIDTH)
308         .padding({ top: Constants.AUTHORITY_ALPHABETINDEX_PADDING_TOP })
309        .margin({ bottom: Constants.APPLICATION_LIST_MARGIN_BOTTOM })
310      }.flexGrow(Constants.FLEX_GROW)
311    }.height(Constants.FULL_HEIGHT)
312  }
313}
314