1/* 2 * Copyright (c) 2024 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 UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; 17import { EditableLeftIconType } from '@ohos.arkui.advanced.EditableTitleBar'; 18import { EditableTitleBar } from '@ohos.arkui.advanced.EditableTitleBar'; 19import ConnectService from '../common/share/ConnectService'; 20import { LengthMetrics } from '@ohos.arkui.node'; 21import dlpPermission from '@ohos.dlpPermission'; 22import promptAction from '@ohos.promptAction'; 23import { BusinessError } from '@ohos.base'; 24import Want from '@ohos.app.ability.Want'; 25import fs from '@ohos.file.fs'; 26import systemParameterEnhance from '@ohos.systemParameterEnhance'; 27import emitter from '@ohos.events.emitter'; 28import { HiLog } from '../common/HiLog'; 29import Constants from '../common/constant'; 30import FileUtils, { FileMsg } from '../common/FileUtils'; 31import { 32 getFileUriByPath, 33 getFileFd, 34 sendDlpFileCreateProperties, 35 getFileSizeByUri, 36 sendDlpManagerAccountLogin, 37 getAppId, 38 getOsAccountInfo, 39 getConnectionStatus 40} from '../common/utils'; 41import { SystemUtils } from '../common/systemUtils'; 42import FontSizeScale from '../common/FontSizeScale'; 43import { contact } from '@kit.ContactsKit'; 44import deviceInfo from '@ohos.deviceInfo'; 45 46const TAG = 'Share'; 47 48class Test { 49 public '0': number = 0; 50 public '1': number = 0; 51 public '4': string = ''; 52} 53 54class AuthUserList { 55 public authAccount: string = ''; 56 public authAccountType: number = 0; 57 public dlpFileAccess: number = 0; 58 public permExpiryTime: number = 0; 59} 60 61let defaultDlpProperty: dlpPermission.DLPProperty = { 62 ownerAccount: '', 63 ownerAccountType: dlpPermission.AccountType.CLOUD_ACCOUNT, 64 authUserList: [], 65 contactAccount: '', 66 offlineAccess: true, 67 ownerAccountID: '', 68 everyoneAccessList: [] 69}; 70 71let storage = LocalStorage.getShared(); 72 73@Entry(storage) 74@Component 75struct encryptedSharing { 76 static readonly GET_ACCOUNT_INFO_RESET = 'clear'; 77 private connectService: ConnectService = new ConnectService(getContext(this)); 78 private isPhoneDevice: boolean = true; 79 @State titlebarMargin: LocalizedMargin = { 80 start: LengthMetrics.vp(Constants.SHARE_TITLE_HEAD_MARGIN_RIGHT), 81 end: LengthMetrics.vp(Constants.SHARE_TITLE_HEAD_MARGIN_RIGHT), 82 }; 83 @LocalStorageLink('commandSearchUserInfo') @Watch('beginToGenerateDLPFile') isInputInvalid: string = ''; 84 @LocalStorageLink('commandGetAccountInfo') @Watch('changeAccountInfo') commandGetAccountInfo: string = ''; 85 @State dlpProperty: dlpPermission.DLPProperty = defaultDlpProperty; 86 @State enabledFocus: boolean = true; 87 @State isConfirmButtonEnabled: boolean = false; 88 @State isShowSheet: boolean = false; 89 @State showUIExtensionForAccountLogin: boolean = false; 90 @State actionWant: Want | undefined = storage.get<Want>('actionWant'); 91 @State inputValue: string = ''; 92 @State phoneFormatTips: boolean = false; 93 @State ownerAccount: string = ''; 94 @State ownerAccountID: string = ''; 95 @State contactExists: boolean = true; 96 @State credentialCallBackMsg: string | Resource = ''; 97 @State session: UIExtensionContentSession | undefined = 98 storage === undefined ? undefined : storage.get<UIExtensionContentSession>('session'); 99 @State placeHolderStr: ResourceStr = ''; 100 @State contactPerson: string = ''; 101 @State recordSuccessUid: string = ''; 102 @State osVersion: ResourceStr = ''; 103 @State isTextInputFocus: boolean = false; 104 @State generalType: string = 'general.file'; 105 @State scrollHeight: number = 188; 106 107 @Builder 108 contactsPicker() { 109 Column() { 110 UIExtensionComponent({ 111 bundleName: 'com.ohos.contacts', 112 abilityName: 'ContactUiExtentionAbility', 113 parameters: { 114 'ability.want.params.uiExtensionType': 'sys/commonUI', 115 'targetUrl': 'BatchSelectContactsPage', 116 'isContactMultiSelect': false, 117 } 118 }) 119 .onRelease((code) => { 120 }) 121 .onResult((data) => { 122 }) 123 .onReceive((data) => { 124 try { 125 let params: [] = JSON.parse((data.want as Want)?.parameters?.contactObjects as string); 126 for (let i = 0; i < params.length; i++) { 127 this.inputValue = (params[i] as Record<string, string>)?.telephone; 128 } 129 } catch (error) { 130 HiLog.error(TAG, `json parse exception, error is ${JSON.stringify(error)}`); 131 } 132 this.isShowSheet = false; 133 }) 134 .width(Constants.CONTACTS_PICKER_WIDTH) 135 .height(Constants.CONTACTS_PICKER_HEIGHT) 136 .hitTestBehavior(HitTestMode.Block) 137 } 138 .width(Constants.CONTACTS_PICKER_WIDTH) 139 .height(Constants.CONTACTS_PICKER_HEIGHT) 140 } 141 142 contactsAction = () => { 143 if (this.isPhoneDevice) { 144 contact.selectContacts({ isMultiSelect: false }).then((data) => { 145 HiLog.info(TAG, 'Succeeded in selecting Contacts.'); 146 if (!data || !data.length) { 147 HiLog.error(TAG, 'Contacts data is empty.'); 148 return; 149 } 150 const phoneNumbers = data[0].phoneNumbers; 151 if (!phoneNumbers || !phoneNumbers.length) { 152 HiLog.error(TAG, 'Contacts phoneNumbers is empty.'); 153 return; 154 } 155 const phoneNumber = phoneNumbers[0].phoneNumber; 156 if (phoneNumber) { 157 this.inputValue = phoneNumber; 158 } 159 }).catch((error: BusinessError) => { 160 HiLog.error(TAG, `Failed to select Contacts, Code: ${error.code}, message: ${error.message}`); 161 }); 162 } else { 163 this.isShowSheet = !this.isShowSheet; 164 } 165 } 166 167 private async beginShareEncrypt() { 168 HiLog.info(TAG, `begin Share Encrypt start`); 169 if (this.checkCloudPhone(this.inputValue)) { 170 this.enabledFocus = false; 171 this.isConfirmButtonEnabled = false; 172 this.getAccountInfo(); 173 } 174 } 175 176 async getAccountInfo() { 177 HiLog.info(TAG, `get Account Info start`); 178 if (await getConnectionStatus() === false) { 179 this.showToast($r('app.string.network_invalid')); 180 this.enabledFocus = true; 181 this.isConfirmButtonEnabled = this.inputValue.length > 0; 182 this.isTextInputFocus = true; 183 this.textInputGetFocus(); 184 return; 185 } 186 try { 187 let accountInfo = await getOsAccountInfo(); 188 if (accountInfo.distributedInfo.name === 'ohosAnonymousName' && 189 accountInfo.distributedInfo.id === 'ohosAnonymousUid') { 190 this.showUIExtensionForAccountLogin = true; 191 return; 192 } 193 if (accountInfo.distributedInfo.id !== this.recordSuccessUid) { 194 HiLog.info(TAG, `COMMAND_GET_ACCOUNT_INFO start`); 195 this.connectService.connectServiceShareAbility(Constants.COMMAND_GET_ACCOUNT_INFO); 196 this.recordSuccessUid = accountInfo.distributedInfo.id; 197 return; 198 } else { 199 this.connectService.connectServiceShareAbility(Constants.COMMAND_SEARCH_USER_INFO); 200 } 201 } catch (err) { 202 HiLog.error(TAG, `getOsAccountInfo failed: ${JSON.stringify(err)}`); 203 this.showToast($r('app.string.Share_File_Encrypted_Failed')); 204 this.enabledFocus = true; 205 this.isConfirmButtonEnabled = this.inputValue.length > 0; 206 } 207 } 208 209 changeAccountInfo() { 210 if (this.commandGetAccountInfo === encryptedSharing.GET_ACCOUNT_INFO_RESET) { 211 return; 212 } 213 HiLog.info(TAG, `changeAccountInfo start`); 214 try { 215 let commandGetAccountInfoCallBack = JSON.parse(this.commandGetAccountInfo) as Record<string, object>; 216 HiLog.info(TAG, `commandGetAccountInfo Call Back errorCode: ${commandGetAccountInfoCallBack.errorCode}`); 217 let res = commandGetAccountInfoCallBack.result as Record<string, string>; 218 if (Number(commandGetAccountInfoCallBack.errorCode) === Constants.ERR_CODE_SUCCESS && res?.uid) { 219 this.ownerAccount = res?.uid; 220 this.ownerAccountID = res?.uid; 221 this.connectService.connectServiceShareAbility(Constants.COMMAND_SEARCH_USER_INFO); 222 return; 223 } else { 224 this.enabledFocus = true; 225 this.isConfirmButtonEnabled = true; 226 this.recordSuccessUid = ''; 227 this.commandGetAccountInfo = encryptedSharing.GET_ACCOUNT_INFO_RESET; 228 if ([ 229 Constants.ERR_CODE_NETWORK_ERROR, 230 Constants.ERR_CODE_CONNECTION_FAIL, 231 Constants.ERR_CODE_CONNECTION_TIME_OUT 232 ].includes(Number(commandGetAccountInfoCallBack.errorCode))) { 233 this.showToast($r('app.string.network_invalid')); 234 } else { 235 this.showToast($r('app.string.Share_File_Encrypted_Failed')); 236 } 237 return; 238 } 239 } catch (error) { 240 HiLog.error(TAG, `get account info failed: ${JSON.stringify(error)}`); 241 this.showToast($r('app.string.Share_File_Encrypted_Failed')); 242 this.enabledFocus = true; 243 this.isConfirmButtonEnabled = true; 244 this.recordSuccessUid = ''; 245 this.commandGetAccountInfo = encryptedSharing.GET_ACCOUNT_INFO_RESET; 246 return; 247 } 248 } 249 250 checkCloudPhone(phone: string): boolean { 251 if (!phone) { 252 return false; 253 } 254 let reg = /^(?:(?:\+|00)86)?1[3456789]\d{9}$/; 255 if (!(reg.test(phone))) { 256 HiLog.info(TAG, `Please enter the phone.`); 257 this.phoneFormatTips = true; 258 this.credentialCallBackMsg = $r('app.string.Share_Tips_Phone_Format'); 259 HiLog.info(TAG, `phoneFormatTips: ${this.phoneFormatTips}`); 260 return false; 261 } 262 reg = /^(0086|\+86)/; 263 let formatPhone = this.inputValue.replace(reg, ''); 264 let cloudPhone = `${Constants.INTERNATIONAL_DIALING_CODE}${formatPhone}`; 265 AppStorage.setOrCreate('cloudPhone', cloudPhone); 266 return true; 267 } 268 269 async beginToGenerateDLPFile() { 270 HiLog.info(TAG, `beginToGenerateDLPFile start`); 271 if (!this.isInputValid()) { 272 this.enabledFocus = true; 273 this.isConfirmButtonEnabled = true; 274 return; 275 } 276 let parameters = this.actionWant?.parameters as Record<string, Array<string>>; 277 let inputUri: string = parameters['ability.params.stream'][0]; 278 let inputFileName: string | null = this.getFileName(parameters, inputUri); 279 if (inputFileName === null) { 280 storage.setOrCreate('commandSearchUserInfo', ''); 281 this.showToast($r('app.string.Share_File_Encrypted_Failed')); 282 this.enabledFocus = true; 283 this.isConfirmButtonEnabled = true; 284 return; 285 } 286 let dlpFileName: string = inputFileName + '.dlp'; 287 let inFileFd = getFileFd(inputUri); 288 let srcFileSize: number = await getFileSizeByUri(inputUri); 289 AppStorage.setOrCreate('hiFileSize', srcFileSize); 290 let filePath = getContext(this).filesDir + `/Share/${new Date().getTime()}/`; 291 try { 292 await fs.mkdir(filePath, true); 293 } catch (error) { 294 HiLog.error(TAG, `mkdir failed: ${JSON.stringify(error)}`); 295 } 296 let newFilePath = filePath + dlpFileName; 297 let file: fs.File | undefined; 298 let filePathUri = getFileUriByPath(newFilePath); 299 try { 300 file = fs.openSync(newFilePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); 301 await dlpPermission.generateDLPFile(inFileFd, file.fd, this.dlpProperty); 302 this.showToast($r('app.string.Share_File_Encrypted_Success')); 303 let dstFileSize: number = await getFileSizeByUri(filePathUri); 304 AppStorage.setOrCreate('hiPolicySizeEnc', dstFileSize); 305 AppStorage.setOrCreate('hiCode', 201); 306 sendDlpFileCreateProperties(dlpPermission.AccountType.CLOUD_ACCOUNT); // 201: DLP_2C_FILE_CREATE_EVENT 307 this.backToPages(filePathUri, dlpFileName); 308 HiLog.info(TAG, `beginToGenerateDLPFile success`); 309 } catch (err) { 310 HiLog.error(TAG, `open temp failed: ${JSON.stringify(err)}`); 311 HiLog.info(TAG, `generateDLPFile file failed: ${JSON.stringify(err)}`); 312 storage.setOrCreate('commandSearchUserInfo', ''); 313 if (err.code === Constants.SHARE_FILE_NAME_TOO_LONG) { 314 this.showToast($r('app.string.Share_File_Name_Too_Long')); 315 return; 316 } 317 this.showToast($r('app.string.Share_File_Encrypted_Failed')); 318 this.enabledFocus = true; 319 this.isConfirmButtonEnabled = true; 320 } finally { 321 if (file) { 322 fs.closeSync(file); 323 } 324 } 325 } 326 327 getFileName(parameters: Record<string, Array<string>>, inputUri: string): string | null { 328 let abilityPickerRecords = parameters['ability.picker.records']; 329 let srcFileMsg: FileMsg = FileUtils.getSuffixFileMsgByUri(inputUri); 330 AppStorage.setOrCreate('hiFileType', srcFileMsg.fileType); 331 let res: string = ''; 332 Object.keys(abilityPickerRecords).forEach(key => { 333 this.generalType = key; 334 res = abilityPickerRecords[key][0]?.['4']; 335 }); 336 if (res === undefined) { 337 try { 338 res = decodeURIComponent(srcFileMsg.fileName + srcFileMsg.fileType); 339 } catch (error) { 340 HiLog.error(TAG, `getFileName failed: ${error?.message}`); 341 return null; 342 } 343 } 344 return res; 345 } 346 347 showToast(msg: Resource) { 348 promptAction.showToast({ 349 message: msg, 350 duration: Constants.SHARE_SET_TIMEOUT 351 }); 352 } 353 354 backToPages(filePathUri: string, dlpFileName: string) { 355 HiLog.info(TAG, `backToPages start: ${dlpFileName}`); 356 if (this.actionWant && this.actionWant.parameters) { 357 this.actionWant.parameters['ability.params.stream'] = [filePathUri]; 358 let arr: Test[] = [ 359 { 360 '0': 0, 361 '1': 0, 362 '4': dlpFileName 363 } 364 ]; 365 let generalFile: Record<string, Test[]> = {}; 366 generalFile[this.generalType] = arr; 367 this.actionWant.parameters['ability.picker.records'] = generalFile; 368 setTimeout(() => { 369 this.session!.terminateSelfWithResult({ 370 resultCode: 2, 371 want: this.actionWant 372 }); 373 }, Constants.SHARE_SET_TIMEOUT) 374 } 375 } 376 377 isInputValid(): boolean { 378 if (!this.isInputInvalid) { 379 return false; 380 } 381 let credentialCallBack = JSON.parse(this.isInputInvalid) as Record<string, string>; 382 HiLog.info(TAG, `credential Call Back errorCode: ${credentialCallBack.errorCode}`); 383 if (!credentialCallBack.status && Number(credentialCallBack.errorCode) === Constants.ERR_CODE_SUCCESS) { 384 HiLog.info(TAG, `credentialCallBack msg`); 385 let str = this.getExternalResourceString(Constants.DLP_CREDMGR_BUNDLE_NAME, 'entry', 'no_user'); 386 this.credentialCallBackMsg = str.length > 0 ? str : credentialCallBack.errorMsg; 387 this.phoneFormatTips = true; 388 storage.setOrCreate('commandSearchUserInfo', ''); 389 return false; 390 } 391 if (!credentialCallBack.status && [ 392 Constants.ERR_CODE_NETWORK_ERROR, 393 Constants.ERR_CODE_CONNECTION_FAIL, 394 Constants.ERR_CODE_CONNECTION_TIME_OUT 395 ].includes(Number(credentialCallBack.errorCode))) { 396 this.showToast($r('app.string.network_invalid')); 397 storage.setOrCreate('commandSearchUserInfo', ''); 398 return false; 399 } 400 if (!credentialCallBack.status && Number(credentialCallBack.errorCode) !== Constants.ERR_CODE_SUCCESS) { 401 this.showToast($r('app.string.Share_File_Encrypted_Failed')); 402 storage.setOrCreate('commandSearchUserInfo', ''); 403 return false; 404 } 405 let authUserList: AuthUserList[] = [ 406 { 407 'authAccount': credentialCallBack.userIdCipher, 408 'authAccountType': 1, 409 'dlpFileAccess': 1, 410 'permExpiryTime': Date.UTC(9999, 1, 1), 411 } 412 ]; 413 this.dlpProperty = { 414 'ownerAccount': this.ownerAccount, 415 'ownerAccountID': this.ownerAccountID, 416 'ownerAccountType': 1, 417 'authUserList': authUserList, 418 'contactAccount': this.ownerAccount, 419 'offlineAccess': true, 420 } 421 return true; 422 } 423 424 async checkContacts() { 425 let callerBundleName = 'com.ohos.contacts'; 426 try { 427 await getAppId(callerBundleName); 428 this.contactExists = true; 429 } catch { 430 this.contactExists = false; 431 } 432 } 433 434 async getLoginStatus() { 435 HiLog.info(TAG, `get login status start.`); 436 if (await getConnectionStatus() === false) { 437 this.showToast($r('app.string.network_invalid')); 438 this.enabledFocus = true; 439 this.isConfirmButtonEnabled = this.inputValue.length > 0; 440 this.isTextInputFocus = true; 441 this.textInputGetFocus(); 442 return; 443 } 444 try { 445 let accountInfo = await getOsAccountInfo(); 446 if (accountInfo.distributedInfo.name === 'ohosAnonymousName' && 447 accountInfo.distributedInfo.id === 'ohosAnonymousUid') { 448 this.showUIExtensionForAccountLogin = true; 449 } else { 450 this.isTextInputFocus = true; 451 this.textInputGetFocus(); 452 } 453 } catch (err) { 454 HiLog.error(TAG, `getOsAccountInfo failed: ${JSON.stringify(err)}`); 455 } 456 } 457 458 459 onLanguageChange() { 460 let str = this.getExternalResourceString(Constants.DLP_CREDMGR_BUNDLE_NAME, 'entry', 'add_users_hint'); 461 if (str.length > 0) { 462 this.placeHolderStr = str; 463 } 464 str = this.getExternalResourceString(Constants.DLP_CREDMGR_BUNDLE_NAME, 'entry', 'no_user'); 465 if (str.length > 0) { 466 this.credentialCallBackMsg = str; 467 } 468 str = this.getExternalResourceString(Constants.DLP_CREDMGR_BUNDLE_NAME, 'entry', 'hmos_version_label'); 469 if (str.length > 0) { 470 this.osVersion = str; 471 } 472 this.getContactPersonString(); 473 } 474 475 subscribeLanguageChange() { 476 emitter.on('onConfigurationUpdate', () => { 477 this.onLanguageChange(); 478 }) 479 } 480 481 getExternalResourceString(bundle: string, module: string, resourceName: string): string { 482 try { 483 let ctx = getContext().createModuleContext(bundle, module); 484 HiLog.info(TAG, 'getExternalResourceString get context from: ' + ctx.applicationInfo.name); 485 let str = ctx.resourceManager.getStringByNameSync(resourceName); 486 return str; 487 } catch (e) { 488 let error = e as BusinessError; 489 HiLog.error(TAG, 'getExternalResourceString error: ' + error.code + ' ' + error.message); 490 return ''; 491 } 492 } 493 494 getContactPersonString() { 495 try { 496 getContext().resourceManager.getStringValue($r('app.string.Share_Contact_Person').id, 497 (error: BusinessError, value: string) => { 498 if (error === undefined || error === null) { 499 this.contactPerson = value; 500 } else { 501 HiLog.error(TAG, `error is ${JSON.stringify(error)}`); 502 } 503 }); 504 } catch (error) { 505 HiLog.error(TAG, `callback getStringValue failed, error ${JSON.stringify(error)}`); 506 } 507 } 508 509 private getSettingItemPadding(): number { 510 const FONT_SIZE_SCALE_PARAM = 'persist.sys.font_scale_for_user0'; 511 let fontSizeScale = Number.parseFloat(systemParameterEnhance.getSync(FONT_SIZE_SCALE_PARAM, '1')); 512 switch (fontSizeScale) { 513 case FontSizeScale.XXL1: 514 return Constants.GET_SETTING_ITEM_XXL1; 515 case FontSizeScale.XXL2: 516 return Constants.GET_SETTING_ITEM_XXL2; 517 case FontSizeScale.XXL3: 518 return Constants.GET_SETTING_ITEM_XXL3; 519 default: 520 return Constants.GET_SETTING_ITEM_DEFAULT; 521 } 522 } 523 524 clearHistoryDLPFile() { 525 let pathDir = getContext(this).filesDir + '/Share'; 526 fs.listFile(pathDir).then((filenames: Array<string>) => { 527 HiLog.info(TAG, `listFile succeed`); 528 let filenamesLists = filenames.sort((a, b) => Number(a) - Number(b)); 529 if (filenamesLists.length > Constants.SHARE_TEMP_SAVE_FILE_NUMBER) { 530 let deleteArray = filenamesLists.slice(0, filenamesLists.length - Constants.SHARE_TEMP_SAVE_FILE_NUMBER); 531 deleteArray.forEach((item) => { 532 fs.rmdirSync(pathDir + `/${item}`); 533 }) 534 } 535 }).catch((err: BusinessError) => { 536 HiLog.error(TAG, `list file failed with error message: ${JSON.stringify(err)}`); 537 }); 538 } 539 540 textInputGetFocus() { 541 setTimeout(() => { 542 try { 543 HiLog.info(TAG, `delay requestFocus start`); 544 this.getUIContext().getFocusController().requestFocus('phoneInput'); 545 } catch (error) { 546 HiLog.error(TAG, `requestFocus failed. Cause: ${JSON.stringify(error)}`); 547 } 548 }, Constants.ENCRYPTION_SET_TIMEOUT_TIME); 549 } 550 551 getScrollHeight(newValue: SizeOptions) { 552 const height = newValue.height as number; 553 this.scrollHeight = height - Constants.SHARE_BUTTON_COLUMN_BOTTOM - Constants.SHARE_TITLE_HEAD_HEIGHT - 554 Constants.SHARE_TITLE_HEAD_MARGIN_TOP - Constants.SHARE_TITLE_HEAD_MARGIN_BOTTOM; 555 if (this.scrollHeight > Constants.SHARE_TEXTAREA_MAX_HEIGHT) { 556 this.scrollHeight = Constants.SHARE_TEXTAREA_MAX_HEIGHT; 557 } 558 } 559 560 aboutToAppear() { 561 HiLog.info(TAG, `aboutToAppear enter: ${this.showUIExtensionForAccountLogin}`); 562 this.isPhoneDevice = deviceInfo.deviceType === 'phone'; 563 this.getLoginStatus(); 564 AppStorage.setOrCreate('hiAccountType', dlpPermission.AccountType.CLOUD_ACCOUNT); 565 sendDlpManagerAccountLogin(-1); 566 this.checkContacts(); 567 this.clearHistoryDLPFile(); 568 this.subscribeLanguageChange(); 569 let str = this.getExternalResourceString(Constants.DLP_CREDMGR_BUNDLE_NAME, 'entry', 'add_users_hint'); 570 this.placeHolderStr = str.length > 0 ? str : ''; 571 str = this.getExternalResourceString(Constants.DLP_CREDMGR_BUNDLE_NAME, 'entry', 'hmos_version_label'); 572 this.osVersion = str.length > 0 ? str : ''; 573 this.getContactPersonString(); 574 } 575 576 build() { 577 Stack() { 578 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start }) { 579 EditableTitleBar({ 580 leftIconStyle: EditableLeftIconType.Back, 581 title: $r('app.string.Share_Add_Viewable_Users'), 582 contentMargin: this.titlebarMargin, 583 menuItems: [ 584 { 585 value: $r('sys.media.ohos_ic_public_cancel'), 586 isEnabled: true, 587 label: $r('app.string.ban'), 588 action: () => { 589 if (this.session !== undefined) { 590 this.session.terminateSelfWithResult({ 591 'resultCode': 1, 592 }); 593 } 594 } 595 } 596 ], 597 isSaveIconRequired: false, 598 onCancel: () => { 599 if (this.session !== undefined) { 600 this.session.terminateSelfWithResult({ 601 'resultCode': 0, 602 }); 603 } 604 }, 605 }) 606 .constraintSize({ minHeight: Constants.SHARE_TITLE_HEAD_HEIGHT }) 607 .margin({ 608 top: Constants.SHARE_TITLE_HEAD_MARGIN_TOP, 609 }) 610 Scroll() { 611 Column() { 612 Row() { 613 TextInput({ placeholder: this.placeHolderStr, text: this.inputValue }) 614 .id('phoneInput') 615 .padding({ 616 left: SystemUtils.isRTL() ? 617 Constants.SHARE_TEXT_INPUT_CONTENT_PADDING_RIGHT : Constants.SHARE_TEXT_INPUT_CONTENT_PADDING_LEFT, 618 right: SystemUtils.isRTL() ? 619 Constants.SHARE_TEXT_INPUT_CONTENT_PADDING_LEFT : Constants.SHARE_TEXT_INPUT_CONTENT_PADDING_RIGHT 620 }) 621 .enabled(this.enabledFocus) 622 .constraintSize({ minHeight: Constants.SHARE_TEXT_INPUT_HEIGHT }) 623 .focusable(this.isTextInputFocus) 624 .defaultFocus(false) 625 .direction(SystemUtils.isRTL() ? Direction.Rtl : Direction.Ltr) 626 .type(InputType.PhoneNumber) 627 .contentType(ContentType.PHONE_COUNTRY_CODE) 628 .enterKeyType(EnterKeyType.NEW_LINE) 629 .border(this.phoneFormatTips ? 630 { width: Constants.DIALOG_MD_OFFSET, color: $r('sys.color.ohos_id_color_warning') } : { width: 0 }) 631 .onChange((value: string) => { 632 HiLog.info(TAG, `input length: ${value.length}`); 633 this.inputValue = value; 634 this.phoneFormatTips = false; 635 this.isConfirmButtonEnabled = value.length > 0; 636 }) 637 if (this.contactExists) { 638 Column() { 639 SymbolGlyph($r('sys.symbol.person_2')) 640 .fontSize(`${Constants.SYMBOL_GLYPH_FONT_SIZE}vp`) 641 .fontColor(this.enabledFocus ? [$r('sys.color.icon_primary')] : [$r('sys.color.icon_tertiary')]) 642 } 643 .accessibilityText(this.contactPerson) 644 .enabled(this.enabledFocus) 645 .offset({ 646 x: SystemUtils.isRTL() 647 ? Constants.SHARE_CONTACTS_GROUP_OFFSET_X_RTL : Constants.SHARE_CONTACTS_GROUP_OFFSET_X, 648 y: Constants.SHARE_CONTACTS_GROUP_OFFSET_Y 649 }) 650 .onClick(this.contactsAction) 651 .bindSheet(this.isShowSheet, this.contactsPicker(), { 652 height: SheetSize.LARGE, 653 dragBar: false, 654 showClose: true, 655 onWillDisappear: () => { 656 this.isShowSheet = false; 657 }, 658 backgroundColor: Color.Transparent, 659 blurStyle: BlurStyle.COMPONENT_ULTRA_THICK 660 }) 661 } 662 } 663 664 Text(this.phoneFormatTips ? 665 this.credentialCallBackMsg : $r('app.string.Share_Enter_Mobile_Number', this.osVersion)) 666 .fontColor(this.phoneFormatTips ? 667 $r('sys.color.ohos_id_color_warning') : $r('sys.color.ohos_id_color_text_secondary')) 668 .fontSize($r('sys.float.ohos_id_text_size_body3')) 669 .fontWeight(FontWeight.Regular) 670 .margin({ top: Constants.ENCRYPTION_ADD_STAFF_BORDER_MARGIN_TOP }) 671 .backgroundColor(Color.Transparent) 672 .width(Constants.CONTACTS_PICKER_WIDTH) 673 .padding({ left: Constants.SHARE_TITLE_HEAD_PADDING_LEFT }) 674 } 675 .margin({ left: Constants.SHARE_TEXT_INPUT_MARGIN_LEFT, right: Constants.SHARE_TEXT_INPUT_MARGIN_RIGHT }) 676 } 677 .align(Alignment.TopStart) 678 .constraintSize({ 679 minHeight: `${this.scrollHeight}vp` 680 }) 681 .padding({ 682 top: Constants.SHARE_TITLE_HEAD_MARGIN_BOTTOM 683 }) 684 Column() { 685 Button($r('app.string.Share_Confirms'), { type: ButtonType.Capsule, stateEffect: true }) 686 .enabled(this.isConfirmButtonEnabled) 687 .backgroundColor($r('sys.color.ohos_id_color_text_primary_activated')) 688 .width(Constants.SHARE_BUTTON_WIDTH) 689 .controlSize(ControlSize.NORMAL) 690 .onClick(async () => { 691 this.beginShareEncrypt(); 692 }) 693 } 694 .justifyContent(FlexAlign.Center) 695 .margin({ 696 left: Constants.SHARE_BUTTON_MARGIN_LEFT, 697 right: Constants.SHARE_BUTTON_MARGIN_RIGHT, 698 bottom: Constants.SHARE_BUTTON_PADDING_BOTTOM 699 }) 700 .constraintSize({ 701 minHeight: `${Constants.SHARE_BUTTON_COLUMN_BOTTOM}vp` 702 }) 703 } 704 .width(Constants.SHARE_PAGES_COLUMN_WIDTH) 705 .height(Constants.SHARE_PAGES_COLUMN_HEIGHT) 706 if (this.showUIExtensionForAccountLogin) { 707 UIExtensionComponent({ 708 bundleName: 'com.huawei.hmos.dlpcredmgr', 709 abilityName: 'DlpCredAccountAbility', 710 parameters: { 711 'ability.want.params.uiExtensionType': 'sys/commonUI' 712 } 713 }) 714 .id('cloudAccountLoginUI') 715 .onRemoteReady(() => { 716 try { 717 HiLog.info(TAG, `cloudAccountLoginUI requestFocus start`); 718 this.getUIContext().getFocusController().requestFocus('cloudAccountLoginUI'); 719 } catch (error) { 720 HiLog.error(TAG, `requestFocus failed. Cause: ${JSON.stringify(error)}`) 721 } 722 }) 723 .onReceive((data) => { 724 HiLog.info(TAG, `data.status: ${JSON.stringify(data.status)}`); 725 let res = data.result as Record<string, string>; 726 HiLog.info(TAG, `res.code: ${JSON.stringify(res.code)}`); 727 if (data.status) { 728 this.ownerAccount = res?.uid; 729 this.ownerAccountID = res?.uid; 730 let checkCloudPhone = this.checkCloudPhone(this.inputValue); 731 HiLog.info(TAG, `checkCloudPhone: ${checkCloudPhone}`); 732 if (checkCloudPhone) { 733 this.enabledFocus = false; 734 this.isConfirmButtonEnabled = false; 735 this.connectService.connectServiceShareAbility(Constants.COMMAND_SEARCH_USER_INFO); 736 } 737 } else { 738 this.enabledFocus = true; 739 this.isConfirmButtonEnabled = this.inputValue.length > 0; 740 if (['12300001', '1001502005', '1001502009'].includes(res.code.toString())) { 741 this.showToast($r('app.string.network_invalid')); 742 } 743 } 744 this.isTextInputFocus = true; 745 this.textInputGetFocus(); 746 this.showUIExtensionForAccountLogin = false; 747 }) 748 .size({ 749 width: Constants.SHARE_PAGES_COLUMN_WIDTH, height: Constants.SHARE_PAGES_COLUMN_HEIGHT 750 }) 751 } 752 } 753 .onSizeChange((oldValue: SizeOptions, newValue: SizeOptions) => { 754 const newHeight = newValue.height as number; 755 const oldHeight = oldValue.height as number; 756 if (newHeight === oldHeight) { 757 return; 758 } 759 this.getScrollHeight(newValue); 760 }) 761 } 762}