• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Copyright (c) 2025-2025 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 */
15import { WidthPercent } from '../common/util/ConfigData';
16import CmAppCredAuthPresenter from '../presenter/CmAppCredAuthPresenter';
17import { common, UIExtensionContentSession } from '@kit.AbilityKit';
18import { CMModelErrorCode, DialogErrorCode } from '../model/CertMangerModel';
19import { CredentialAbstractVo } from '../model/CertManagerVo/CredentialAbstractVo';
20import { LengthUnit } from '@kit.ArkUI';
21import hilog from '@ohos.hilog'
22
23const DOMAIN = 0x0000;
24const TAG = 'RequestAuthSheet';
25function hilogInfo(message: string): void {
26  hilog.info(DOMAIN, TAG, message);
27}
28function hilogError(message: string): void {
29  hilog.error(DOMAIN, TAG, message);
30}
31
32let storage = LocalStorage.getShared();
33
34@Entry(storage)
35@Component
36struct RequestAuthSheet {
37  private session: UIExtensionContentSession =
38    storage?.get<UIExtensionContentSession>('session') as UIExtensionContentSession;
39  private want : Want = storage?.get<Want>('want') as Want;
40  private resultCode: number = -1;
41  private appUid: string = '';
42  @State private selectUri: string = ''
43  @State private mAppCredAuthPresenter: CmAppCredAuthPresenter = CmAppCredAuthPresenter.getInstance();
44  @State private isDisplaySheet: boolean = true;
45  @State private bottomRectHeight: Length = 0;
46  @State private buttonHeight: Length = 40;
47  @State private isExtraLargeFontMode: boolean = false;
48  @State private isAuthBtnOverflow: boolean = false;
49  @State private hoverItemUri: string = '';
50  @State private listPadding: Resource = $r('sys.float.padding_level4');
51
52  aboutToAppear() {
53    let parameters = this.want.parameters;
54    if (parameters === undefined || parameters === null) {
55      hilogError(`parameters is undefinde`);
56      return;
57    }
58    let callerBundleName: string = parameters['bundleName'] as string;
59    if (callerBundleName == null || callerBundleName.length === 0) {
60      hilogError(`bundleName is empty`);
61      return;
62    }
63    hilogInfo(`USER_CERD_GRANT_APP ${callerBundleName}`);
64    this.appUid = parameters['appUid'].toString();
65    if (this.appUid != null && this.appUid.length > 0) {
66      this.mAppCredAuthPresenter.updateAppNameFromUid(this.appUid);
67      this.mAppCredAuthPresenter.updateAppCredList((code: CMModelErrorCode) => {
68        if (code === CMModelErrorCode.CM_MODEL_ERROR_EXCEPTION) {
69          this.session.terminateSelfWithResult({resultCode: DialogErrorCode.DIALOG_ERROR_INTERNAL});
70        }
71      })
72    } else {
73      hilogError(`request auth appear failed`);
74      this.session.terminateSelfWithResult({resultCode: DialogErrorCode.DIALOG_ERROR_PARAM_INVALID});
75    }
76  }
77
78  private requestAuth() {
79    hilogInfo(`USER_CERD_GRANT_APP_SEL_CONFIRM authorize`);
80    if (this.appUid != null && this.appUid.length > 0 && this.selectUri != null && this.selectUri.length > 0) {
81      this.mAppCredAuthPresenter.sheetRequestAuthorize(this.selectUri, this.appUid,
82        (errCode: CMModelErrorCode, data: string) => {
83          if (errCode === CMModelErrorCode.CM_MODEL_ERROR_SUCCESS) {
84            this.session?.sendData({ 'uri': data });
85          } else {
86            this.resultCode = DialogErrorCode.DIALOG_ERROR_INTERNAL;
87            this.isDisplaySheet = false;
88          }
89        });
90    } else {
91      this.session.terminateSelfWithResult({resultCode: DialogErrorCode.DIALOG_ERROR_PARAM_INVALID});
92    }
93  }
94
95  @Builder
96  private buildSheetTitle() {
97    Row() {
98      Text($r('app.string.pickCredToAuth'))
99        .fontWeight(FontWeight.Bold)
100        .fontSize($r('sys.float.ohos_id_text_size_headline8'))
101        .fontColor($r('sys.color.font_primary'))
102        .textOverflow({ overflow: TextOverflow.Ellipsis})
103        .maxLines(1)
104        .maxFontScale(1)
105    }
106    .width(WidthPercent.WH_100_100)
107    .constraintSize({
108      minHeight: $r('app.float.wh_value_56')
109    })
110    .justifyContent(FlexAlign.Start)
111  }
112
113  @Builder
114  private buildOptBtn() {
115    Column() {
116      Button() {
117        Text($r('app.string.requestAuthFinish'))
118          .fontWeight(FontWeight.Medium)
119          .fontSize($r('sys.float.Body_L'))
120          .fontColor($r('sys.color.font_emphasize'))
121          .maxLines(1)
122          .textOverflow({ overflow: TextOverflow.Ellipsis})
123      }
124      .buttonStyle(ButtonStyleMode.NORMAL)
125      .type(ButtonType.ROUNDED_RECTANGLE)
126      .width('100%')
127      .constraintSize({
128        minHeight: $r('app.float.wh_value_40')
129      })
130      .onClick(() => {
131        this.requestAuth();
132      })
133    }
134    .width('100%')
135    .margin({
136      top: $r('app.float.wh_value_16'),
137      bottom: $r('app.float.wh_value_16'),
138    })
139    .justifyContent(FlexAlign.SpaceBetween)
140  }
141
142  @Builder
143  private buildSheetContent() {
144    Column() {
145      Scroll() {
146        Column() {
147          Column() {
148            Text($r('app.string.requestAuthMsg', this.mAppCredAuthPresenter.appName))
149              .fontSize($r('sys.float.ohos_id_text_size_body1'))
150              .fontColor($r('sys.color.ohos_id_color_text_primary'))
151              .fontWeight(FontWeight.Regular)
152              .alignSelf(ItemAlign.Start)
153          }
154          .width('100%')
155          .padding({ left: 12, right: 12 })
156          .margin({ top: 8, bottom: 8 })
157
158          List() {
159            ForEach(this.mAppCredAuthPresenter.credList, (item: CredentialAbstractVo) => {
160              ListItem() {
161                Column() {
162                  Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
163                    Column() {
164                      Text(item.alias)
165                        .fontSize($r('app.float.font_18'))
166                        .fontColor($r('sys.color.ohos_id_color_text_primary'))
167                        .fontWeight(FontWeight.Medium)
168                        .textAlign(TextAlign.Start);
169                    }
170                    .alignItems(HorizontalAlign.Start)
171                    .padding({ top: this.listPadding, bottom: this.listPadding })
172
173                    Row() {
174                      Blank().width(8)
175                      Radio({ value: item.alias, group: 'appCredGroup' })
176                        .height(24)
177                        .width(24)
178                        .checked(this.selectUri === item.keyUri)
179                        .onChange((value: boolean) => {
180                          if (value && this.selectUri !== item.keyUri) {
181                            this.selectUri = item.keyUri;
182                          }
183                        })
184                    }
185                  }
186                  .width(WidthPercent.WH_100_100)
187                }
188              }
189              .constraintSize({
190                minHeight: 48
191              })
192              .onClick(() => {
193                if (this.selectUri !== item.keyUri) {
194                  this.selectUri = item.keyUri;
195                }
196              })
197              .padding({ left: 8, right: 8 })
198              .borderRadius(16)
199              .stateStyles({
200                normal: {
201                  .backgroundColor(this.hoverItemUri === item.keyUri ? $r('sys.color.interactive_hover') :
202                  Color.Transparent)
203                },
204                pressed: {
205                  .backgroundColor($r('sys.color.interactive_pressed'))
206                }
207              })
208              .onHover((isHover: boolean) => {
209                if (isHover) {
210                  this.hoverItemUri = item.keyUri;
211                } else {
212                  this.hoverItemUri = '';
213                }
214              })
215              .focusBox({
216                margin: {
217                  value: -2,
218                  unit: LengthUnit.VP
219                }
220              })
221            }, (item: CredentialAbstractVo) => JSON.stringify(item) )
222          }
223          .divider({
224            strokeWidth: '1px',
225            color: $r('sys.color.ohos_id_color_list_separator'),
226            startMargin: 8,
227            endMargin: 8
228          })
229          .padding({
230            top: 4,
231            bottom: 4,
232            left: 4,
233            right: 4
234          })
235          .borderRadius(10)
236          .backgroundColor($r('sys.color.ohos_id_color_list_card_bg'))
237          .scrollBar(BarState.Off)
238          .nestedScroll({
239            scrollForward: NestedScrollMode.PARENT_FIRST,
240            scrollBackward: NestedScrollMode.SELF_FIRST,
241          })
242          .visibility(this.mAppCredAuthPresenter.credList.length > 0 ? Visibility.Visible : Visibility.None)
243        }
244        .width('100%')
245      }
246      .scrollable(ScrollDirection.Vertical)
247      .scrollBar(BarState.Auto)
248      .align(Alignment.Top)
249      .width('100%')
250      .height(`calc(100% - ${this.buttonHeight}vp)`)
251
252      Column() {
253        this.buildOptBtn()
254      }
255      .width('100%')
256      .onAreaChange((oldValue: Area, newValue: Area) => {
257        this.buttonHeight = newValue.height;
258      })
259    }
260    .padding({ left: 16, right: 16, bottom: this.bottomRectHeight })
261    .height('100%')
262    .justifyContent(FlexAlign.SpaceBetween)
263  }
264
265  build() {
266    Column() {
267      Column() {
268      }
269      .bindSheet(this.isDisplaySheet, this.buildSheetContent, {
270        height: '100%',
271        title: this.buildSheetTitle,
272        showClose: true,
273        onDisappear: () => {
274          this.session.terminateSelfWithResult({resultCode: this.resultCode});
275        }
276      })
277    }
278  }
279}