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 { Callback } from '@ohos.base';
17import Router from '@system.router';
18import deviceInfo from '@ohos.deviceInfo';
19import bundle from '@ohos.bundle.bundleManager';
20import Want from '@ohos.app.ability.Want';
21import { BaseData } from '../../../../../../common/utils/src/main/ets/default/bean/BaseData';
22import LogUtil from '../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
23import { GlobalContext } from '../../../../../../common/utils/src/main/ets/default/baseUtil/GlobalContext';
24import ApplicationInfoController from '../controller/application/ApplicationInfoController';
25import ConfigData from '../../../../../../common/utils/src/main/ets/default/baseUtil/ConfigData';
26import HeadComponent from '../../../../../../common/component/src/main/ets/default/headComponent';
27import EntryComponent from '../../../../../../common/component/src/main/ets/default/entryComponent';
28import { DialogButtonLayout } from '../../../../../../common/component/src/main/ets/default/dialogComponent';
29import AppManagementModel from '../model/appManagementImpl/AppManagementModel';
30
31const MODULE_TAG = ConfigData.TAG + 'application-> ';
32const deviceTypeInfo = deviceInfo.deviceType;
33
34/**
35 * Application Info
36 */
37@Entry
38@Component
39struct ApplicationInfo {
40  tag: string = "ApplicationInfoSettings";
41  @StorageLink('appInformation') appInfo: BaseData = {
42    settingIcon: "",
43    settingTitle: "",
44    settingValue: "",
45    settingArrow: "",
46    settingSummary: "",
47    settingBundleName: "",
48    settingIconId: "",
49    settingUri: ""
50  };
51  @StorageLink('appManagement') mBundleInfoList: BaseData[] = [];
52  @State isPhoneOrRK: boolean = false;
53  @State isRemovableBundle: boolean = true;
54  @State isTouchedLeft: boolean = false;
55  @State isTouchedRight: boolean = false;
56  private controller: ApplicationInfoController = new ApplicationInfoController();
57  private bundleName: string = " ";
58  showDialog: CustomDialogController | null = new CustomDialogController({
59    builder: ShowDialog({
60      action: () => {
61        this.controller.uninstall(this.bundleName);
62      }
63    }),
64    alignment: this.isPhoneOrRK ? DialogAlignment.Bottom : DialogAlignment.Center,
65    autoCancel: true,
66    offset: ({ dx: 0, dy: this.isPhoneOrRK ? '-24dp' : 0 })
67  });
68
69  build() {
70    Column() {
71      GridContainer({ gutter: ConfigData.GRID_CONTAINER_GUTTER_24, margin: ConfigData.GRID_CONTAINER_MARGIN_24 }) {
72        Column() {
73          HeadComponent({ headName: $r('app.string.applicationInfo'), isActive: true });
74
75          Row() {
76            Image(this.appInfo.settingIcon)
77              .width($r('app.float.wh_value_64'))
78              .height($r('app.float.wh_value_64'))
79              .margin({ right: $r('app.float.distance_16'), left: $r('sys.float.ohos_id_card_margin_start') })
80
81            Column() {
82              Text(this.appInfo.settingTitle)
83                .fontColor($r('app.color.font_color_182431'))
84                .fontSize($r('app.float.font_16'))
85                .margin({ top: $r('app.float.wh_value_10'), bottom: $r('app.float.wh_value_5') })
86
87              Text(this.appInfo.settingSummary)
88                .fontColor($r('app.color.font_color_182431'))
89                .fontSize($r('app.float.font_14'))
90                .maxLines(ConfigData.MAX_LINES_1)
91                .margin({ bottom: $r('app.float.distance_11') });
92            }
93            .alignItems(HorizontalAlign.Start)
94            .width(ConfigData.WH_100_100)
95            .height($r('app.float.wh_value_64'))
96          }
97          .width(ConfigData.WH_100_100)
98          .margin({ top: $r("app.float.distance_8") })
99
100          Row() {
101            Button($r('app.string.uninstall'))
102              .fontSize($r('app.float.application_button_subtitle_size'))
103              .fontColor($r('app.color.font_color_007DFF'))
104              .layoutWeight(ConfigData.LAYOUT_WEIGHT_1)
105              .height($r('app.float.application_button_height'))
106              .visibility(this.isRemovableBundle ? Visibility.Visible : Visibility.Hidden)
107              .borderRadius($r('app.float.radius_20'))
108              .backgroundColor($r('sys.color.ohos_id_color_button_normal'))
109              .onClick(() => {
110                this.showDialog?.open();
111              })
112
113            Column()
114              .width($r('app.float.distance_24'))
115              .height($r('app.float.application_button_height'))
116
117            Button($r('app.string.forcedStop'))
118              .fontSize($r('app.float.application_button_subtitle_size'))
119              .fontColor($r('app.color.font_color_007DFF'))
120              .layoutWeight(ConfigData.LAYOUT_WEIGHT_1)
121              .height($r('app.float.application_button_height'))
122              .borderRadius($r('app.float.radius_20'))
123              .backgroundColor($r('sys.color.ohos_id_color_button_normal'))
124              .onClick(() => {
125                this.showPromptDialog(() => {
126                  this.controller.killProcessesByBundleName(this.bundleName);
127                });
128              })
129          }
130          .alignItems(VerticalAlign.Center)
131          .width(ConfigData.WH_100_100)
132          .padding({
133            top: $r('app.float.distance_24'),
134            bottom: $r('app.float.distance_36'),
135            left: $r('app.float.distance_24'),
136            right: $r('app.float.distance_24')
137          })
138
139          Row() {
140            EntryComponent({
141              settingIcon: '',
142              settingTitle: $r('app.string.storageTab'),
143              settingSummary: JSON.parse(JSON.stringify($r('app.string.store_description_information', ''))),
144              settingValue: '',
145              settingArrow: $r("app.string.ic_settings_arrow").toString(),
146              settingArrowStyle: '',
147              settingUri: '',
148              fontSize: $r('app.float.font_16'),
149              valueFontSize: $r('app.float.font_14')
150            })
151          }
152          .padding({ top: $r('app.float.distance_4'), bottom: $r('app.float.distance_4') })
153          .borderRadius($r('sys.float.ohos_id_corner_radius_default_l'))
154          .backgroundColor($r('app.color.white_bg_color'))
155          .onClick(() => {
156            Router.push({ uri: 'pages/applicationStorage', params: this.appInfo });
157          })
158        }
159        .useSizeType({
160          sm: { span: 4, offset: 0 },
161          md: { span: 6, offset: 1 },
162          lg: { span: 8, offset: 2 }
163        })
164      }
165      .width(ConfigData.WH_100_100)
166      .height(ConfigData.WH_100_100)
167    }
168    .backgroundColor($r("sys.color.ohos_id_color_sub_background"))
169    .width(ConfigData.WH_100_100)
170    .height(ConfigData.WH_100_100)
171  }
172
173  aboutToAppear(): void {
174    LogUtil.info(this.tag + " aboutToAppear start ");
175    if (deviceTypeInfo === 'phone' || deviceTypeInfo === 'default') {
176      this.isPhoneOrRK = true;
177    } else {
178      this.isPhoneOrRK = false;
179    }
180
181    this.getBundleName();
182    this.updateRemovableStatus(this.bundleName);
183    LogUtil.info(this.tag + " aboutToAppear end ");
184  }
185
186  aboutToDisappear(): void {
187    this.showDialog = null;
188  }
189
190  getBundleName(): void {
191    let param = Router.getParams();
192    if (param) {
193      this.bundleName = param.settingBundleName.toString();
194      this.appInfo = param;
195      AppStorage.SetOrCreate('appInformation', param);
196    }
197
198    if (this.bundleName == ' ') {
199      let want = GlobalContext.getContext().getObject(GlobalContext.globalKeyAbilityWant) as Want;
200      if (want?.action === 'action.settings.app.info') {
201        this.bundleName = want?.parameters?.settingsParamBundleName as string;
202        let bundleList: bundle.BundleInfo[] = [];
203        bundle.getBundleInfo(this.bundleName, bundle.BundleFlag.GET_BUNDLE_INFO_WITH_ABILITY)
204          .then((data) => {
205            bundleList[0] = data;
206            AppManagementModel.getResourceItem(0, 1, bundleList)
207              .then(() => {
208                let appMgrList = AppStorage.Get('appManagementList') as BaseData[];
209                if (appMgrList) {
210                  this.mBundleInfoList = appMgrList;
211                }
212                this.appInfo = this.mBundleInfoList[0];
213                AppStorage.SetOrCreate('appInformation', this.mBundleInfoList[0]);
214              })
215          });
216      }
217    }
218  }
219
220  onBackPress() {
221    LogUtil.info('settings ApplicationInfo onBackPress');
222  }
223
224  /**
225   * Stop exception prompt Dialog
226   */
227  showPromptDialog(callback: Callback<void>) {
228    AlertDialog.show({
229      message: $r("app.string.Stop_exception_prompt"),
230      primaryButton: {
231        value: $r('app.string.cancel'),
232        action: () => {
233          LogUtil.info(ConfigData.TAG + 'Closed callbacks');
234        }
235      },
236      secondaryButton: {
237        value: $r('app.string.forcedStop'),
238        action: () => {
239          LogUtil.info(ConfigData.TAG + `AlertDialog success:`);
240          callback();
241        }
242      },
243      alignment: this.isPhoneOrRK ? DialogAlignment.Bottom : DialogAlignment.Center,
244      offset: ({ dx: 0, dy: this.isPhoneOrRK ? '-24dp' : 0 })
245    })
246  }
247
248  updateRemovableStatus(bundleName: string) {
249    this.controller.getBundleInfo(bundleName, (err: Error, result: bundle.BundleInfo) => {
250      if (err) {
251        LogUtil.info(MODULE_TAG + 'get system bundle info failed');
252      } else {
253        LogUtil.info(MODULE_TAG + `${bundleName} is removeable = ${result.appInfo.removable}`);
254        if (result.appInfo.removable !== true) {
255          this.isRemovableBundle = false;
256        }
257      }
258    });
259  }
260}
261
262/**
263 * Show dialog
264 */
265@CustomDialog
266struct ShowDialog {
267  dialogController?: CustomDialogController;
268  @StorageLink('appInformation') appInfo: BaseData = {
269    settingIcon: "",
270    settingTitle: "",
271    settingValue: "",
272    settingArrow: "",
273    settingSummary: "",
274    settingBundleName: "",
275    settingIconId: "",
276    settingUri: ""
277  };
278  private uirBack: string = 'pages/appManagement';
279  action: () => void = () => {
280  };
281
282  build() {
283    Column() {
284      Image(`${this.appInfo.settingIcon}`)
285        .height($r("app.float.application_common_size"))
286        .width($r("app.float.application_common_size"))
287        .margin({
288          top: $r('app.float.item_common_vertical_margin'),
289          bottom: $r('app.float.item_common_vertical_margin')
290        })
291
292      Text(`${this.appInfo.settingTitle}`)
293        .fontSize($r('app.float.font_18'))
294        .align(Alignment.Center)
295        .margin({ bottom: $r('app.float.item_common_vertical_margin') })
296
297      Text($r("app.string.uninstall_prompt"))
298        .fontSize($r('app.float.font_18'))
299        .align(Alignment.Center)
300        .margin({ bottom: $r('app.float.item_common_vertical_margin') })
301
302      // button
303      DialogButtonLayout({
304        secondTitle: $r('app.string.uninstall'),
305        firstClickEvent: () => {
306          if (this.dialogController) {
307            this.dialogController.close();
308          }
309        },
310        secondClickEvent: () => {
311          this.action();
312          if (this.dialogController) {
313            this.dialogController.close();
314          }
315          Router.back({ uri: this.uirBack });
316        }
317      })
318    }
319    .alignItems(HorizontalAlign.Center)
320    .width(ConfigData.WH_100_100);
321  }
322}