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}