1/* 2 * Copyright (c) 2023-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 16const photoAccessHelper = requireInternal('file.photoAccessHelper'); 17const bundleManager = requireNapi('bundle.bundleManager'); 18 19const ARGS_ZERO = 0; 20const ARGS_ONE = 1; 21const ARGS_TWO = 2; 22const ARGS_THREE = 3; 23 24const WRITE_PERMISSION = 'ohos.permission.WRITE_IMAGEVIDEO'; 25 26const PERMISSION_DENIED = 13900012; 27const ERR_CODE_PARAMERTER_INVALID = 13900020; 28const ERR_CODE_OHOS_PERMISSION_DENIED = 201; 29const ERR_CODE_OHOS_PARAMERTER_INVALID = 401; 30const REQUEST_CODE_SUCCESS = 0; 31const PERMISSION_STATE_ERROR = -1; 32const ERROR_MSG_WRITE_PERMISSION = 'not have ohos.permission.WRITE_IMAGEVIDEO'; 33const ERROR_MSG_USER_DENY = 'user deny'; 34const ERROR_MSG_PARAMERTER_INVALID = 'input parmaeter invalid'; 35const ERROR_MSG_INNER_FAIL = 'System inner fail'; 36const ERROR_MSG_OHOS_INNER_FAIL = 'Internal system error'; 37 38const MAX_DELETE_NUMBER = 300; 39const MIN_DELETE_NUMBER = 1; 40const MAX_CONFIRM_NUMBER = 100; 41const MIN_CONFIRM_NUMBER = 1; 42 43let gContext = undefined; 44 45class BusinessError extends Error { 46 constructor(msg, code) { 47 super(msg); 48 this.code = code || PERMISSION_DENIED; 49 } 50} 51 52function checkArrayAndSize(array, minSize, maxSize) { 53 // check whether input is array 54 if (!Array.isArray(array)) { 55 console.error('photoAccessHelper invalid, array is null.'); 56 return false; 57 } 58 59 // check whether array length is valid 60 let len = array.length; 61 if ((len < minSize) || (len > maxSize)) { 62 console.error('photoAccessHelper invalid, array size invalid.'); 63 return false; 64 } 65 66 return true; 67} 68 69function checkIsUriValid(uri, isAppUri) { 70 if (!uri) { 71 console.error('photoAccessHelper invalid, uri is null.'); 72 return false; 73 } 74 75 if (typeof uri !== 'string') { 76 console.error('photoAccessHelper invalid, uri type is not string.'); 77 return false; 78 } 79 80 // media library uri starts with 'file://media/Photo/', createDeleteReques delete media library resource should check 81 if (!isAppUri) { 82 return uri.includes('file://media/Photo/'); 83 } 84 85 // showAssetsCreationDialog store third part application resource to media library, no need to check it 86 return true; 87} 88 89function checkParams(uriList, asyncCallback) { 90 if (arguments.length > ARGS_TWO) { 91 return false; 92 } 93 if (!checkArrayAndSize(uriList, MIN_DELETE_NUMBER, MAX_DELETE_NUMBER)) { 94 return false; 95 } 96 if (asyncCallback && typeof asyncCallback !== 'function') { 97 return false; 98 } 99 for (let uri of uriList) { 100 if (!checkIsUriValid(uri, false)) { 101 console.info(`photoAccessHelper invalid uri: ${uri}`); 102 return false; 103 } 104 } 105 return true; 106} 107function errorResult(rej, asyncCallback) { 108 if (asyncCallback) { 109 return asyncCallback(rej); 110 } 111 return new Promise((resolve, reject) => { 112 reject(rej); 113 }); 114} 115 116function getAbilityResource(bundleInfo) { 117 console.info('getAbilityResource enter.'); 118 let labelId = 0; 119 for (let hapInfo of bundleInfo.hapModulesInfo) { 120 if (hapInfo.type === bundleManager.ModuleType.ENTRY) { 121 labelId = getLabelId(hapInfo); 122 } 123 } 124 return labelId; 125} 126 127function getLabelId(hapInfo) { 128 let labelId = 0; 129 for (let abilityInfo of hapInfo.abilitiesInfo) { 130 let abilitiesInfoName = ''; 131 if (abilityInfo.name.includes('.')) { 132 let abilitiesInfoLength = abilityInfo.name.split('.').length; 133 abilitiesInfoName = abilityInfo.name.split('.')[abilitiesInfoLength - 1]; 134 } else { 135 abilitiesInfoName = abilityInfo.name; 136 } 137 if (abilitiesInfoName === hapInfo.mainElementName) { 138 labelId = abilityInfo.labelId; 139 } 140 } 141 return labelId; 142} 143 144async function getAppName() { 145 let appName = ''; 146 try { 147 const flags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_ABILITY | bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_HAP_MODULE; 148 const bundleInfo = await bundleManager.getBundleInfoForSelf(flags); 149 console.info(`photoAccessHelper bundleInfo: ${JSON.stringify(bundleInfo)}`); 150 if (bundleInfo === undefined || bundleInfo.hapModulesInfo === undefined || bundleInfo.hapModulesInfo.length === 0) { 151 return appName; 152 } 153 const labelId = getAbilityResource(bundleInfo); 154 const resourceMgr = gContext.resourceManager; 155 appName = await resourceMgr.getStringValue(labelId); 156 console.info(`photoAccessHelper appName: ${appName}`); 157 } catch (error) { 158 console.info(`photoAccessHelper error: ${JSON.stringify(error)}`); 159 } 160 161 return appName; 162} 163 164async function createPhotoDeleteRequestParamsOk(uriList, asyncCallback) { 165 let flags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION; 166 let { reqPermissionDetails, permissionGrantStates } = await bundleManager.getBundleInfoForSelf(flags); 167 let permissionIndex = -1; 168 for (let i = 0; i < reqPermissionDetails.length; i++) { 169 if (reqPermissionDetails[i].name === WRITE_PERMISSION) { 170 permissionIndex = i; 171 } 172 } 173 if (permissionIndex < 0 || permissionGrantStates[permissionIndex] === PERMISSION_STATE_ERROR) { 174 console.info('photoAccessHelper permission error'); 175 return errorResult(new BusinessError(ERROR_MSG_WRITE_PERMISSION), asyncCallback); 176 } 177 const appName = await getAppName(); 178 if (appName.length === 0) { 179 console.info(`photoAccessHelper appName not found`); 180 return errorResult(new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_PARAMERTER_INVALID), asyncCallback); 181 } 182 try { 183 if (asyncCallback) { 184 return photoAccessHelper.createDeleteRequest(getContext(this), appName, uriList, result => { 185 if (result.result === REQUEST_CODE_SUCCESS) { 186 asyncCallback(); 187 } else if (result.result == PERMISSION_DENIED) { 188 asyncCallback(new BusinessError(ERROR_MSG_USER_DENY)); 189 } else { 190 asyncCallback(new BusinessError(ERROR_MSG_INNER_FAIL, result.result)); 191 } 192 }); 193 } else { 194 return new Promise((resolve, reject) => { 195 photoAccessHelper.createDeleteRequest(getContext(this), appName, uriList, result => { 196 if (result.result === REQUEST_CODE_SUCCESS) { 197 resolve(); 198 } else if (result.result == PERMISSION_DENIED) { 199 reject(new BusinessError(ERROR_MSG_USER_DENY)); 200 } else { 201 reject(new BusinessError(ERROR_MSG_INNER_FAIL, result.result)); 202 } 203 }); 204 }); 205 } 206 } catch (error) { 207 return errorResult(new BusinessError(error.message, error.code), asyncCallback); 208 } 209} 210 211function createDeleteRequest(...params) { 212 if (!checkParams(...params)) { 213 throw new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_PARAMERTER_INVALID); 214 } 215 return createPhotoDeleteRequestParamsOk(...params); 216} 217 218function checkIsPhotoCreationConfigValid(config) { 219 if (!config) { 220 console.error('photoAccessHelper invalid, config is null.'); 221 return false; 222 } 223 224 // check whether input is a object 225 if (typeof config !== 'object') { 226 console.error('photoAccessHelper invalid, config type is not object.'); 227 return false; 228 } 229 230 // check whether title is string if exsit 231 if ((config.title) && (typeof config.title !== 'string')) { 232 console.error('photoAccessHelper invalid, config.title type is not string.'); 233 return false; 234 } 235 236 // check whether fileNameExtension is string 237 if (!config.fileNameExtension) { 238 console.error('photoAccessHelper invalid, config.fileNameExtension is null.'); 239 return false; 240 } 241 if (typeof config.fileNameExtension !== 'string') { 242 console.error('photoAccessHelper invalid, config.fileNameExtension type is not string.'); 243 return false; 244 } 245 246 // check whether photoType is number 247 if (!config.photoType) { 248 console.error('photoAccessHelper invalid, config.photoType is null.'); 249 return false; 250 } 251 if (typeof config.photoType !== 'number') { 252 console.error('photoAccessHelper invalid, config.photoType type is not number.'); 253 return false; 254 } 255 256 // check whether subtype is number if exsit 257 if ((config.subtype) && (typeof config.subtype !== 'number')) { 258 console.error('photoAccessHelper invalid, config.subtype type is not number.'); 259 return false; 260 } 261 262 return true; 263} 264 265function checkConfirmBoxParams(srcFileUris, photoCreationConfigs) { 266 // check param number 267 if (arguments.length > ARGS_TWO) { 268 return false; 269 } 270 271 // check whether input array is valid 272 if (!checkArrayAndSize(srcFileUris, MIN_CONFIRM_NUMBER, MAX_CONFIRM_NUMBER)) { 273 return false; 274 } 275 if (!checkArrayAndSize(photoCreationConfigs, MIN_CONFIRM_NUMBER, MAX_CONFIRM_NUMBER)) { 276 return false; 277 } 278 if (srcFileUris.length !== photoCreationConfigs.length) { 279 return false; 280 } 281 282 // check whether srcFileUris element is valid 283 for (let srcFileUri of srcFileUris) { 284 if (!checkIsUriValid(srcFileUri, true)) { 285 console.error('photoAccessHelper invalid uri: ${srcFileUri}.'); 286 return false; 287 } 288 } 289 290 // check whether photoCreationConfigs element is valid 291 for (let photoCreateConfig of photoCreationConfigs) { 292 if (!checkIsPhotoCreationConfigValid(photoCreateConfig)) { 293 return false; 294 } 295 } 296 297 return true; 298} 299 300function getBundleInfo() { 301 let flags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_ABILITY | // for appName 302 bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_HAP_MODULE | // for appName 303 bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO | // for appId 304 bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION; // for appInfo 305 let bundleInfo = bundleManager.getBundleInfoForSelfSync(flags); 306 if (((bundleInfo === undefined) || (bundleInfo.name === undefined)) || 307 ((bundleInfo.hapModulesInfo === undefined) || (bundleInfo.hapModulesInfo.length === 0)) || 308 ((bundleInfo.signatureInfo === undefined) || (bundleInfo.signatureInfo.appId === undefined)) || 309 ((bundleInfo.appInfo === undefined) || (bundleInfo.appInfo.labelId === 0))) { 310 console.error('photoAccessHelper failed to get bundle info.'); 311 return undefined; 312 } 313 314 return bundleInfo; 315} 316 317function showAssetsCreationDialogResult(result, reject, resolve) { 318 if (result.result !== REQUEST_CODE_SUCCESS) { 319 reject(new BusinessError(ERROR_MSG_OHOS_INNER_FAIL, result.result)); 320 } 321 322 if (result.data === undefined) { 323 result.data = []; 324 } 325 326 resolve(result.data); 327} 328 329async function showAssetsCreationDialogParamsOk(srcFileUris, photoCreationConfigs) { 330 let bundleInfo = getBundleInfo(); 331 if (bundleInfo === undefined) { 332 return new Promise((resolve, reject) => { 333 reject(new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID)); 334 }); 335 } 336 337 // get bundleName and appId and appName 338 let bundleName = bundleInfo.name; 339 let appId = bundleInfo.signatureInfo.appId; 340 console.info('photoAccessHelper bundleName is ' + bundleName + '.'); 341 console.info('photoAccessHelper appId is ' + appId + '.'); 342 343 let labelId = bundleInfo.appInfo.labelId; 344 console.info('photoAccessHelper labelId is ' + appId + '.'); 345 let appName = ''; 346 347 try { 348 let modeleName = ''; 349 for (let hapInfo of bundleInfo.hapModulesInfo) { 350 if (labelId === hapInfo.labelId) { 351 modeleName = hapInfo.name; 352 } 353 } 354 console.info('photoAccessHelper modeleName is ' + modeleName + '.'); 355 appName = await gContext.createModuleContext(modeleName).resourceManager.getStringValue(labelId); 356 console.info('photoAccessHelper appName is ' + appName + '.'); 357 // only promise type 358 return new Promise((resolve, reject) => { 359 photoAccessHelper.showAssetsCreationDialog(getContext(this), srcFileUris, photoCreationConfigs, bundleName, 360 appName, appId, result => { 361 showAssetsCreationDialogResult(result, reject, resolve); 362 }); 363 }); 364 } catch (error) { 365 return errorResult(new BusinessError(error.message, error.code), null); 366 } 367} 368 369function showAssetsCreationDialog(...params) { 370 if (!checkConfirmBoxParams(...params)) { 371 throw new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID); 372 } 373 return showAssetsCreationDialogParamsOk(...params); 374} 375 376async function requestPhotoUrisReadPermission(srcFileUris) { 377 console.info('requestPhotoUrisReadPermission enter'); 378 379 //check whether srcFileUris is valid 380 if (srcFileUris === undefined || srcFileUris.length < MIN_CONFIRM_NUMBER) { 381 console.error('photoAccessHelper invalid, array size invalid.'); 382 return false; 383 } 384 for (let srcFileUri of srcFileUris) { 385 if (!checkIsUriValid(srcFileUri, true)) { 386 console.error('photoAccesshelper invalid uri : ${srcFileUri}.'); 387 return false; 388 } 389 } 390 391 let context = gContext; 392 if (context === undefined) { 393 console.info('photoAccessHelper gContet undefined'); 394 context = getContext(this); 395 } 396 397 let bundleInfo = getBundleInfo(); 398 if (bundleInfo === undefined) { 399 return new Promise((resolve, reject) => { 400 reject(new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID)); 401 }); 402 } 403 let labelId = bundleInfo.appInfo.labelId; 404 console.info('photoAccessHelper labelId is ' + labelId + '.'); 405 let appName = ''; 406 407 try { 408 let moduleName = ''; 409 for (let hapInfo of bundleInfo.hapModulesInfo) { 410 if (labelId === hapInfo.labelId) { 411 moduleName = hapInfo.name; 412 } 413 } 414 console.info('photoAccessHelper moduleName is ' + moduleName + '.'); 415 appName = await gContext.createModuleContext(moduleName).resourceManager.getStringValue(labelId); 416 console.info('photoAccessHelper appName is ' + appName + '.'); 417 return new Promise((resolve, reject) => { 418 photoAccessHelper.requestPhotoUrisReadPermission(context, srcFileUris, appName, result => { 419 showAssetsCreationDialogResult(result, reject, resolve); 420 }); 421 }); 422 } catch (error) { 423 console.error('requestPhotoUrisReadPermission catch error.'); 424 return errorResult(new BusinessError(ERROR_MSG_INNER_FAIL, error.code), null); 425 } 426} 427 428async function createAssetWithShortTermPermissionOk(photoCreationConfig) { 429 let bundleInfo = getBundleInfo(); 430 if (bundleInfo === undefined) { 431 return new Promise((resolve, reject) => { 432 reject(new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID)); 433 }); 434 } 435 436 let bundleName = bundleInfo.name; 437 let appId = bundleInfo.signatureInfo.appId; 438 console.info('photoAccessHelper bundleName is ' + bundleName + '.'); 439 console.info('photoAccessHelper appId is ' + appId + '.'); 440 441 let labelId = bundleInfo.appInfo.labelId; 442 console.info('photoAccessHelper labelId is ' + appId + '.'); 443 let appName = ''; 444 445 try { 446 let modeleName = ''; 447 for (let hapInfo of bundleInfo.hapModulesInfo) { 448 if (labelId === hapInfo.labelId) { 449 modeleName = hapInfo.name; 450 } 451 } 452 console.info('photoAccessHelper modeleName is ' + modeleName + '.'); 453 appName = await gContext.createModuleContext(modeleName).resourceManager.getStringValue(labelId); 454 console.info('photoAccessHelper appName is ' + appName + '.'); 455 456 if (photoAccessHelper.checkShortTermPermission()) { 457 let photoCreationConfigs = [photoCreationConfig]; 458 let desFileUris = await getPhotoAccessHelper(getContext(this)).createAssetsHasPermission(bundleName, appName, appId, 459 photoCreationConfigs); 460 return new Promise((resolve, reject) => { 461 resolve(desFileUris[0]); 462 }); 463 } 464 return new Promise((resolve, reject) => { 465 photoAccessHelper.createAssetWithShortTermPermission(getContext(this), photoCreationConfig, bundleName, appName, 466 appId, result => { 467 showAssetsCreationDialogResult(result, reject, resolve); 468 }); 469 }); 470 } catch (error) { 471 return errorResult(new BusinessError(ERROR_MSG_INNER_FAIL, error.code), null); 472 } 473} 474 475function createAssetWithShortTermPermission(photoCreationConfig) { 476 if (!checkIsPhotoCreationConfigValid(photoCreationConfig)) { 477 throw new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID); 478 } 479 return createAssetWithShortTermPermissionOk(photoCreationConfig); 480} 481 482function getPhotoAccessHelper(context) { 483 if (context === undefined) { 484 console.log('photoAccessHelper gContext undefined'); 485 throw Error('photoAccessHelper gContext undefined'); 486 } 487 gContext = context; 488 let helper = photoAccessHelper.getPhotoAccessHelper(gContext); 489 if (helper !== undefined) { 490 console.log('photoAccessHelper getPhotoAccessHelper inner add createDeleteRequest and showAssetsCreationDialog'); 491 helper.createDeleteRequest = createDeleteRequest; 492 helper.showAssetsCreationDialog = showAssetsCreationDialog; 493 helper.createAssetWithShortTermPermission = createAssetWithShortTermPermission; 494 helper.requestPhotoUrisReadPermission = requestPhotoUrisReadPermission; 495 } 496 return helper; 497} 498 499function startPhotoPicker(context, config) { 500 if (context === undefined) { 501 console.log('photoAccessHelper gContext undefined'); 502 throw Error('photoAccessHelper gContext undefined'); 503 } 504 if (config === undefined) { 505 console.log('photoAccessHelper config undefined'); 506 throw Error('photoAccessHelper config undefined'); 507 } 508 gContext = context; 509 let helper = photoAccessHelper.startPhotoPicker(gContext, config); 510 if (helper !== undefined) { 511 console.log('photoAccessHelper startPhotoPicker inner add createDeleteRequest'); 512 helper.createDeleteRequest = createDeleteRequest; 513 } 514 return helper; 515} 516 517function getPhotoAccessHelperAsync(context, asyncCallback) { 518 if (context === undefined) { 519 console.log('photoAccessHelper gContext undefined'); 520 throw Error('photoAccessHelper gContext undefined'); 521 } 522 gContext = context; 523 if (arguments.length === 1) { 524 return photoAccessHelper.getPhotoAccessHelperAsync(gContext) 525 .then((helper) => { 526 if (helper !== undefined) { 527 console.log('photoAccessHelper getPhotoAccessHelperAsync inner add createDeleteRequest' + 528 ' and showAssetsCreationDialog'); 529 helper.createDeleteRequest = createDeleteRequest; 530 helper.showAssetsCreationDialog = showAssetsCreationDialog; 531 helper.createAssetWithShortTermPermission = createAssetWithShortTermPermission; 532 helper.requestPhotoUrisReadPermission = requestPhotoUrisReadPermission; 533 } 534 return helper; 535 }) 536 .catch((err) => { 537 console.log('photoAccessHelper getPhotoAccessHelperAsync err ' + err); 538 throw Error(err); 539 }); 540 } else if (arguments.length === ARGS_TWO && typeof asyncCallback === 'function') { 541 photoAccessHelper.getPhotoAccessHelperAsync(gContext, (err, helper) => { 542 console.log('photoAccessHelper getPhotoAccessHelperAsync callback ' + err); 543 if (err) { 544 asyncCallback(err); 545 } else { 546 if (helper !== undefined) { 547 console.log('photoAccessHelper getPhotoAccessHelperAsync callback add createDeleteRequest' + 548 ' and showAssetsCreationDialog'); 549 helper.createDeleteRequest = createDeleteRequest; 550 helper.showAssetsCreationDialog = showAssetsCreationDialog; 551 helper.createAssetWithShortTermPermission = createAssetWithShortTermPermission; 552 helper.requestPhotoUrisReadPermission = requestPhotoUrisReadPermission; 553 } 554 asyncCallback(err, helper); 555 } 556 }); 557 } else { 558 console.log('photoAccessHelper getPhotoAccessHelperAsync param invalid'); 559 throw new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID); 560 } 561 return undefined; 562} 563 564const RecommendationType = { 565 // Indicates that QR code or barcode photos can be recommended 566 QR_OR_BAR_CODE: 1, 567 568 // Indicates that QR code photos can be recommended 569 QR_CODE: 2, 570 571 // Indicates that barcode photos can be recommended 572 BAR_CODE: 3, 573 574 // Indicates that QR code or barcode photos can be recommended 575 ID_CARD: 4, 576 577 // Indicates that profile picture photos can be recommended 578 PROFILE_PICTURE: 5, 579 580 // Indicates that passport photos can be recommended 581 PASSPORT: 6, 582 583 // Indicates that bank card photos can be recommended 584 BANK_CARD: 7, 585 586 // Indicates that driver license photos can be recommended 587 DRIVER_LICENSE: 8, 588 589 // Indicates that driving license photos can be recommended 590 DRIVING_LICENSE: 9, 591 592 // Indicates that featured single portrait photos can be recommended 593 FEATURED_SINGLE_PORTRAIT: 10 594}; 595 596const PhotoViewMIMETypes = { 597 IMAGE_TYPE: 'image/*', 598 VIDEO_TYPE: 'video/*', 599 IMAGE_VIDEO_TYPE: '*/*', 600 MOVING_PHOTO_IMAGE_TYPE: 'image/movingPhoto', 601 INVALID_TYPE: '' 602}; 603 604const ErrCode = { 605 INVALID_ARGS: 13900020, 606 RESULT_ERROR: 13900042, 607 CONTEXT_NO_EXIST: 16000011, 608}; 609 610const CompleteButtonText = { 611 TEXT_DONE: 0, 612 TEXT_SEND: 1, 613 TEXT_ADD: 2, 614}; 615 616const ERRCODE_MAP = new Map([ 617 [ErrCode.INVALID_ARGS, 'Invalid argument'], 618 [ErrCode.RESULT_ERROR, 'Unknown error'], 619 [ErrCode.CONTEXT_NO_EXIST, 'Current ability failed to obtain context'], 620]); 621 622const PHOTO_VIEW_MIME_TYPE_MAP = new Map([ 623 [PhotoViewMIMETypes.IMAGE_TYPE, 'FILTER_MEDIA_TYPE_IMAGE'], 624 [PhotoViewMIMETypes.VIDEO_TYPE, 'FILTER_MEDIA_TYPE_VIDEO'], 625 [PhotoViewMIMETypes.IMAGE_VIDEO_TYPE, 'FILTER_MEDIA_TYPE_ALL'], 626 [PhotoViewMIMETypes.MOVING_PHOTO_IMAGE_TYPE, 'FILTER_MEDIA_TYPE_IMAGE_MOVING_PHOTO'], 627]); 628 629function checkArguments(args) { 630 let checkArgumentsResult = undefined; 631 632 if (args.length === ARGS_TWO && typeof args[ARGS_ONE] !== 'function') { 633 checkArgumentsResult = getErr(ErrCode.INVALID_ARGS); 634 } 635 636 if (args.length > 0 && typeof args[ARGS_ZERO] === 'object') { 637 let option = args[ARGS_ZERO]; 638 if (option.maxSelectNumber !== undefined) { 639 if (option.maxSelectNumber.toString().indexOf('.') !== -1) { 640 checkArgumentsResult = getErr(ErrCode.INVALID_ARGS); 641 } 642 } 643 } 644 645 return checkArgumentsResult; 646} 647 648function getErr(errCode) { 649 return { code: errCode, message: ERRCODE_MAP.get(errCode) }; 650} 651 652function parsePhotoPickerSelectOption(args) { 653 let config = { 654 action: 'ohos.want.action.photoPicker', 655 type: 'multipleselect', 656 parameters: { 657 uri: 'multipleselect', 658 }, 659 }; 660 661 if (args.length > ARGS_ZERO && typeof args[ARGS_ZERO] === 'object') { 662 let option = args[ARGS_ZERO]; 663 if (option.maxSelectNumber && option.maxSelectNumber > 0) { 664 let select = (option.maxSelectNumber === 1) ? 'singleselect' : 'multipleselect'; 665 config.type = select; 666 config.parameters.uri = select; 667 config.parameters.maxSelectCount = option.maxSelectNumber; 668 } 669 if (option.MIMEType && PHOTO_VIEW_MIME_TYPE_MAP.has(option.MIMEType)) { 670 config.parameters.filterMediaType = PHOTO_VIEW_MIME_TYPE_MAP.get(option.MIMEType); 671 } 672 config.parameters.isSearchSupported = option.isSearchSupported === undefined || option.isSearchSupported; 673 config.parameters.isPhotoTakingSupported = option.isPhotoTakingSupported === undefined || option.isPhotoTakingSupported; 674 config.parameters.isEditSupported = option.isEditSupported === undefined || option.isEditSupported; 675 config.parameters.recommendationOptions = option.recommendationOptions; 676 config.parameters.preselectedUris = option.preselectedUris; 677 config.parameters.isPreviewForSingleSelectionSupported = option.isPreviewForSingleSelectionSupported; 678 config.parameters.isOriginalSupported = option.isOriginalSupported; 679 config.parameters.subWindowName = option.subWindowName; 680 config.parameters.themeColor = option.themeColor; 681 config.parameters.completeButtonText = option.completeButtonText; 682 } 683 684 return config; 685} 686 687function getPhotoPickerSelectResult(args) { 688 let selectResult = { 689 error: undefined, 690 data: undefined, 691 }; 692 693 if (args.resultCode === 0) { 694 let uris = args.uris; 695 let isOrigin = args.isOrigin; 696 selectResult.data = new PhotoSelectResult(uris, isOrigin); 697 } else if (args.resultCode === -1) { 698 selectResult.data = new PhotoSelectResult([], undefined); 699 } else { 700 selectResult.error = getErr(ErrCode.RESULT_ERROR); 701 } 702 703 return selectResult; 704} 705 706async function photoPickerSelect(...args) { 707 let checkArgsResult = checkArguments(args); 708 if (checkArgsResult !== undefined) { 709 console.log('[picker] Invalid argument'); 710 throw checkArgsResult; 711 } 712 713 const config = parsePhotoPickerSelectOption(args); 714 console.log('[picker] config: ' + JSON.stringify(config)); 715 716 let context = undefined; 717 try { 718 context = getContext(this); 719 } catch (getContextError) { 720 console.error('[picker] getContext error: ' + getContextError); 721 throw getErr(ErrCode.CONTEXT_NO_EXIST); 722 } 723 try { 724 if (context === undefined) { 725 throw getErr(ErrCode.CONTEXT_NO_EXIST); 726 } 727 let result = await startPhotoPicker(context, config); 728 console.log('[picker] result: ' + JSON.stringify(result)); 729 const selectResult = getPhotoPickerSelectResult(result); 730 console.log('[picker] selectResult: ' + JSON.stringify(selectResult)); 731 if (args.length === ARGS_TWO && typeof args[ARGS_ONE] === 'function') { 732 return args[ARGS_ONE](selectResult.error, selectResult.data); 733 } else if (args.length === ARGS_ONE && typeof args[ARGS_ZERO] === 'function') { 734 return args[ARGS_ZERO](selectResult.error, selectResult.data); 735 } 736 return new Promise((resolve, reject) => { 737 if (selectResult.data !== undefined) { 738 resolve(selectResult.data); 739 } else { 740 reject(selectResult.error); 741 } 742 }); 743 } catch (error) { 744 console.error('[picker] error: ' + JSON.stringify(error)); 745 } 746 return undefined; 747} 748 749function BaseSelectOptions() { 750 this.MIMEType = PhotoViewMIMETypes.INVALID_TYPE; 751 this.maxSelectNumber = -1; 752 this.isSearchSupported = true; 753 this.isPhotoTakingSupported = true; 754 this.isPreviewForSingleSelectionSupported = true; 755} 756 757function PhotoSelectOptions() { 758 this.MIMEType = PhotoViewMIMETypes.INVALID_TYPE; 759 this.maxSelectNumber = -1; 760 this.isSearchSupported = true; 761 this.isPhotoTakingSupported = true; 762 this.isEditSupported = true; 763 this.isOriginalSupported = false; 764 this.completeButtonText = CompleteButtonText.TEXT_DONE; 765} 766 767function PhotoSelectResult(uris, isOriginalPhoto) { 768 this.photoUris = uris; 769 this.isOriginalPhoto = isOriginalPhoto; 770} 771 772function PhotoViewPicker() { 773 this.select = photoPickerSelect; 774} 775 776function RecommendationOptions() { 777} 778 779class MediaAssetChangeRequest extends photoAccessHelper.MediaAssetChangeRequest { 780 static deleteAssets(context, assets, asyncCallback) { 781 if (arguments.length > ARGS_THREE || arguments.length < ARGS_TWO) { 782 throw new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID); 783 } 784 785 try { 786 if (asyncCallback) { 787 return super.deleteAssets(context, result => { 788 if (result.result === REQUEST_CODE_SUCCESS) { 789 asyncCallback(); 790 } else if (result.result === PERMISSION_DENIED) { 791 asyncCallback(new BusinessError(ERROR_MSG_USER_DENY, ERR_CODE_OHOS_PERMISSION_DENIED)); 792 } else { 793 asyncCallback(new BusinessError(ERROR_MSG_INNER_FAIL, result.result)); 794 } 795 }, assets, asyncCallback); 796 } 797 798 return new Promise((resolve, reject) => { 799 super.deleteAssets(context, result => { 800 if (result.result === REQUEST_CODE_SUCCESS) { 801 resolve(); 802 } else if (result.result === PERMISSION_DENIED) { 803 reject(new BusinessError(ERROR_MSG_USER_DENY, ERR_CODE_OHOS_PERMISSION_DENIED)); 804 } else { 805 reject(new BusinessError(ERROR_MSG_INNER_FAIL, result.result)); 806 } 807 }, assets, (err) => { 808 if (err) { 809 reject(err); 810 } else { 811 resolve(); 812 } 813 }); 814 }); 815 } catch (error) { 816 return errorResult(new BusinessError(error.message, error.code), asyncCallback); 817 } 818 } 819} 820 821export default { 822 getPhotoAccessHelper, 823 startPhotoPicker, 824 getPhotoAccessHelperAsync, 825 PhotoType: photoAccessHelper.PhotoType, 826 ThumbnailType: photoAccessHelper.ThumbnailType, 827 PhotoCreationConfig: photoAccessHelper.PhotoCreationConfig, 828 PhotoKeys: photoAccessHelper.PhotoKeys, 829 AlbumKeys: photoAccessHelper.AlbumKeys, 830 AlbumType: photoAccessHelper.AlbumType, 831 AlbumSubtype: photoAccessHelper.AlbumSubtype, 832 HighlightAlbum: photoAccessHelper.HighlightAlbum, 833 PositionType: photoAccessHelper.PositionType, 834 PhotoSubtype: photoAccessHelper.PhotoSubtype, 835 PhotoPermissionType: photoAccessHelper.PhotoPermissionType, 836 HideSensitiveType: photoAccessHelper.HideSensitiveType, 837 NotifyType: photoAccessHelper.NotifyType, 838 DefaultChangeUri: photoAccessHelper.DefaultChangeUri, 839 HiddenPhotosDisplayMode: photoAccessHelper.HiddenPhotosDisplayMode, 840 AnalysisType: photoAccessHelper.AnalysisType, 841 HighlightAlbumInfoType: photoAccessHelper.HighlightAlbumInfoType, 842 HighlightUserActionType: photoAccessHelper.HighlightUserActionType, 843 RequestPhotoType: photoAccessHelper.RequestPhotoType, 844 PhotoViewMIMETypes: PhotoViewMIMETypes, 845 DeliveryMode: photoAccessHelper.DeliveryMode, 846 SourceMode: photoAccessHelper.SourceMode, 847 AuthorizationMode: photoAccessHelper.AuthorizationMode, 848 CompatibleMode: photoAccessHelper.CompatibleMode, 849 BaseSelectOptions: BaseSelectOptions, 850 PhotoSelectOptions: PhotoSelectOptions, 851 PhotoSelectResult: PhotoSelectResult, 852 PhotoViewPicker: PhotoViewPicker, 853 RecommendationType: RecommendationType, 854 RecommendationOptions: RecommendationOptions, 855 ResourceType: photoAccessHelper.ResourceType, 856 MediaAssetEditData: photoAccessHelper.MediaAssetEditData, 857 MediaAssetChangeRequest: MediaAssetChangeRequest, 858 MediaAssetsChangeRequest: photoAccessHelper.MediaAssetsChangeRequest, 859 MediaAlbumChangeRequest: photoAccessHelper.MediaAlbumChangeRequest, 860 MediaAssetManager: photoAccessHelper.MediaAssetManager, 861 MovingPhoto: photoAccessHelper.MovingPhoto, 862 MovingPhotoEffectMode: photoAccessHelper.MovingPhotoEffectMode, 863 CompleteButtonText: CompleteButtonText, 864 ImageFileType: photoAccessHelper.ImageFileType, 865 CloudEnhancement: photoAccessHelper.CloudEnhancement, 866 CloudEnhancementTaskStage: photoAccessHelper.CloudEnhancementTaskStage, 867 CloudEnhancementState: photoAccessHelper.CloudEnhancementState, 868 CloudEnhancementTaskState: photoAccessHelper.CloudEnhancementTaskState, 869 WatermarkType: photoAccessHelper.WatermarkType, 870 VideoEnhancementType: photoAccessHelper.VideoEnhancementType, 871}; 872