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 358 // only promise type 359 return new Promise((resolve, reject) => { 360 photoAccessHelper.showAssetsCreationDialog(getContext(this), srcFileUris, photoCreationConfigs, bundleName, 361 appName, appId, result => { 362 showAssetsCreationDialogResult(result, reject, resolve); 363 }); 364 }); 365 } catch (error) { 366 return errorResult(new BusinessError(error.message, error.code), null); 367 } 368} 369 370function showAssetsCreationDialog(...params) { 371 if (!checkConfirmBoxParams(...params)) { 372 throw new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID); 373 } 374 return showAssetsCreationDialogParamsOk(...params); 375} 376 377async function createAssetWithShortTermPermissionOk(photoCreationConfig) { 378 let bundleInfo = getBundleInfo(); 379 if (bundleInfo === undefined) { 380 return new Promise((resolve, reject) => { 381 reject(new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID)); 382 }); 383 } 384 385 let bundleName = bundleInfo.name; 386 let appId = bundleInfo.signatureInfo.appId; 387 console.info('photoAccessHelper bundleName is ' + bundleName + '.'); 388 console.info('photoAccessHelper appId is ' + appId + '.'); 389 390 let labelId = bundleInfo.appInfo.labelId; 391 console.info('photoAccessHelper labelId is ' + appId + '.'); 392 let appName = ''; 393 394 try { 395 let modeleName = ''; 396 for (let hapInfo of bundleInfo.hapModulesInfo) { 397 if (labelId === hapInfo.labelId) { 398 modeleName = hapInfo.name; 399 } 400 } 401 console.info('photoAccessHelper modeleName is ' + modeleName + '.'); 402 appName = await gContext.createModuleContext(modeleName).resourceManager.getStringValue(labelId); 403 console.info('photoAccessHelper appName is ' + appName + '.'); 404 405 if (photoAccessHelper.checkShortTermPermission()) { 406 let photoCreationConfigs = [photoCreationConfig]; 407 let desFileUris = await getPhotoAccessHelper(getContext(this)).createAssetsHasPermission(bundleName, appName, appId, 408 photoCreationConfigs); 409 return new Promise((resolve, reject) => { 410 resolve(desFileUris[0]); 411 }); 412 } 413 return new Promise((resolve, reject) => { 414 photoAccessHelper.createAssetWithShortTermPermission(getContext(this), photoCreationConfig, bundleName, appName, 415 appId, result => { 416 showAssetsCreationDialogResult(result, reject, resolve); 417 }); 418 }); 419 } catch (error) { 420 return errorResult(new BusinessError(ERROR_MSG_INNER_FAIL, error.code), null); 421 } 422} 423 424function createAssetWithShortTermPermission(photoCreationConfig) { 425 if (!checkIsPhotoCreationConfigValid(photoCreationConfig)) { 426 throw new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID); 427 } 428 return createAssetWithShortTermPermissionOk(photoCreationConfig); 429} 430 431async function requestPhotoUrisReadPermission(srcFileUris) { 432 console.info('requestPhotoUrisReadPermission enter'); 433 434 //check whether srcFileUris is valid 435 if (srcFileUris === undefined || srcFileUris.length < MIN_CONFIRM_NUMBER) { 436 console.error('photoAccessHelper invalid, array size invalid.'); 437 return false; 438 } 439 for (let srcFileUri of srcFileUris) { 440 if (!checkIsUriValid(srcFileUri, true)) { 441 console.error('photoAccesshelper invalid uri : ${srcFileUri}.'); 442 return false; 443 } 444 } 445 446 let context = gContext; 447 if (context === undefined) { 448 console.info('photoAccessHelper gContet undefined'); 449 context = getContext(this); 450 } 451 452 let bundleInfo = getBundleInfo(); 453 if (bundleInfo === undefined) { 454 return new Promise((resolve, reject) => { 455 reject(new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID)); 456 }); 457 } 458 let labelId = bundleInfo.appInfo.labelId; 459 console.info('photoAccessHelper labelId is ' + labelId + '.'); 460 let appName = ''; 461 462 try { 463 let moduleName = ''; 464 for (let hapInfo of bundleInfo.hapModulesInfo) { 465 if (labelId === hapInfo.labelId) { 466 moduleName = hapInfo.name; 467 } 468 } 469 console.info('photoAccessHelper moduleName is ' + moduleName + '.'); 470 appName = await gContext.createModuleContext(moduleName).resourceManager.getStringValue(labelId); 471 console.info('photoAccessHelper appName is ' + appName + '.'); 472 return new Promise((resolve, reject) => { 473 photoAccessHelper.requestPhotoUrisReadPermission(context, srcFileUris, appName, result => { 474 showAssetsCreationDialogResult(result, reject, resolve); 475 }); 476 }); 477 } catch (error) { 478 console.error('requestPhotoUrisReadPermission catch error.'); 479 return errorResult(new BusinessError(ERROR_MSG_INNER_FAIL, error.code), null); 480 } 481} 482 483function getPhotoAccessHelper(context) { 484 if (context === undefined) { 485 console.log('photoAccessHelper gContext undefined'); 486 throw Error('photoAccessHelper gContext undefined'); 487 } 488 gContext = context; 489 let helper = photoAccessHelper.getPhotoAccessHelper(gContext); 490 if (helper !== undefined) { 491 console.log('photoAccessHelper getPhotoAccessHelper inner add createDeleteRequest and showAssetsCreationDialog'); 492 helper.createDeleteRequest = createDeleteRequest; 493 helper.showAssetsCreationDialog = showAssetsCreationDialog; 494 helper.createAssetWithShortTermPermission = createAssetWithShortTermPermission; 495 helper.requestPhotoUrisReadPermission = requestPhotoUrisReadPermission; 496 } 497 return helper; 498} 499 500function startPhotoPicker(context, config) { 501 if (context === undefined) { 502 console.log('photoAccessHelper gContext undefined'); 503 throw Error('photoAccessHelper gContext undefined'); 504 } 505 if (config === undefined) { 506 console.log('photoAccessHelper config undefined'); 507 throw Error('photoAccessHelper config undefined'); 508 } 509 gContext = context; 510 let helper = photoAccessHelper.startPhotoPicker(gContext, config); 511 if (helper !== undefined) { 512 console.log('photoAccessHelper startPhotoPicker inner add createDeleteRequest'); 513 helper.createDeleteRequest = createDeleteRequest; 514 } 515 return helper; 516} 517 518function getPhotoAccessHelperAsync(context, asyncCallback) { 519 if (context === undefined) { 520 console.log('photoAccessHelper gContext undefined'); 521 throw Error('photoAccessHelper gContext undefined'); 522 } 523 gContext = context; 524 if (arguments.length === 1) { 525 return photoAccessHelper.getPhotoAccessHelperAsync(gContext) 526 .then((helper) => { 527 if (helper !== undefined) { 528 console.log('photoAccessHelper getPhotoAccessHelperAsync inner add createDeleteRequest' + 529 ' and showAssetsCreationDialog'); 530 helper.createDeleteRequest = createDeleteRequest; 531 helper.showAssetsCreationDialog = showAssetsCreationDialog; 532 helper.createAssetWithShortTermPermission = createAssetWithShortTermPermission; 533 helper.requestPhotoUrisReadPermission = requestPhotoUrisReadPermission; 534 } 535 return helper; 536 }) 537 .catch((err) => { 538 console.log('photoAccessHelper getPhotoAccessHelperAsync err ' + err); 539 throw Error(err); 540 }); 541 } else if (arguments.length === ARGS_TWO && typeof asyncCallback === 'function') { 542 photoAccessHelper.getPhotoAccessHelperAsync(gContext, (err, helper) => { 543 console.log('photoAccessHelper getPhotoAccessHelperAsync callback ' + err); 544 if (err) { 545 asyncCallback(err); 546 } else { 547 if (helper !== undefined) { 548 console.log('photoAccessHelper getPhotoAccessHelperAsync callback add createDeleteRequest' + 549 ' and showAssetsCreationDialog'); 550 helper.createDeleteRequest = createDeleteRequest; 551 helper.showAssetsCreationDialog = showAssetsCreationDialog; 552 helper.createAssetWithShortTermPermission = createAssetWithShortTermPermission; 553 helper.requestPhotoUrisReadPermission = requestPhotoUrisReadPermission; 554 } 555 asyncCallback(err, helper); 556 } 557 }); 558 } else { 559 console.log('photoAccessHelper getPhotoAccessHelperAsync param invalid'); 560 throw new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID); 561 } 562 return undefined; 563} 564 565const RecommendationType = { 566 // Indicates that QR code or barcode photos can be recommended 567 QR_OR_BAR_CODE: 1, 568 569 // Indicates that QR code photos can be recommended 570 QR_CODE: 2, 571 572 // Indicates that barcode photos can be recommended 573 BAR_CODE: 3, 574 575 // Indicates that QR code or barcode photos can be recommended 576 ID_CARD: 4, 577 578 // Indicates that profile picture photos can be recommended 579 PROFILE_PICTURE: 5, 580 581 // Indicates that passport photos can be recommended 582 PASSPORT: 6, 583 584 // Indicates that bank card photos can be recommended 585 BANK_CARD: 7, 586 587 // Indicates that driver license photos can be recommended 588 DRIVER_LICENSE: 8, 589 590 // Indicates that driving license photos can be recommended 591 DRIVING_LICENSE: 9, 592 593 // Indicates that featured single portrait photos can be recommended 594 FEATURED_SINGLE_PORTRAIT: 10 595}; 596 597const PhotoViewMIMETypes = { 598 IMAGE_TYPE: 'image/*', 599 VIDEO_TYPE: 'video/*', 600 IMAGE_VIDEO_TYPE: '*/*', 601 MOVING_PHOTO_IMAGE_TYPE: 'image/movingPhoto', 602 INVALID_TYPE: '' 603}; 604 605const ErrCode = { 606 INVALID_ARGS: 13900020, 607 RESULT_ERROR: 13900042, 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]); 620 621const PHOTO_VIEW_MIME_TYPE_MAP = new Map([ 622 [PhotoViewMIMETypes.IMAGE_TYPE, 'FILTER_MEDIA_TYPE_IMAGE'], 623 [PhotoViewMIMETypes.VIDEO_TYPE, 'FILTER_MEDIA_TYPE_VIDEO'], 624 [PhotoViewMIMETypes.IMAGE_VIDEO_TYPE, 'FILTER_MEDIA_TYPE_ALL'], 625 [PhotoViewMIMETypes.MOVING_PHOTO_IMAGE_TYPE, 'FILTER_MEDIA_TYPE_IMAGE_MOVING_PHOTO'], 626]); 627 628function checkArguments(args) { 629 let checkArgumentsResult = undefined; 630 631 if (args.length === ARGS_TWO && typeof args[ARGS_ONE] !== 'function') { 632 checkArgumentsResult = getErr(ErrCode.INVALID_ARGS); 633 } 634 635 if (args.length > 0 && typeof args[ARGS_ZERO] === 'object') { 636 let option = args[ARGS_ZERO]; 637 if (option.maxSelectNumber !== undefined) { 638 if (option.maxSelectNumber.toString().indexOf('.') !== -1) { 639 checkArgumentsResult = getErr(ErrCode.INVALID_ARGS); 640 } 641 } 642 } 643 644 return checkArgumentsResult; 645} 646 647function getErr(errCode) { 648 return { code: errCode, message: ERRCODE_MAP.get(errCode) }; 649} 650 651function parsePhotoPickerSelectOption(args) { 652 let config = { 653 action: 'ohos.want.action.photoPicker', 654 type: 'multipleselect', 655 parameters: { 656 uri: 'multipleselect', 657 }, 658 }; 659 660 if (args.length > ARGS_ZERO && typeof args[ARGS_ZERO] === 'object') { 661 let option = args[ARGS_ZERO]; 662 if (option.maxSelectNumber && option.maxSelectNumber > 0) { 663 let select = (option.maxSelectNumber === 1) ? 'singleselect' : 'multipleselect'; 664 config.type = select; 665 config.parameters.uri = select; 666 config.parameters.maxSelectCount = option.maxSelectNumber; 667 } 668 if (option.MIMEType && PHOTO_VIEW_MIME_TYPE_MAP.has(option.MIMEType)) { 669 config.parameters.filterMediaType = PHOTO_VIEW_MIME_TYPE_MAP.get(option.MIMEType); 670 } 671 config.parameters.isSearchSupported = option.isSearchSupported === undefined || option.isSearchSupported; 672 config.parameters.isPhotoTakingSupported = option.isPhotoTakingSupported === undefined || option.isPhotoTakingSupported; 673 config.parameters.isEditSupported = option.isEditSupported === undefined || option.isEditSupported; 674 config.parameters.recommendationOptions = option.recommendationOptions; 675 config.parameters.preselectedUris = option.preselectedUris; 676 config.parameters.isPreviewForSingleSelectionSupported = option.isPreviewForSingleSelectionSupported; 677 config.parameters.isOriginalSupported = option.isOriginalSupported; 678 config.parameters.subWindowName = option.subWindowName; 679 config.parameters.themeColor = option.themeColor; 680 config.parameters.completeButtonText = option.completeButtonText; 681 } 682 683 return config; 684} 685 686function getPhotoPickerSelectResult(args) { 687 let selectResult = { 688 error: undefined, 689 data: undefined, 690 }; 691 692 if (args.resultCode === 0) { 693 let uris = args.uris; 694 let isOrigin = args.isOrigin; 695 selectResult.data = new PhotoSelectResult(uris, isOrigin); 696 } else if (args.resultCode === -1) { 697 selectResult.data = new PhotoSelectResult([], undefined); 698 } else { 699 selectResult.error = getErr(ErrCode.RESULT_ERROR); 700 } 701 702 return selectResult; 703} 704 705async function photoPickerSelect(...args) { 706 let checkArgsResult = checkArguments(args); 707 if (checkArgsResult !== undefined) { 708 console.log('[picker] Invalid argument'); 709 throw checkArgsResult; 710 } 711 712 const config = parsePhotoPickerSelectOption(args); 713 console.log('[picker] config: ' + JSON.stringify(config)); 714 715 try { 716 let context = getContext(this); 717 let result = await startPhotoPicker(context, config); 718 console.log('[picker] result: ' + JSON.stringify(result)); 719 const selectResult = getPhotoPickerSelectResult(result); 720 console.log('[picker] selectResult: ' + JSON.stringify(selectResult)); 721 if (args.length === ARGS_TWO && typeof args[ARGS_ONE] === 'function') { 722 return args[ARGS_ONE](selectResult.error, selectResult.data); 723 } else if (args.length === ARGS_ONE && typeof args[ARGS_ZERO] === 'function') { 724 return args[ARGS_ZERO](selectResult.error, selectResult.data); 725 } 726 return new Promise((resolve, reject) => { 727 if (selectResult.data !== undefined) { 728 resolve(selectResult.data); 729 } else { 730 reject(selectResult.error); 731 } 732 }); 733 } catch (error) { 734 console.log('[picker] error: ' + error); 735 } 736 return undefined; 737} 738 739function BaseSelectOptions() { 740 this.MIMEType = PhotoViewMIMETypes.INVALID_TYPE; 741 this.maxSelectNumber = -1; 742 this.isSearchSupported = true; 743 this.isPhotoTakingSupported = true; 744 this.isPreviewForSingleSelectionSupported = true; 745} 746 747function PhotoSelectOptions() { 748 this.MIMEType = PhotoViewMIMETypes.INVALID_TYPE; 749 this.maxSelectNumber = -1; 750 this.isSearchSupported = true; 751 this.isPhotoTakingSupported = true; 752 this.isEditSupported = true; 753 this.isOriginalSupported = false; 754 this.completeButtonText = CompleteButtonText.TEXT_DONE; 755} 756 757function PhotoSelectResult(uris, isOriginalPhoto) { 758 this.photoUris = uris; 759 this.isOriginalPhoto = isOriginalPhoto; 760} 761 762function PhotoViewPicker() { 763 this.select = photoPickerSelect; 764} 765 766function RecommendationOptions() { 767} 768 769class MediaAssetChangeRequest extends photoAccessHelper.MediaAssetChangeRequest { 770 static deleteAssets(context, assets, asyncCallback) { 771 if (arguments.length > ARGS_THREE || arguments.length < ARGS_TWO) { 772 throw new BusinessError(ERROR_MSG_PARAMERTER_INVALID, ERR_CODE_OHOS_PARAMERTER_INVALID); 773 } 774 775 try { 776 if (asyncCallback) { 777 return super.deleteAssets(context, result => { 778 if (result.result === REQUEST_CODE_SUCCESS) { 779 asyncCallback(); 780 } else if (result.result === PERMISSION_DENIED) { 781 asyncCallback(new BusinessError(ERROR_MSG_USER_DENY, ERR_CODE_OHOS_PERMISSION_DENIED)); 782 } else { 783 asyncCallback(new BusinessError(ERROR_MSG_INNER_FAIL, result.result)); 784 } 785 }, assets, asyncCallback); 786 } 787 788 return new Promise((resolve, reject) => { 789 super.deleteAssets(context, result => { 790 if (result.result === REQUEST_CODE_SUCCESS) { 791 resolve(); 792 } else if (result.result === PERMISSION_DENIED) { 793 reject(new BusinessError(ERROR_MSG_USER_DENY, ERR_CODE_OHOS_PERMISSION_DENIED)); 794 } else { 795 reject(new BusinessError(ERROR_MSG_INNER_FAIL, result.result)); 796 } 797 }, assets, (err) => { 798 if (err) { 799 reject(err); 800 } else { 801 resolve(); 802 } 803 }); 804 }); 805 } catch (error) { 806 return errorResult(new BusinessError(error.message, error.code), asyncCallback); 807 } 808 } 809} 810 811export default { 812 getPhotoAccessHelper, 813 startPhotoPicker, 814 getPhotoAccessHelperAsync, 815 PhotoType: photoAccessHelper.PhotoType, 816 PhotoCreationConfig: photoAccessHelper.PhotoCreationConfig, 817 PhotoKeys: photoAccessHelper.PhotoKeys, 818 AlbumKeys: photoAccessHelper.AlbumKeys, 819 AlbumType: photoAccessHelper.AlbumType, 820 AlbumSubtype: photoAccessHelper.AlbumSubtype, 821 HighlightAlbum: photoAccessHelper.HighlightAlbum, 822 PositionType: photoAccessHelper.PositionType, 823 PhotoSubtype: photoAccessHelper.PhotoSubtype, 824 PhotoPermissionType: photoAccessHelper.PhotoPermissionType, 825 HideSensitiveType: photoAccessHelper.HideSensitiveType, 826 NotifyType: photoAccessHelper.NotifyType, 827 DefaultChangeUri: photoAccessHelper.DefaultChangeUri, 828 HiddenPhotosDisplayMode: photoAccessHelper.HiddenPhotosDisplayMode, 829 RequestPhotoType: photoAccessHelper.RequestPhotoType, 830 AnalysisType: photoAccessHelper.AnalysisType, 831 HighlightAlbumInfoType: photoAccessHelper.HighlightAlbumInfoType, 832 HighlightUserActionType: photoAccessHelper.HighlightUserActionType, 833 RequestPhotoType: photoAccessHelper.RequestPhotoType, 834 PhotoViewMIMETypes: PhotoViewMIMETypes, 835 DeliveryMode: photoAccessHelper.DeliveryMode, 836 SourceMode: photoAccessHelper.SourceMode, 837 AuthorizationMode: photoAccessHelper.AuthorizationMode, 838 BaseSelectOptions: BaseSelectOptions, 839 PhotoSelectOptions: PhotoSelectOptions, 840 PhotoSelectResult: PhotoSelectResult, 841 PhotoViewPicker: PhotoViewPicker, 842 RecommendationType: RecommendationType, 843 RecommendationOptions: RecommendationOptions, 844 ResourceType: photoAccessHelper.ResourceType, 845 MediaAssetEditData: photoAccessHelper.MediaAssetEditData, 846 MediaAssetChangeRequest: MediaAssetChangeRequest, 847 MediaAssetsChangeRequest: photoAccessHelper.MediaAssetsChangeRequest, 848 MediaAlbumChangeRequest: photoAccessHelper.MediaAlbumChangeRequest, 849 MediaAssetManager: photoAccessHelper.MediaAssetManager, 850 MovingPhoto: photoAccessHelper.MovingPhoto, 851 MovingPhotoEffectMode: photoAccessHelper.MovingPhotoEffectMode, 852 CompleteButtonText: CompleteButtonText, 853 ImageFileType: photoAccessHelper.ImageFileType, 854 CloudEnhancement: photoAccessHelper.CloudEnhancement, 855 CloudEnhancementTaskStage: photoAccessHelper.CloudEnhancementTaskStage, 856 CloudEnhancementState: photoAccessHelper.CloudEnhancementState, 857 CloudEnhancementTaskState: photoAccessHelper.CloudEnhancementTaskState, 858 VideoEnhancementType: photoAccessHelper.VideoEnhancementType, 859 WatermarkType: photoAccessHelper.WatermarkType, 860 CloudMediaAssetManager: photoAccessHelper.CloudMediaAssetManager, 861 CloudMediaDownloadType: photoAccessHelper.CloudMediaDownloadType, 862 CloudMediaRetainType: photoAccessHelper.CloudMediaRetainType, 863 CloudMediaAssetTaskStatus: photoAccessHelper.CloudMediaAssetTaskStatus, 864 CloudMediaTaskPauseCause: photoAccessHelper.CloudMediaTaskPauseCause, 865 CloudMediaAssetStatus: photoAccessHelper.CloudMediaAssetStatus, 866}; 867