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 photoAccessHelper from '@ohos.file.photoAccessHelper'; 17import { fileIo as fs, fileUri } from '@kit.CoreFileKit'; 18import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit'; 19import { bundleManager } from '@kit.AbilityKit'; 20 21const FILTER_MEDIA_TYPE_ALL = 'FILTER_MEDIA_TYPE_ALL'; 22const FILTER_MEDIA_TYPE_IMAGE = 'FILTER_MEDIA_TYPE_IMAGE'; 23const FILTER_MEDIA_TYPE_VIDEO = 'FILTER_MEDIA_TYPE_VIDEO'; 24const FILTER_MEDIA_TYPE_IMAGE_MOVING_PHOTO = 'FILTER_MEDIA_TYPE_IMAGE_MOVING_PHOTO'; 25 26@Component 27export struct PhotoPickerComponent { 28 pickerOptions?: PickerOptions | undefined; 29 onSelect?: (uri: string) => void; 30 onDeselect?: (uri: string) => void; 31 onItemClicked?: (itemInfo: ItemInfo, clickType: ClickType) => boolean; 32 onEnterPhotoBrowser?: (photoBrowserInfo: PhotoBrowserInfo) => boolean; 33 onExitPhotoBrowser?: (photoBrowserInfo: PhotoBrowserInfo) => boolean; 34 onPickerControllerReady?: () => void; 35 onPhotoBrowserChanged?: (browserItemInfo: BaseItemInfo) => boolean; 36 onSelectedItemsDeleted?: ItemsDeletedCallback; 37 onExceedMaxSelected?: ExceedMaxSelectedCallback; 38 onCurrentAlbumDeleted?: CurrentAlbumDeletedCallback; 39 onVideoPlayStateChanged?: VideoPlayStateChangedCallback; 40 @ObjectLink @Watch('onChanged') pickerController: PickerController; 41 private proxy: UIExtensionProxy | undefined; 42 43 private onChanged(): void { 44 if (!this.proxy) { 45 return; 46 } 47 let data = this.pickerController?.data; 48 if (data?.has('SET_SELECTED_URIS')) { 49 this.proxy.send({'selectUris': data?.get('SET_SELECTED_URIS') as Array<string>}); 50 console.info('PhotoPickerComponent onChanged: SET_SELECTED_URIS'); 51 } else if (data?.has('SET_ALBUM_URI')) { 52 this.proxy.send({'albumUri': data?.get('SET_ALBUM_URI') as string}); 53 console.info('PhotoPickerComponent onChanged: SET_ALBUM_URI'); 54 } else if (data?.has('SET_MAX_SELECT_COUNT')) { 55 this.onSetMaxSelectCount(data); 56 } else if (data?.has('SET_PHOTO_BROWSER_ITEM')) { 57 this.onSetPhotoBrowserItem(data); 58 } else { 59 this.otherOnChange(data); 60 } 61 } 62 63 private otherOnChange(data?: Map<string, Object>) { 64 if (data?.has('EXIT_PHOTO_BROWSER')) { 65 this.handleExitPhotoBrowser(); 66 } else if (data?.has('SET_PHOTO_BROWSER_UI_ELEMENT_VISIBILITY')) { 67 this.onSetPhotoBrowserUIElementVisibility(data); 68 } else if (data?.has('CREATE_URI')) { 69 this.onCreateUri(data); 70 console.info('PhotoPickerComponent onChanged: CREATE_URI'); 71 } else if (data?.has('REPLACE_URI')) { 72 this.onReplaceUri(data); 73 console.info('PhotoPickerComponent onChanged: REPLACE_URI'); 74 } else if (data?.has('SAVE_TRUSTED_PHOTO_ASSETS')) { 75 this.onSaveTrustedPhotoAssets(data); 76 console.info('PhotoPickerComponent onChanged: SAVE_REPLACE_PHOTO_ASSETS'); 77 } else { 78 console.info('PhotoPickerComponent onChanged: other case'); 79 } 80 } 81 82 private onSetMaxSelectCount(data?: Map<string, Object>): void { 83 let maxSelected: MaxSelected = data?.get('SET_MAX_SELECT_COUNT') as MaxSelected; 84 let map: Map<MaxCountType, number> | undefined = maxSelected?.data; 85 this.proxy.send({ 86 'totalCount': map?.get(MaxCountType.TOTAL_MAX_COUNT), 87 'photoCount': map?.get(MaxCountType.PHOTO_MAX_COUNT), 88 'videoCount': map?.get(MaxCountType.VIDEO_MAX_COUNT) 89 }); 90 console.info('PhotoPickerComponent onChanged: SET_MAX_SELECT_COUNT'); 91 } 92 93 private onSetPhotoBrowserItem(data?: Map<string, Object>): void { 94 let photoBrowserRangeInfo: PhotoBrowserRangeInfo = data?.get('SET_PHOTO_BROWSER_ITEM') as PhotoBrowserRangeInfo; 95 this.proxy?.send({ 96 'itemUri': photoBrowserRangeInfo?.uri, 97 'photoBrowserRange': photoBrowserRangeInfo?.photoBrowserRange 98 }); 99 console.info('PhotoPickerComponent onChanged: SET_PHOTO_BROWSER_ITEM'); 100 } 101 102 private handleExitPhotoBrowser(): void { 103 this.proxy.send({'exitPhotoBrowser': true}); 104 console.info('PhotoPickerComponent onChanged: EXIT_PHOTO_BROWSER'); 105 } 106 107 private onSetPhotoBrowserUIElementVisibility(data?: Map<string, Object>): void { 108 let photoBrowserUIElementVisibility: PhotoBrowserUIElementVisibility = 109 data?.get('SET_PHOTO_BROWSER_UI_ELEMENT_VISIBILITY') as PhotoBrowserUIElementVisibility; 110 this.proxy?.send({ 111 'elements': photoBrowserUIElementVisibility?.elements, 112 'isVisible': photoBrowserUIElementVisibility?.isVisible 113 }); 114 console.info('PhotoPickerComponent onChanged: SET_PHOTO_BROWSER_UI_ELEMENT_VISIBILITY'); 115 } 116 117 private onCreateUri(data?: Map<string, Object>): void { 118 let array = data?.get('CREATE_URI') as Array<Object>; 119 this.proxy?.send({ 120 selectedMediaUri: array[0], 121 createUri: array[1], 122 date: array[2] 123 }); 124 console.info('PhotoPickerComponent onChanged CREATE_URI'); 125 } 126 127 private onReplaceUri(data?: Map<string, Object>): void { 128 let array = data?.get('REPLACE_URI') as Array<Object>; 129 this.proxy?.send({ 130 oriUri: array[0], 131 replaceUri: array[1], 132 date: array[2] 133 }); 134 console.info('PhotoPickerComponent onChanged REPLACE_URI'); 135 } 136 137 private onSaveTrustedPhotoAssets(data?: Map<string, Object>): void { 138 let array: Array<object> = data?.get('SAVE_TRUSTED_PHOTO_ASSETS') as Array<object>; 139 this.proxy?.send({ 140 replaceUris: array[0], 141 config: array[1], 142 saveMode: array[2], 143 appName: array[3], 144 date: array[4] 145 }); 146 console.info('PhotoPickerComponent onChanged SAVE_REPLACE_PHOTO_ASSETS'); 147 } 148 149 build() { 150 Row() { 151 Column() { 152 SecurityUIExtensionComponent({ 153 parameters: { 154 "ability.want.params.uiExtensionTargetType":"photoPicker", 155 uri: "multipleselect", 156 targetPage: "photoPage", 157 filterMediaType: this.convertMIMETypeToFilterType(this.pickerOptions?.MIMEType), 158 maxSelectNumber: this.pickerOptions?.maxSelectNumber as number, 159 isPhotoTakingSupported: this.pickerOptions?.isPhotoTakingSupported as boolean, 160 isEditSupported: false, 161 recommendationOptions: this.pickerOptions?.recommendationOptions as photoAccessHelper.RecommendationOptions, 162 preselectedUri: this.pickerOptions?.preselectedUris as Array<string>, 163 isFromPickerView: true, 164 isNeedActionBar: false, 165 isNeedSelectBar: false, 166 isSearchSupported: this.pickerOptions?.isSearchSupported as boolean, 167 checkBoxColor: this.pickerOptions?.checkBoxColor as string, 168 backgroundColor: this.pickerOptions?.backgroundColor as string, 169 checkboxTextColor: this.pickerOptions?.checkboxTextColor as string, 170 photoBrowserBackgroundColorMode: this.pickerOptions?.photoBrowserBackgroundColorMode as PickerColorMode, 171 isRepeatSelectSupported: this.pickerOptions?.isRepeatSelectSupported as boolean, 172 maxSelectedReminderMode: this.pickerOptions?.maxSelectedReminderMode as ReminderMode, 173 orientation: this.pickerOptions?.orientation as PickerOrientation, 174 selectMode: this.pickerOptions?.selectMode as SelectMode, 175 maxPhotoSelectNumber: this.pickerOptions?.maxPhotoSelectNumber as number, 176 maxVideoSelectNumber: this.pickerOptions?.maxVideoSelectNumber as number, 177 isOnItemClickedSet: this.onItemClicked? true : false, 178 isPreviewForSingleSelectionSupported: this.pickerOptions?.isPreviewForSingleSelectionSupported as boolean, 179 isSlidingSelectionSupported: this.pickerOptions?.isSlidingSelectionSupported as boolean, 180 photoBrowserCheckboxPosition: this.pickerOptions?.photoBrowserCheckboxPosition as [number, number], 181 gridMargin: this.pickerOptions?.gridMargin as Margin, 182 photoBrowserMargin: this.pickerOptions?.photoBrowserMargin as Margin 183 } 184 }).height('100%').width('100%').onRemoteReady((proxy) => { 185 this.proxy = proxy; 186 console.info('PhotoPickerComponent onRemoteReady'); 187 }).onReceive((data) => { 188 let wantParam: Record<string, Object> = data as Record<string, Object>; 189 this.handleOnReceive(wantParam); 190 }).onError(() => { 191 console.info('PhotoPickerComponent onError'); 192 }); 193 } 194 .width('100%') 195 } 196 .height('100%') 197 } 198 199 private handleOnReceive(wantParam: Record<string, Object>): void { 200 let dataType = wantParam['dataType'] as string; 201 console.info('PhotoPickerComponent onReceive: dataType = ' + dataType); 202 if (dataType === 'selectOrDeselect') { 203 this.handleSelectOrDeselect(wantParam); 204 } else if (dataType === 'itemClick') { 205 this.handleItemClick(wantParam); 206 } else if (dataType === 'onPhotoBrowserStateChanged') { 207 this.handleEnterOrExitPhotoBrowser(wantParam); 208 } else if (dataType === 'remoteReady') { 209 if (this.onPickerControllerReady) { 210 this.onPickerControllerReady(); 211 console.info('PhotoPickerComponent onReceive: onPickerControllerReady'); 212 } 213 } else if (dataType === 'onPhotoBrowserChanged') { 214 this.handlePhotoBrowserChange(wantParam); 215 } else if (dataType === 'onVideoPlayStateChanged') { 216 this.handleVideoPlayStateChange(wantParam) 217 } else if (dataType === 'replaceCallback') { 218 this.handleReplaceCallback(wantParam); 219 } else if (dataType === 'createCallback') { 220 this.handleCreateCallback(wantParam); 221 } else if (dataType === 'saveCallback') { 222 this.handleSaveCallback(wantParam); 223 } else if (dataType === 'onBackground') { 224 console.info('PhotoPickerComponent onReceive: onBackground'); 225 this.revokeIndex = 0; 226 } else { 227 this.handleOtherOnReceive(wantParam); 228 console.info('PhotoPickerComponent onReceive: other case'); 229 } 230 console.info('PhotoPickerComponent onReceive' + JSON.stringify(wantParam)); 231 } 232 233 private handleOtherOnReceive(wantParam: Record<string, Object>): void{ 234 let dataType = wantParam.dataType as string; 235 if (dataType === 'exceedMaxSelected') { 236 if (this.onExceedMaxSelected) { 237 this.onExceedMaxSelected(wantParam.maxCountType as MaxCountType); 238 } 239 } else if (dataType === 'selectedItemsDeleted') { 240 if (this.onSelectedItemsDeleted) { 241 this.onSelectedItemsDeleted(wantParam.selectedItemInfos as Array<BaseItemInfo>); 242 } 243 } else if (dataType === 'currentAlbumDeleted') { 244 if (this.onCurrentAlbumDeleted) { 245 this.onCurrentAlbumDeleted(); 246 } 247 } else { 248 console.info('PhotoPickerComponent onReceive: other case'); 249 } 250 } 251 252 private handleSelectOrDeselect(wantParam: Record<string, Object>): void { 253 let isSelect: boolean = wantParam['isSelect'] as boolean; 254 if (isSelect) { 255 if (this.onSelect) { 256 this.onSelect(wantParam['select-item-list'] as string); 257 console.info('PhotoPickerComponent onReceive: onSelect'); 258 } 259 } else { 260 if (this.onDeselect) { 261 this.onDeselect(wantParam['select-item-list'] as string); 262 console.info('PhotoPickerComponent onReceive: onDeselect'); 263 } 264 } 265 } 266 267 private handleItemClick(wantParam: Record<string, Object>): void { 268 if (this.onItemClicked) { 269 let clickType: ClickType = ClickType.SELECTED; 270 let type = wantParam['clickType'] as string; 271 if (type === 'select') { 272 clickType = ClickType.SELECTED; 273 } else if (type === 'deselect') { 274 clickType = ClickType.DESELECTED; 275 } else { 276 console.info('PhotoPickerComponent onReceive: other clickType'); 277 } 278 let itemInfo: ItemInfo = new ItemInfo(); 279 let itemType: string = wantParam['itemType'] as string; 280 if (itemType === 'thumbnail') { 281 itemInfo.itemType = ItemType.THUMBNAIL; 282 } else if (itemType === 'camera') { 283 itemInfo.itemType = ItemType.CAMERA; 284 } else { 285 console.info('PhotoPickerComponent onReceive: other itemType'); 286 } 287 itemInfo.uri = wantParam['uri'] as string; 288 itemInfo.mimeType = wantParam['mimeType'] as string; 289 itemInfo.width = wantParam['width'] as number; 290 itemInfo.height = wantParam['height'] as number; 291 itemInfo.size = wantParam['size'] as number; 292 itemInfo.duration = wantParam['duration'] as number; 293 let result: boolean = this.onItemClicked(itemInfo, clickType); 294 console.info('PhotoPickerComponent onReceive: onItemClicked = ' + clickType); 295 if (this.proxy) { 296 if (itemType === 'thumbnail' && clickType === ClickType.SELECTED) { 297 this.proxy.send({'clickConfirm': itemInfo.uri, 'isConfirm': result}); 298 console.info('PhotoPickerComponent onReceive: click confirm: uri = ' + itemInfo.uri + 'isConfirm = ' + result); 299 } 300 if (itemType === 'camera') { 301 this.proxy.send({'enterCamera': result}); 302 console.info('PhotoPickerComponent onReceive: enter camera ' + result); 303 } 304 } 305 } 306 } 307 308 private handleEnterOrExitPhotoBrowser(wantParam: Record<string, Object>): void { 309 let isEnter: boolean = wantParam['isEnter'] as boolean; 310 let photoBrowserInfo: PhotoBrowserInfo = new PhotoBrowserInfo(); 311 photoBrowserInfo.animatorParams = new AnimatorParams(); 312 photoBrowserInfo.animatorParams.duration = wantParam['duration'] as number; 313 photoBrowserInfo.animatorParams.curve = wantParam['curve'] as Curve | ICurve | string; 314 if (isEnter) { 315 if (this.onEnterPhotoBrowser) { 316 this.onEnterPhotoBrowser(photoBrowserInfo); 317 } 318 } else { 319 if (this.onExitPhotoBrowser) { 320 this.onExitPhotoBrowser(photoBrowserInfo); 321 } 322 } 323 console.info('PhotoPickerComponent onReceive: onPhotoBrowserStateChanged = ' + isEnter); 324 } 325 326 private handlePhotoBrowserChange(wantParam: Record<string, Object>): void { 327 let browserItemInfo: BaseItemInfo = new BaseItemInfo(); 328 browserItemInfo.uri = wantParam['uri'] as string; 329 if (this.onPhotoBrowserChanged) { 330 this.onPhotoBrowserChanged(browserItemInfo); 331 } 332 console.info('PhotoPickerComponent onReceive: onPhotoBrowserChanged = ' + browserItemInfo.uri); 333 } 334 335 private handleVideoPlayStateChange(wantParam: Record<string, Object>): void { 336 if(this.onVideoPlayStateChanged) { 337 this.onVideoPlayStateChanged(wantParam.state as VideoPlayerState) 338 } 339 console.info('PhotoPickerComponent onReceive: onVideoPlayStateChanged = ' + JSON.stringify(wantParam)); 340 } 341 342 private handleCreateCallback(wantParam: Record<string, Object>): void { 343 this.pickerController.actionCreateCallback(wantParam['grantUri'] as string, wantParam['date'] as number, 344 wantParam['code'] as number, wantParam['message'] as string); 345 console.info('PhotoPickerComponent onReceive: handleCreateCallback'); 346 } 347 348 private handleReplaceCallback(wantParam: Record<string, Object>): void { 349 this.pickerController.actionReplaceCallback(wantParam['date'] as number, 350 { 'name': '', 'code': wantParam['code'] as number, 'message': wantParam['message'] as string }); 351 console.info('PhotoPickerComponent onReceive: handleReplaceCallback'); 352 } 353 354 private handleSaveCallback(wantParam: Record<string, Object>): void { 355 this.pickerController.actionSaveCallback(wantParam['date'] as number, 356 { 'name': '', 'code': wantParam['code'] as number, 'message': wantParam['error'] as string }, 357 wantParam['data'] as Array<string>); 358 console.info('PhotoPickerComponent onReceive: handleSaveCallback'); 359 } 360 361 private convertMIMETypeToFilterType(mimeType: photoAccessHelper.PhotoViewMIMETypes): string { 362 let filterType: string; 363 if (mimeType === photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE) { 364 filterType = FILTER_MEDIA_TYPE_IMAGE; 365 } else if (mimeType === photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE) { 366 filterType = FILTER_MEDIA_TYPE_VIDEO; 367 } else if (mimeType === photoAccessHelper.PhotoViewMIMETypes.MOVING_PHOTO_IMAGE_TYPE) { 368 filterType = FILTER_MEDIA_TYPE_IMAGE_MOVING_PHOTO; 369 } else { 370 filterType = FILTER_MEDIA_TYPE_ALL; 371 } 372 console.info('PhotoPickerComponent convertMIMETypeToFilterType:' + JSON.stringify(filterType)); 373 return filterType; 374 } 375} 376 377export type ItemsDeletedCallback = (baseItemInfos: Array<BaseItemInfo>) => void; 378 379export type ExceedMaxSelectedCallback = (exceedMaxCountType: MaxCountType) => void; 380 381export type CurrentAlbumDeletedCallback = () => void; 382 383export type VideoPlayStateChanged = (state: VideoPlayerState) => {} void; 384 385@Observed 386export class PickerController { 387 data?: Map<string, Object>; 388 replaceCallbackMap: Map<number, Object> = new Map<number, Object>(); 389 saveCallbackMap: Map<number, Object> = new Map<number, Object>(); 390 createCallbackMap: Map<number, Object> = new Map<number, Object>(); 391 392 setData(type: DataType, data: Object) { 393 if (data === undefined) { 394 return; 395 } 396 if (type === DataType.SET_SELECTED_URIS) { 397 if (data instanceof Array) { 398 let uriLists: Array<string> = data as Array<string>; 399 if (uriLists) { 400 this.data = new Map([['SET_SELECTED_URIS', [...uriLists]]]); 401 console.info('PhotoPickerComponent SET_SELECTED_URIS' + JSON.stringify(uriLists)); 402 } 403 } 404 } else if (type === DataType.SET_ALBUM_URI) { 405 let albumUri: string = data as string; 406 if (albumUri !== undefined) { 407 this.data = new Map([['SET_ALBUM_URI', albumUri]]); 408 console.info('PhotoPickerComponent SET_ALBUM_URI' + JSON.stringify(albumUri)); 409 } 410 } else { 411 console.info('PhotoPickerComponent setData: other case'); 412 } 413 } 414 415 setMaxSelected(maxSelected: MaxSelected) { 416 if (maxSelected) { 417 this.data = new Map([['SET_MAX_SELECT_COUNT', maxSelected]]); 418 console.info('PhotoPickerComponent SET_MAX_SELECT_COUNT' + JSON.stringify(maxSelected)); 419 } 420 } 421 422 setPhotoBrowserItem(uri: string, photoBrowserRange?: PhotoBrowserRange) { 423 let photoBrowserRangeInfo: PhotoBrowserRangeInfo = new PhotoBrowserRangeInfo(); 424 photoBrowserRangeInfo.uri = uri; 425 let newPhotoBrowserRange = photoBrowserRange ? photoBrowserRange : PhotoBrowserRange.ALL; 426 photoBrowserRangeInfo.photoBrowserRange = newPhotoBrowserRange; 427 this.data = new Map([['SET_PHOTO_BROWSER_ITEM', photoBrowserRangeInfo]]); 428 console.info('PhotoPickerComponent SET_PHOTO_BROWSER_ITEM' + JSON.stringify(photoBrowserRangeInfo)); 429 } 430 431 exitPhotoBrowser() { 432 this.data = new Map([['EXIT_PHOTO_BROWSER', true]]); 433 console.info('PhotoPickerComponent EXIT_PHOTO_BROWSER'); 434 } 435 436 setPhotoBrowserUIElementVisibility(elements: Array<PhotoBrowserUIElement>, isVisible?: boolean) { 437 let photoBrowserUIElementVisibility: PhotoBrowserUIElementVisibility = new PhotoBrowserUIElementVisibility(); 438 photoBrowserUIElementVisibility.elements = elements; 439 photoBrowserUIElementVisibility.isVisible = isVisible; 440 this.data = new Map([['SET_PHOTO_BROWSER_UI_ELEMENT_VISIBILITY', photoBrowserUIElementVisibility]]); 441 console.info('PhotoPickerComponent SET_PHOTO_BROWSER_UI_ELEMENT_VISIBILITY ' + 442 JSON.stringify(photoBrowserUIElementVisibility)); 443 } 444 445 private async getAppName(): Promise<string> { 446 let flags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_ABILITY | // for appName 447 bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_HAP_MODULE | // for appName 448 bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO | // for appId 449 bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION; // for appInfo 450 let bundleInfo = bundleManager.getBundleInfoForSelfSync(flags); 451 let labelId = bundleInfo.appInfo.labelId; 452 let appName = ''; 453 let moduleName = ''; 454 for (let hapInfo of bundleInfo.hapModulesInfo) { 455 if (labelId === hapInfo.labelId) { 456 moduleName = hapInfo.name; 457 } 458 } 459 appName = await getContext(this).createModuleContext(moduleName).resourceManager.getStringValue(labelId); 460 return appName; 461 } 462 463 replacePhotoPickerPreview(selectedMediaUri: string, replaceUri: string, callback: AsyncCallback<void>) { 464 try { 465 let fd = fs.openSync(replaceUri).fd; 466 fs.close(fd); 467 } catch (err) { 468 callback({'code': 13900002, 'message': 'No such file', name: ''}); 469 return; 470 } 471 let date = Math.random(); 472 this.data = new Map([['CREATE_URI', [selectedMediaUri, replaceUri, date]]]); 473 this.createCallbackMap.set(date, (grantUri: string, code: number, message: string) => { 474 if (code !== 0) { 475 callback({ 'name': '', 'code': code, 'message': message }); 476 return; 477 } 478 let createFd = 0; 479 let replaceFd = 0; 480 try { 481 createFd = fs.openSync(grantUri, fs.OpenMode.READ_WRITE).fd; 482 replaceFd = fs.openSync(replaceUri, fs.OpenMode.READ_ONLY).fd; 483 fs.copyFileSync(replaceFd, createFd); 484 this.data = new Map([['REPLACE_URI', [selectedMediaUri, grantUri, date]]]); 485 this.replaceCallbackMap.set(date, callback); 486 } catch (err) { 487 callback({ 'code': 14000011, 'message': 'System inner fail', name: '' }); 488 } finally { 489 fs.close(createFd); 490 fs.close(replaceFd); 491 } 492 }) 493 } 494 495 saveTrustedPhotoAssets(selectedMediaUris: Array<string>, callback: AsyncCallback<Array<string>>, 496 config?: Array<photoAccessHelper.PhotoCreationConfig>, saveMode?: SaveMode) { 497 if (!selectedMediaUris || selectedMediaUris.length === 0) { 498 callback({'code': 14000002, 'message': 'Invalid URI', name: ''}, []); 499 return; 500 } 501 this.getAppName().then((appName: string)=>{ 502 let date = Math.random(); 503 this.data = new Map([['SAVE_TRUSTED_PHOTO_ASSETS', [selectedMediaUris, config, saveMode, appName, date]]]); 504 this.saveCallbackMap.set(date, callback); 505 }) 506 console.info('PhotoPickerComponent SAVE_TRUSTED_PHOTO_ASSETS '); 507 } 508 509 actionCreateCallback(grantUri: string, date: number, code: number, message: string) { 510 if (this.createCallbackMap.has(date)) { 511 let callback = this.createCallbackMap.get(date) as Function; 512 if (callback) { 513 callback(grantUri, code, message); 514 this.createCallbackMap.delete(date); 515 } 516 } 517 } 518 519 actionReplaceCallback(date: number, err: BusinessError) { 520 if (this.replaceCallbackMap.has(date)) { 521 let callback = this.replaceCallbackMap.get(date) as Function; 522 if (callback) { 523 callback(err); 524 this.replaceCallbackMap.delete(date); 525 } 526 } 527 } 528 529 actionSaveCallback(date: number, err: BusinessError, data: Array<string>) { 530 if (this.saveCallbackMap.has(date)) { 531 let callback = this.saveCallbackMap.get(date) as Function; 532 if (callback) { 533 callback(err, data); 534 this.saveCallbackMap.delete(date); 535 } 536 } 537 } 538} 539 540export class PickerOptions extends photoAccessHelper.BaseSelectOptions { 541 checkBoxColor?: string; 542 backgroundColor?: string; 543 isRepeatSelectSupported?: boolean; 544 checkboxTextColor?: string; 545 photoBrowserBackgroundColorMode?: PickerColorMode; 546 maxSelectedReminderMode?: ReminderMode; 547 orientation?: PickerOrientation; 548 selectMode?: SelectMode; 549 maxPhotoSelectNumber?: number; 550 maxVideoSelectNumber?: number; 551 isSlidingSelectionSupported?: boolean; 552 photoBrowserCheckboxPosition?: [number, number]; 553 gridMargin?: Margin; 554 photoBrowserMargin?: Margin; 555} 556 557export class BaseItemInfo { 558 uri?: string; 559 mimeType?: string; 560 width?: number; 561 height?: number; 562 size?: number; 563 duration?: number; 564} 565 566export class ItemInfo extends BaseItemInfo { 567 itemType?: ItemType; 568} 569 570export class PhotoBrowserInfo { 571 animatorParams?: AnimatorParams; 572} 573 574export class AnimatorParams { 575 duration?: number; 576 curve?: Curve | ICurve | string; 577} 578 579export class MaxSelected { 580 data?: Map<MaxCountType, number>; 581} 582 583class PhotoBrowserRangeInfo { 584 uri?: string; 585 photoBrowserRange?: PhotoBrowserRange; 586} 587 588class PhotoBrowserUIElementVisibility { 589 elements?: Array<PhotoBrowserUIElement>; 590 isVisible?: boolean; 591} 592 593export enum DataType { 594 SET_SELECTED_URIS = 1, 595 SET_ALBUM_URI = 2 596} 597 598export enum ItemType { 599 THUMBNAIL = 0, 600 CAMERA = 1 601} 602 603export enum ClickType { 604 SELECTED = 0, 605 DESELECTED = 1 606} 607 608export enum PickerOrientation { 609 VERTICAL = 0, 610 HORIZONTAL = 1 611} 612 613export enum SelectMode { 614 SINGLE_SELECT = 0, 615 MULTI_SELECT = 1 616} 617 618export enum PickerColorMode { 619 AUTO = 0, 620 LIGHT = 1, 621 DARK = 2 622} 623 624export enum ReminderMode { 625 NONE = 0, 626 TOAST = 1, 627 MASK = 2 628} 629 630export enum MaxCountType { 631 TOTAL_MAX_COUNT = 0, 632 PHOTO_MAX_COUNT = 1, 633 VIDEO_MAX_COUNT = 2 634} 635 636export enum PhotoBrowserRange { 637 ALL = 0, 638 SELECTED_ONLY = 1 639} 640 641export enum PhotoBrowserUIElement { 642 CHECKBOX = 0, 643 BACK_BUTTON = 1 644} 645 646export enum VideoPlayerState { 647 PLAYING = 0, 648 PAUSED = 1, 649 STOPPED = 3, 650 SEEK_START = 4, 651 SEEK_FINISH = 5 652} 653 654export enum SaveMode { 655 SAVE_AS = 0, 656 OVERWRITE = 1 657}