1/* 2 * Copyright (c) 2022-2023 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 router from '@ohos.router'; 17import { 18 Action, 19 AlbumDefine, 20 BigDataConstants, 21 BroadCast, 22 BroadCastConstants, 23 BroadCastManager, 24 CommonObserverCallback, 25 Constants, 26 Log, 27 MediaItem, 28 MediaObserver, 29 PhotoDataImpl, 30 ReportToBigDataUtil, 31 ScreenManager, 32 SelectUtil, 33 ThirdSelectManager, 34 UiUtil, 35 UserFileManagerAccess, 36 ViewData, 37 BrowserDataFactory, 38 MediaDataSource 39} from '@ohos/common'; 40import { 41 BrowserController, 42 GridScrollBar, 43 ImageGridItemComponent, 44 NoPhotoComponent, 45 NoPhotoIndexComponent 46} from '@ohos/common/CommonComponents'; 47import { ThirdSelectedPageActionBar } from './ThirdSelectedPageActionBar'; 48import { ThirdSelectedPanel } from './ThirdSelectedPanel'; 49import { CameraGridItemComponent } from './CameraGridItemComponent'; 50import { 51 FormConstants, 52 IS_HORIZONTAL, 53 IS_SPLIT_MODE, 54 LEFT_BLANK, 55 SelectParams, 56 THIRD_SELECT_IS_ORIGIN 57} from '../utils/ThirdSelectConstants'; 58import ability from '@ohos.ability.ability'; 59import common from '@ohos.app.ability.common'; 60import SmartPickerRecommendInfo from '../common/SmartPickerRecommendInfo'; 61import SmartPickerRecommendInfoObserver from '../common/SmartPickerRecommendInfoObserver'; 62import { PickerMediaDataSource } from '../common/PickerMediaDataSource'; 63import SmartPickerDataImpl from '../common/SmartPickerDataImpl'; 64import SmartPickerRecommendTabInfo from '../common/SmartPickerRecommendTabInfo'; 65import SmartPickerConstants from '../common/SmartPickerConstants'; 66import { SmartPickerManager } from '../common/SmartPickerManager'; 67import { ThirdSelectSmartRecommendTabBar } from './ThirdSelectSmartRecommendTabBar'; 68import SmartPickerDataAdapter from '../common/SmartPickerDataAdapter'; 69import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; 70 71const TAG: string = 'thiSel_ThirdSelectPhotoGridBase'; 72 73let localStorage = LocalStorage.getShared(); 74 75// Third Select Album Page 76@Component 77export struct ThirdSelectPhotoGridBase { 78 @State selectedCount: number = 0; 79 @Provide isSelectedMode: boolean = true; 80 @Provide moreMenuList: Action[] = []; 81 @Provide rightClickMenuList: Action[] = []; 82 photoDataImpl: PhotoDataImpl | undefined = 83 BrowserDataFactory.getFeature(BrowserDataFactory.TYPE_PHOTO) as PhotoDataImpl; 84 smartPickerDataImpl: SmartPickerDataImpl | undefined; 85 dataSource: PickerMediaDataSource = new PickerMediaDataSource(Constants.DEFAULT_SLIDING_WIN_SIZE, this.photoDataImpl); 86 @Provide broadCast: BroadCast = new BroadCast(); 87 @Provide isShow: boolean = true; 88 selectManager: ThirdSelectManager | null = null; 89 isActive = false; 90 @State title: string = ''; 91 @State isEmpty: boolean = false; 92 @StorageLink(IS_SPLIT_MODE) isSplitMode: boolean = ScreenManager.getInstance().isSplitMode(); 93 @StorageLink(LEFT_BLANK) leftBlank: number[] = 94 [0, ScreenManager.getInstance().getStatusBarHeight(), 0, ScreenManager.getInstance().getNaviBarHeight()]; 95 @StorageLink(IS_HORIZONTAL) isHorizontal: boolean = ScreenManager.getInstance().isHorizontal(); 96 DEFAULT_TOAST_DURATION = 2000; 97 @State gridRowCount: number = 0; 98 @State isShowScrollBar: boolean = false; 99 @State currentUri: string = ''; 100 @Provide isShowBar: boolean = true; 101 scroller: Scroller = new Scroller(); 102 isFirstEnter: boolean = false; 103 @Prop @Watch('onPageChanged') pageStatus: boolean = false; 104 backFuncBinder: Function | null = null; 105 @State selectParams: SelectParams = SelectParams.defaultParam(); 106 @State screenHeight: number = ScreenManager.getInstance().getWinHeight(); 107 @StorageLink('placeholderIndex') @Watch('onPlaceholderChanged') placeholderIndex: number = -1; 108 @ObjectLink @Watch('onBrowserControllerChanged') browserController: BrowserController; 109 @State isShowSmartRecommendTabBar: boolean = false; 110 @State smartRecommendTabItems: Array<SmartPickerRecommendTabInfo> = []; 111 @State isAllMediaAlbum: boolean = true; 112 @State currentSmartRecommendTabIndex: number = 0; 113 private smartPickerRecommendInfoObserver: SmartPickerRecommendInfoObserver = 114 new SmartPickerRecommendInfoObserver(this); 115 private smartPickerManager: SmartPickerManager | undefined; 116 private appBroadCast: BroadCast = BroadCastManager.getInstance().getBroadCast(); 117 private dataObserver: CommonObserverCallback = new CommonObserverCallback(this); 118 private selectFromCameraFunc: Function = (): void => {}; 119 private itemId: string = ''; 120 private isItemIdChange: boolean = false; 121 private onWindowSizeChangeCallBack: Function = () => this.initGridRowCount(); 122 private selectFunc: Function = (position: number, key: string, value: boolean, callback: Function): void => 123 this.onSelectCallback(position, key, value, callback); 124 private jumpThirdPhotoBrowserFunc: Function = (name: string, item: MediaItem, geometryTapIndex: number, 125 geometryTransitionString: string, isSelectMode = false): void => 126 this.jumpBrowserCallback(name, item, geometryTapIndex, geometryTransitionString, isSelectMode); 127 private onDataReloadedFunc: Function = (): void => this.onReloadFinishedCallback(); 128 private onSwitchSmartRecommendTabFunc: Function = (index: number): void => this.onSwitchSmartRecommendTab(index); 129 private funcOnLoadingFinished: Function = (size: number): void => this.onLoadingFinished(size); 130 private pickerInitDataFirstQueryFinishFunc: Function = (): void => this.pickerInitDataFirstQueryFinish(); 131 132 onPlaceholderChanged() { 133 Log.debug(TAG, 'onPlaceholderChanged placeholderIndex is ' + this.placeholderIndex); 134 if (this.placeholderIndex != -1) { 135 this.scroller.scrollToIndex(this.placeholderIndex); 136 } 137 } 138 139 private onSwitchSmartRecommendTab(index: number): void { 140 Log.debug(TAG, ' onSwitchSmartRecommendTab index:' + index) 141 AppStorage.setOrCreate<number>('placeholderIndex', Constants.INVALID); 142 this.currentSmartRecommendTabIndex = index; 143 Log.debug(TAG, ' onSwitchSmartRecommendTab this.isShowSmartRecommendTabBar:' + this.isShowSmartRecommendTabBar) 144 if (this.isShowSmartRecommendTabBar) { 145 this.selectParams.cameraAble = this.smartRecommendTabItems[this.currentSmartRecommendTabIndex].isCameraAble(); 146 } 147 this.dataSource.changeDataImpl(this.currentSmartRecommendTabIndex === 0 ? 148 this.photoDataImpl : this.smartPickerDataImpl); 149 this.smartRecommendTabItems[this.currentSmartRecommendTabIndex].setUserClickTab(true); 150 this.dataSource.setAlbumUri(this.smartRecommendTabItems[this.currentSmartRecommendTabIndex].getAlbumUri()); 151 this.dataSource.resetActiveWindow(); 152 this.dataSource.initData(); 153 } 154 155 onBrowserControllerChanged(): void { 156 if (!this.browserController.isBrowserShow) { 157 ScreenManager.getInstance().setSystemUi(true); 158 } 159 } 160 161 onMenuClicked(action: Action) { 162 Log.info(TAG, `onMenuClicked, action: ${action.actionID}`); 163 if (action.actionID === Action.BACK.actionID) { 164 this.goBackFormEditor(); 165 } else if (action.actionID === Action.CANCEL.actionID) { 166 this.setPickResult(); 167 } else if (action.actionID === Action.OK.actionID) { 168 let uriArray: string[] = []; 169 if (this.selectManager !== null) { 170 uriArray = SelectUtil.getUriArray(this.selectManager.clickedSet); 171 } 172 this.setPickResult(uriArray); 173 } else if (action.actionID === Action.NAVIGATION_ALBUMS.actionID) { 174 let params = this.selectParams; 175 params.isFirstEnter = false; 176 router.pushUrl({ 177 url: 'pages/ThirdSelectAlbumSetPage', 178 params: this.selectParams 179 }) 180 ReportToBigDataUtil.report(BigDataConstants.SELECT_PICKER_SWITCH_ALBUM, undefined); 181 } 182 } 183 184 aboutToAppear(): void { 185 let param: SelectParams; 186 if (localStorage?.has(Constants.PHOTO_PICKER_SESSION_KEY)) { 187 param = localStorage.get<SelectParams>(Constants.PHOTO_PICKER_PARAMS_KEY) as SelectParams; 188 } else { 189 param = router.getParams() as SelectParams; 190 } 191 this.initSelectParams(param); 192 if (param && param.preselectedUris) { 193 this.selectParams.preselectedUris = param.preselectedUris; 194 } 195 this.selectParams.cameraAble = param.cameraAble; 196 197 // 更新编辑许可 198 this.selectParams.editAble = param.editAble; 199 AppStorage.setOrCreate<boolean>(Constants.KEY_OF_IS_THIRD_EDITABLE, this.selectParams.editAble); 200 if (this.selectParams.isFromFa) { 201 this.selectParams.filterMediaType = AlbumDefine.FILTER_MEDIA_TYPE_IMAGE; 202 AppStorage.setOrCreate(FormConstants.FORM_ITEM_ALBUM_URI, param.uri); 203 AppStorage.setOrCreate(FormConstants.FORM_ITEM_DISPLAY_NAME, param.itemDisplayName); 204 } 205 this.dataSource.setFilterMediaType(this.selectParams.filterMediaType); 206 this.initSelectManager(); 207 this.selectManager?.setIsMultiPick(this.selectParams.isMultiPick); 208 209 let self = this; 210 // 后续phone缩略图支持横竖屏后再放开 211 if (AppStorage.Get('deviceType') as string !== Constants.DEFAULT_DEVICE_TYPE) { 212 ScreenManager.getInstance().on(ScreenManager.ON_WIN_SIZE_CHANGED, this.onWindowSizeChangeCallBack); 213 } 214 this.initGridRowCount(); 215 if (localStorage && localStorage.has(SmartPickerConstants.SMART_PICKER_MANAGER)) { 216 this.smartPickerManager = localStorage.get<SmartPickerManager>(SmartPickerConstants.SMART_PICKER_MANAGER); 217 if (this.smartPickerManager) { 218 this.smartPickerManager.addPickerRecommendInfoListener(this.smartPickerRecommendInfoObserver); 219 } 220 } 221 this.dataSource.setBroadCast(this.broadCast); 222 this.broadCast.on(BroadCastConstants.SELECT, this.selectFunc); 223 this.broadCast.on(BroadCastConstants.JUMP_THIRD_PHOTO_BROWSER, this.jumpThirdPhotoBrowserFunc); 224 this.broadCast.on(Constants.ON_LOADING_FINISHED, this.funcOnLoadingFinished); 225 this.broadCast.on(BroadCastConstants.ON_DATA_RELOADED, this.onDataReloadedFunc); 226 this.broadCast.on(SmartPickerConstants.PICKER_INIT_DATA_FIRST_QUERY_FINISH, 227 this.pickerInitDataFirstQueryFinishFunc); 228 this.selectManager?.registerCallback('updateCount', 229 (newState: number) => { 230 Log.info(TAG, `updateSelectedCount ${newState}`); 231 self.selectedCount = newState; 232 self.selectManager?.emitCallback('thirdSelectUpdateCount', [newState]); 233 }); 234 this.dataSource.registerCallback('updateCount', 235 (newState: number) => { 236 Log.info(TAG, `updateTotalCount ${newState}`); 237 self.isShowScrollBar = (newState > Constants.PHOTOS_CNT_FOR_HIDE_SCROLL_BAR); 238 self.selectManager?.setTotalCount(newState); 239 }); 240 this.broadCast.on(BroadCastConstants.THIRD_PICKER_SWITCH_SMART_RECOMMEND_TAB, this.onSwitchSmartRecommendTabFunc); 241 MediaObserver.getInstance().registerObserver(this.dataObserver); 242 this.isActive = true; 243 244 // save all photo dataSource 245 if (this.dataSource.albumUri === '' && AppStorage.get<MediaDataSource>(Constants.APP_KEY_ALL_PHOTO_DATASOURCE) === undefined) { 246 AppStorage.setOrCreate(Constants.APP_KEY_ALL_PHOTO_DATASOURCE, this.dataSource); 247 } 248 Log.error(TAG, 'meow data count = ' + this.dataSource.totalCount()); 249 } 250 251 onBackPress() { 252 this.onMenuClicked(this.selectParams.isFromFa ? Action.BACK : Action.CANCEL); 253 } 254 255 onPageShow() { 256 Log.debug(TAG, 'onPageShow'); 257 let param: SelectParams = router.getParams() as SelectParams; 258 this.isItemIdChange = (this.itemId && param && this.itemId !== param.itemId) as boolean; 259 if (this.isItemIdChange) { 260 this.initSelectParams(param); 261 } 262 263 MediaObserver.getInstance().registerObserver(this.dataObserver); 264 this.appBroadCast.emit(BroadCastConstants.THIRD_ROUTE_PAGE, []); 265 this.isShow = true; 266 if (!this.browserController.isBrowserShow) { 267 ScreenManager.getInstance().setSystemUi(true); 268 } 269 this.onActive(); 270 } 271 272 onPageChanged() { 273 if (this.pageStatus) { 274 this.onPageShow(); 275 } else { 276 this.onPageHide(); 277 } 278 } 279 280 onPageHide() { 281 Log.debug(TAG, 'onPageHide'); 282 this.isShow = false; 283 this.onInActive(); 284 } 285 286 aboutToDisappear(): void { 287 ScreenManager.getInstance().off(ScreenManager.ON_WIN_SIZE_CHANGED, this.onWindowSizeChangeCallBack); 288 MediaObserver.getInstance().unregisterObserver(this.dataObserver); 289 if (this.smartPickerManager) { 290 this.smartPickerManager.removePickerRecommendInfoListener(this.smartPickerRecommendInfoObserver); 291 } 292 this.dataObserver.clearSource(); 293 if (this.broadCast) { 294 this.broadCast.off(BroadCastConstants.SELECT, this.selectFunc); 295 this.broadCast.off(BroadCastConstants.JUMP_THIRD_PHOTO_BROWSER, this.jumpThirdPhotoBrowserFunc); 296 this.broadCast.off(BroadCastConstants.ON_DATA_RELOADED, this.onDataReloadedFunc); 297 this.broadCast.off(BroadCastConstants.THIRD_PICKER_SWITCH_SMART_RECOMMEND_TAB, 298 this.onSwitchSmartRecommendTabFunc); 299 this.broadCast.off(SmartPickerConstants.PICKER_INIT_DATA_FIRST_QUERY_FINISH, 300 this.pickerInitDataFirstQueryFinishFunc); 301 this.broadCast.off(Constants.ON_LOADING_FINISHED, this.funcOnLoadingFinished); 302 } 303 this.dataSource.releaseBroadCast(); 304 this.selectManager?.releaseGetMediaItemFunc(); 305 this.selectManager?.unregisterCallback('updateCount'); 306 Log.info(TAG, `call aboutToDisappear`) 307 } 308 309 onSmartPickerRecommendInfoListReady(pickerRecommendInfoList: SmartPickerRecommendInfo[], 310 dataAdapter: SmartPickerDataAdapter): void { 311 let param: SelectParams = router.getParams() as SelectParams; 312 if (pickerRecommendInfoList === undefined || pickerRecommendInfoList === null || 313 pickerRecommendInfoList.length === 0) { 314 return; 315 } 316 if (this.smartPickerDataImpl === undefined || this.smartPickerDataImpl === null) { 317 this.smartPickerDataImpl = new SmartPickerDataImpl(); 318 this.smartPickerDataImpl.setDataAdapter(dataAdapter); 319 } 320 let tabInfo = new SmartPickerRecommendTabInfo(); 321 tabInfo.setCameraAble(param ? param.cameraAble : this.selectParams.cameraAble); 322 tabInfo.setAlbumUri(''); 323 tabInfo.setLabelId(SmartPickerConstants.LABEL_ALL_PHOTO); 324 this.smartRecommendTabItems.push(tabInfo); 325 pickerRecommendInfoList.forEach((item, index) => { 326 let tabInfo = new SmartPickerRecommendTabInfo(); 327 tabInfo.setLabelId(item.getLabelId()); 328 tabInfo.setRecommendType(item.getRecommendType()); 329 tabInfo.setAlbumUri(item.getAlbumUri()); 330 tabInfo.setTotalCount(item.getTotalCount()); 331 tabInfo.setRecommendContent(item.getRecommendContent()); 332 tabInfo.setCameraAble(false); 333 this.smartRecommendTabItems.push(tabInfo); 334 }); 335 this.isShowSmartRecommendTabBar = true; 336 this.onSwitchSmartRecommendTab(this.currentSmartRecommendTabIndex); 337 } 338 339 onMediaLibDataChange(changeType: string): void { 340 Log.info(TAG, `onMediaLibDataChange type: ${changeType}`); 341 this.dataSource.onChange(changeType); 342 } 343 344 getGeometryTransitionId(item: ViewData, index: number): string { 345 let mediaItem = item.mediaItem as MediaItem; 346 if (mediaItem) { 347 return TAG + mediaItem.getHashCode() + (this.selectManager?.isItemSelected(mediaItem.uri as string) ?? false); 348 } else { 349 return TAG + item.viewIndex; 350 } 351 } 352 353 @Builder 354 buildGrid() { 355 Grid(this.scroller) { 356 if (!this.selectParams.isFromFa && this.selectParams.cameraAble) { 357 GridItem() { 358 CameraGridItemComponent({ 359 selectParams: this.selectParams, 360 updateDataFunc: (uri: string) => { 361 Log.debug(TAG, `get camera callback, uri ${uri}`) 362 this.dataSource.initData(); 363 this.selectFromCameraFunc = () => { 364 this.onSelectCallback(0, uri, true, () => {}); 365 } 366 } 367 }) 368 } 369 .aspectRatio(1) 370 } 371 LazyForEach(this.dataSource, (item: ViewData, index?: number) => { 372 if (item?.mediaItem) { 373 GridItem() { 374 ImageGridItemComponent({ 375 dataSource: this.dataSource, 376 item: item?.mediaItem, 377 isSelected: this.selectManager?.isItemSelected((item.mediaItem as MediaItem).uri as string) ?? false, 378 pageName: Constants.PHOTO_TRANSITION_ALBUM, 379 isThird: true, 380 mPosition: item?.viewIndex, 381 isThirdMultiPick: this.selectParams.isMultiPick, 382 geometryTransitionString: this.getGeometryTransitionId(item, index as number), 383 selectedCount: $selectedCount 384 }) 385 } 386 .aspectRatio(1) 387 .zIndex(index === this.placeholderIndex ? 1 : 0) 388 } 389 }, (item: ViewData, index?: number) => { 390 if (item == null || item == undefined) { 391 return JSON.stringify(item) + index; 392 } 393 return this.getGeometryTransitionId(item, index as number); 394 }) 395 } 396 .edgeEffect(EdgeEffect.Spring) 397 .scrollBar(BarState.Off) 398 .gridStyle(this.gridRowCount) 399 } 400 401 build() { 402 Column() { 403 ThirdSelectedPageActionBar({ 404 leftAction: this.selectParams.isFromFa ? Action.BACK : Action.CANCEL, 405 isSelectPhotoGrid: true, 406 title: $title, 407 selectParams: this.selectParams, 408 onMenuClicked: (action: Action): void => this.onMenuClicked(action), 409 isFirstEnter: this.isFirstEnter, 410 totalSelectedCount: $selectedCount 411 }) 412 413 if (this.isEmpty) { 414 if (this.selectParams.isFromFa) { 415 NoPhotoIndexComponent({ index: Constants.TIMELINE_PAGE_INDEX, hasBarSpace: false }) 416 } else { 417 if (!this.selectParams.cameraAble) { 418 NoPhotoComponent({ title: $r('app.string.no_distributed_photo_head_title_album') }) 419 } 420 } 421 } 422 if (this.isShowSmartRecommendTabBar && this.isAllMediaAlbum) { 423 ThirdSelectSmartRecommendTabBar({ 424 smartRecommendTabItems: this.smartRecommendTabItems, 425 currentTabIndex: this.currentSmartRecommendTabIndex 426 }) 427 } 428 Stack() { 429 this.buildGrid() 430 if (this.isShowScrollBar) { 431 GridScrollBar({ scroller: this.scroller }); 432 } 433 } 434 .layoutWeight(1) 435 436 if (this.selectParams.isMultiPick) { 437 ThirdSelectedPanel({ 438 maxSelectCount: this.selectParams.maxSelectCount, 439 onMenuClicked: (action: Action): void => this.onMenuClicked(action), 440 mTransition: TAG, 441 currentUri: this.currentUri, 442 isShowBar: $isShowBar, 443 totalSelectedCount: $selectedCount, 444 dataSource: this.dataSource 445 }) 446 } 447 } 448 .backgroundColor($r('sys.color.ohos_id_color_sub_background')) 449 .padding({ 450 top: this.leftBlank[1], 451 bottom: this.leftBlank[3] 452 }) 453 } 454 455 jumpToBrowserNormal(targetIndex: number, name: string, item: MediaItem, isSelectMode = false): void { 456 interface AniParams { 457 position: number; 458 bundleName: string; 459 transition: string; 460 title: string; 461 selectMode: boolean; 462 maxSelectCount: number; 463 isFromFa: boolean; 464 } 465 let params: AniParams = { 466 position: targetIndex, 467 bundleName: this.selectParams.bundleName, 468 transition: name, 469 title: this.title, 470 selectMode: isSelectMode, 471 maxSelectCount: this.selectParams.maxSelectCount, 472 isFromFa: this.selectParams.isFromFa, 473 }; 474 475 router.pushUrl({ 476 url: 'pages/ThirdSelectPhotoBrowser', 477 params: params 478 }); 479 } 480 481 jumpToBrowserGeometryTransition(targetIndex: number, name: string, item: MediaItem, isSelectMode = false, 482 geometryTapIndex: number, 483 geometryTransitionString: string): void { 484 interface AniParams { 485 position: number; 486 bundleName: string; 487 transition: string; 488 title: string; 489 selectMode: boolean; 490 maxSelectCount: number; 491 isFromFa: boolean; 492 } 493 494 let params: AniParams = { 495 position: targetIndex, 496 bundleName: this.selectParams.bundleName, 497 transition: name, 498 title: this.title, 499 selectMode: isSelectMode, 500 maxSelectCount: this.selectParams.maxSelectCount, 501 isFromFa: this.selectParams.isFromFa, 502 }; 503 this.browserController.showBrowser(geometryTapIndex, geometryTransitionString, TAG, params); 504 } 505 506 private initGridRowCount(): void { 507 let contentWidth = ScreenManager.getInstance().getWinWidth(); 508 let margin = 0; 509 let maxThumbWidth = px2vp(Constants.GRID_IMAGE_SIZE) * Constants.GRID_MAX_SIZE_RATIO; 510 let calCount = Math.round( 511 ((contentWidth - Constants.NUMBER_2 * margin) + Constants.GRID_GUTTER) / 512 (maxThumbWidth + Constants.GRID_GUTTER)); 513 let newCount = Math.max(Constants.GRID_MIN_COUNT, calCount); 514 if (newCount != this.gridRowCount) { 515 this.gridRowCount = newCount; 516 } 517 Log.info(TAG, `initGridRowCount contentWidth: ${contentWidth}, row count ${this.gridRowCount}`); 518 } 519 520 private initSelectParams(param?: SelectParams): void { 521 if (param) { 522 this.isItemIdChange = 523 (this.itemId !== undefined && this.itemId !== null && this.itemId !== param.itemId) as boolean; 524 this.itemId = param.itemId == undefined ? AlbumDefine.ALBUM_ID_ALL : param.itemId; 525 this.dataSource.setAlbumUri(this.itemId as string); 526 527 let albumUri = param.uri === undefined ? 528 UserFileManagerAccess.getInstance().getSystemAlbumUri(UserFileManagerAccess.IMAGE_ALBUM_SUB_TYPE) : 529 param.uri; 530 this.dataSource.setAlbumUri(this.isShowSmartRecommendTabBar ? 531 this.smartRecommendTabItems[this.currentSmartRecommendTabIndex].getAlbumUri() : albumUri); 532 this.updateTitle(param); 533 this.selectParams.bundleName = param.bundleName; 534 this.selectParams.isMultiPick = param.isMultiPick; 535 if (param.isFromFa != undefined || param.isFromFa != null) { 536 this.selectParams.isFromFa = param.isFromFa; 537 } 538 if (param.isFromFaPhoto != undefined || param.isFromFaPhoto != null) { 539 this.selectParams.isFromFaPhoto = param.isFromFaPhoto; 540 } 541 if (param.isFirstEnter != undefined || param.isFirstEnter != null) { 542 this.isFirstEnter = param.isFirstEnter; 543 } 544 if (!!param.filterMediaType) { 545 this.selectParams.filterMediaType = param.filterMediaType; 546 } 547 this.selectParams.isFromWallpaper = param.isFromWallpaper; 548 if (this.selectParams.isFromWallpaper) { 549 this.selectParams.maxSelectCount = param.remainingOfWallpapers; 550 } else if (!!param.maxSelectCount && param.maxSelectCount > 0) { 551 this.selectParams.maxSelectCount = param.maxSelectCount > Constants.LIMIT_MAX_THIRD_SELECT_COUNT 552 ? Constants.LIMIT_MAX_THIRD_SELECT_COUNT 553 : param.maxSelectCount; 554 } 555 if (this.backFuncBinder) { 556 this.backFuncBinder((): void => this.onBackPress()); 557 } 558 Log.debug(TAG, `select param ${JSON.stringify(this.selectParams)}`); 559 } 560 this.isSelectedMode = this.selectParams.isMultiPick; 561 Log.debug(TAG, `select param ${JSON.stringify(this.selectParams)}, select mode ${this.isSelectedMode}`); 562 } 563 564 private updateTitle(param?: SelectParams): void { 565 let displayName = param?.itemDisplayName == undefined ? $r('app.string.album_all') : param.itemDisplayName; 566 if (typeof displayName === 'object') { 567 UiUtil.getResourceString(displayName as Resource).then((stringResource: string) => { 568 this.title = stringResource; 569 }) 570 } else { 571 this.title = displayName as string; 572 } 573 Log.debug(TAG, `update title ${this.title}`); 574 } 575 576 private onSelectCallback(position: number, key: string, value: boolean, callback: Function): void{ 577 Log.debug(TAG, `isHorizontal ${this.isHorizontal}, position ${position}, uri ${key}, select ${value}`) 578 let isMultiPick = this.selectParams.isMultiPick; 579 if (value && isMultiPick && this.selectedCount >= this.selectParams.maxSelectCount) { 580 if (!this.isHorizontal) { 581 UiUtil.showToast($r('app.string.up_to_limit_tips')); 582 } 583 return; 584 } 585 if (this.isShowSmartRecommendTabBar && this.isAllMediaAlbum && value) { 586 if (this.smartRecommendTabItems[this.currentSmartRecommendTabIndex].getUserPickUriList().indexOf(key) === -1) { 587 this.smartRecommendTabItems[this.currentSmartRecommendTabIndex].getUserPickUriList().push(key); 588 } 589 } 590 if (!isMultiPick) { 591 // update correct status from select manager 592 value = !this.selectManager?.isItemSelected(key); 593 this.selectManager?.deSelectAll(); 594 } 595 if (this.selectManager?.toggle(key, value, position)) { 596 Log.info(TAG, 'enter event process'); 597 this.dataSource.onDataChanged(this.dataSource.getDataIndexByUri(key)); 598 callback && callback(value); 599 } 600 } 601 602 private jumpBrowserCallback(name: string, item: MediaItem, geometryTapIndex: number , 603 geometryTransitionString: string, isSelectMode = false) { 604 let selectItemIndex: number = this.selectManager?.getSelectItemIndex(item) ?? Constants.INVALID; 605 let targetIndex = isSelectMode ? selectItemIndex : this.dataSource.getDataIndex(item); 606 Log.info(TAG, `jump to photo browser at index: ${targetIndex}, transition: ${name}`); 607 AppStorage.setOrCreate(Constants.APP_KEY_PHOTO_BROWSER, this.dataSource); 608 if (geometryTapIndex != -1 && geometryTransitionString != '') { 609 this.jumpToBrowserGeometryTransition( 610 targetIndex, name, item, isSelectMode, geometryTapIndex, geometryTransitionString); 611 } else { 612 this.jumpToBrowserNormal(targetIndex, name, item, isSelectMode); 613 } 614 ReportToBigDataUtil.report(BigDataConstants.SELECT_PICKER_CLICK_PREVIEW, undefined); 615 } 616 617 private onReloadFinishedCallback(): void { 618 Log.info(TAG, 'ON_DATA_RELOADED'); 619 this.dataSource.onDataReloaded(); 620 this.selectFromCameraFunc && this.selectFromCameraFunc(); 621 this.selectFromCameraFunc = () => {}; 622 } 623 624 private pickerInitDataFirstQueryFinish(): void { 625 if (this.isShowSmartRecommendTabBar) { 626 this.selectParams.cameraAble = 627 this.smartRecommendTabItems[this.isAllMediaAlbum ? this.currentSmartRecommendTabIndex : 0].isCameraAble(); 628 } 629 } 630 631 private onLoadingFinished(size: number): void { 632 this.onLoadFinishedCallback(size, (param: SelectParams): void => this.updateTitle(param)); 633 } 634 635 private onLoadFinishedCallback(size: number, updateTitle: Function) { 636 Log.info(TAG, `ON_LOADING_FINISHED size: ${size}`); 637 this.isEmpty = size == 0; 638 if (this.isEmpty && updateTitle) { 639 updateTitle(); 640 } 641 Log.info(TAG, `isEmpty: ${this.isEmpty}`) 642 this.dataSource.onDataReloaded(); 643 this.modifyPhotoSelectStatus(); 644 } 645 646 /** 647 * 图库预选择 648 */ 649 private modifyPhotoSelectStatus(): void { 650 if (this.selectParams.preselectedUris.length > 0) { 651 if (this.selectParams.preselectedUris.length > this.selectParams.maxSelectCount) { 652 this.selectParams.preselectedUris = 653 this.selectParams.preselectedUris.slice(0, this.selectParams.maxSelectCount); 654 } 655 this.selectManager?.initPreSelectPhotos(this.selectParams.preselectedUris); 656 this.selectParams.preselectedUris = []; 657 } 658 } 659 660 private initSelectManager() { 661 let manager: ThirdSelectManager = 662 AppStorage.get<ThirdSelectManager>(Constants.THIRD_SELECT_MANAGER) as ThirdSelectManager; 663 if (manager && manager.getClassName() === 'ThirdSelectManager') { 664 Log.debug(TAG, `use cached select manager, current select count ${manager.getSelectedCount()}`); 665 this.selectManager = manager; 666 } else { 667 Log.debug(TAG, 'create new select manager'); 668 this.selectManager = new ThirdSelectManager(); 669 AppStorage.setOrCreate(Constants.THIRD_SELECT_MANAGER, this.selectManager); 670 } 671 if (this.isFirstEnter) { 672 Log.debug(TAG, 'clear select manager'); 673 this.selectManager.deSelectAll(); 674 AppStorage.setOrCreate(THIRD_SELECT_IS_ORIGIN, false); 675 } 676 this.selectManager.setGetMediaItemFunc((uri: string): MediaItem => { 677 return this.dataSource.getMediaItemByUri(uri); 678 }); 679 } 680 681 private onActive() { 682 if (this.isItemIdChange) { 683 this.isActive = false; 684 this.dataSource && this.dataSource.initData(); 685 } 686 687 if (!this.isActive) { 688 Log.info(TAG, 'onActive'); 689 this.isActive = true; 690 this.dataSource && this.dataSource.onActive(); 691 if (this.selectParams.isMultiPick) { 692 this.dataSource.forceUpdate(); 693 } 694 } 695 } 696 697 private onInActive() { 698 if (this.isActive) { 699 Log.info(TAG, 'onInActive'); 700 this.isActive = false; 701 this.dataSource && this.dataSource.onInActive(); 702 } 703 } 704 705 private setPickResult(uriArray?: Array<string>): void { 706 let isOrigin: boolean = AppStorage.get<boolean>(THIRD_SELECT_IS_ORIGIN) as boolean; 707 if (isOrigin == undefined) { 708 isOrigin = false; 709 } 710 let abilityResult: ability.AbilityResult = { 711 resultCode: (uriArray === null || uriArray === undefined) ? -1 : 0, 712 want: { 713 parameters: { 714 'select-item-list': uriArray as Object, 715 isOriginal: isOrigin 716 } 717 } 718 }; 719 let self = this; 720 let uriLength = 0; 721 if (uriArray == null && uriArray == undefined) { 722 if (localStorage?.has(Constants.PHOTO_PICKER_SESSION_KEY)) { 723 let session = localStorage?.get<UIExtensionContentSession>(Constants.PHOTO_PICKER_SESSION_KEY); 724 session?.terminateSelfWithResult(abilityResult as ability.AbilityResult).then((result: void) => { 725 Log.debug(TAG, `session terminateSelfWithResult result: ${result}, self result ${JSON.stringify(abilityResult)}`); 726 }); 727 } else { 728 let context: common.UIAbilityContext = AppStorage.get<common.UIAbilityContext>('photosAbilityContext') as common.UIAbilityContext; 729 context.terminateSelfWithResult(abilityResult as ability.AbilityResult).then((result: void) => { 730 Log.debug(TAG, `terminateSelfWithResult result: ${result}, self result ${JSON.stringify(abilityResult)}`); 731 }); 732 } 733 } else { 734 uriLength = uriArray.length; 735 if (localStorage?.has(Constants.PHOTO_PICKER_SESSION_KEY)) { 736 let session = localStorage?.get<UIExtensionContentSession>(Constants.PHOTO_PICKER_SESSION_KEY); 737 let param = localStorage?.get<SelectParams>(Constants.PHOTO_PICKER_PARAMS_KEY); 738 if (param?.bundleName) { 739 SelectUtil.grantPermissionForUris(uriArray, param.bundleName).then(() => { 740 Log.info(TAG, `session grant permission success.`); 741 let context: common.UIAbilityContext = AppStorage.get<common.UIAbilityContext>('photosAbilityContext') as common.UIAbilityContext; 742 session?.terminateSelfWithResult(abilityResult as ability.AbilityResult).then((result: void) => { 743 Log.debug(TAG, `session terminateSelfWithResult result: ${result}, self result ${JSON.stringify(abilityResult)}`); 744 }); 745 }).catch((err: Error) => { 746 Log.error(TAG, `session grant permission error: ${JSON.stringify(err)}, self result ${JSON.stringify(abilityResult)}`); 747 session?.terminateSelfWithResult(abilityResult as ability.AbilityResult).then((result: void) => { 748 Log.debug(TAG, `session terminateSelfWithResult result: ${result}, self result ${JSON.stringify(abilityResult)}`); 749 }); 750 }); 751 } 752 } else { 753 SelectUtil.grantPermissionForUris(uriArray, self.selectParams.bundleName).then(() => { 754 Log.info(TAG, `grant permission success.`); 755 let context: common.UIAbilityContext = AppStorage.get<common.UIAbilityContext>('photosAbilityContext') as common.UIAbilityContext; 756 context.terminateSelfWithResult(abilityResult as ability.AbilityResult).then((result: void) => { 757 Log.debug(TAG, `terminateSelfWithResult result: ${result}, self result ${JSON.stringify(abilityResult)}`); 758 }); 759 }).catch((err: Error) => { 760 Log.error(TAG, `grant permission error: ${JSON.stringify(err)}, self result ${JSON.stringify(abilityResult)}`); 761 }); 762 } 763 } 764 interface Msg { 765 isOriginalChecked: boolean; 766 selectItemSize: number; 767 } 768 let msg: Msg = { 769 isOriginalChecked: isOrigin, 770 selectItemSize: uriLength, 771 } 772 ReportToBigDataUtil.report(BigDataConstants.SELECT_PICKER_RESULT, msg); 773 } 774 775 private goBackFormEditor(): void { 776 let formEditorOption: router.RouterOptions = { 777 url: 'pages/FormEditorPage' 778 }; 779 router.replaceUrl(formEditorOption); 780 } 781} 782 783@Extend(Grid) 784function gridStyle(gridCount: number) { 785 .columnsTemplate('1fr '.repeat(gridCount)) 786 .columnsGap(Constants.GRID_GUTTER) 787 .rowsGap(Constants.GRID_GUTTER) 788 .cachedCount(Constants.GRID_CACHE_ROW_COUNT) 789 .layoutWeight(1) 790} 791