1/** 2 * Copyright (c) 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 prompt from '@system.prompt'; 18import Curves from '@ohos.curves'; 19import { MenuOperation } from '@ohos/common'; 20import { 21 Action, 22 AddMenuOperation, 23 AlbumDefine, 24 AlbumInfo, 25 BatchDeleteMenuOperation, 26 BatchRemoveMenuOperation, 27 BroadCast, 28 BroadCastConstants, 29 BroadCastManager, 30 BrowserConstants, 31 CommonObserverCallback, 32 Constants, 33 DeleteMenuOperation, 34 ImageUtil, 35 JumpSourceToMain, 36 Log, 37 MediaDataSource, 38 MediaItem, 39 MediaObserver, 40 MediaOperationType, 41 MenuContext, 42 MenuOperationFactory, 43 MoveMenuOperation, 44 RemoveMenuOperation, 45 ScreenManager, 46 SelectManager, 47 ShareMenuOperation, 48 TraceControllerUtils, 49 UiUtil, 50 UserFileManagerAccess, 51 ViewData 52} from '@ohos/common'; 53import { 54 BrowserController, 55 CustomDialogView, 56 GridScrollBar, 57 ImageGridItemComponent, 58 NoPhotoComponent 59} from '@ohos/common/CommonComponents'; 60import { RecoverMenuOperation } from '@ohos/browser'; 61import { 62 BatchRecoverMenuOperation, 63 ClearRecycleMenuOperation, 64 PhotoGridPageActionBar, 65 PhotoGridPageToolBar 66} from '@ohos/browser/BrowserComponents'; 67 68 69const TAG: string = 'PhotoGridView'; 70AppStorage.setOrCreate('photoGridPageIndex', Constants.INVALID); 71 72// Album View 73@Component 74export struct PhotoGridView { 75 @State isShowScrollBar: boolean = false; 76 @Provide isEmpty: boolean = false; 77 @State gridRowCount: number = 0; 78 @Consume @Watch('updateRightClickMenuList') isSelectedMode: boolean; 79 @Provide isAllSelected: boolean = false; 80 @State totalSelectedCount: number = 0; 81 @StorageLink('isHorizontal') isHorizontal: boolean = ScreenManager.getInstance().isHorizontal(); 82 @Provide broadCast: BroadCast = new BroadCast(); 83 @Consume isShow: boolean; 84 @Provide isShowBar: boolean = true; 85 @Provide moreMenuList: Action[] = []; 86 @Provide rightClickMenuList: Action[] = []; 87 @StorageLink('photoGridPageIndex') @Watch('onIndexChange') photoGridPageIndex: number = Constants.INVALID; 88 @StorageLink('isSplitMode') isSplitMode: boolean = ScreenManager.getInstance().isSplitMode(); 89 @StorageLink('leftBlank') leftBlank: number[] = 90 [0, ScreenManager.getInstance().getStatusBarHeight(), 0, ScreenManager.getInstance().getNaviBarHeight()]; 91 @Prop @Watch('onPageChanged') pageStatus: boolean = false; 92 @State gridItemWidth: number = 0; 93 @StorageLink('photoGridActionBarOpacity') photoGridActionBarOpacity: number = 0; 94 @StorageLink('photoGridViewOpacity') photoGridViewOpacity: number = 0; 95 albumInfo: AlbumInfo = new AlbumInfo(); 96 title: string = ''; 97 deviceName: string = ''; 98 dataSource: MediaDataSource = new MediaDataSource(Constants.DEFAULT_SLIDING_WIN_SIZE); 99 scroller: Scroller = new Scroller(); 100 isDataFreeze = false; 101 mSelectManager = new SelectManager(); 102 isActive = false; 103 isDistributedAlbum = false; 104 deleteMode: boolean = false; 105 routerStart = false; 106 isFromFACard = false; 107 @StorageLink('placeholderIndex') @Watch('onPlaceholderChanged') placeholderIndex: number = -1; 108 @Provide hidePopup: boolean = false; 109 @ObjectLink browserController: BrowserController; 110 private dataObserver: CommonObserverCallback = new CommonObserverCallback(this); 111 private appBroadCast: BroadCast = BroadCastManager.getInstance().getBroadCast(); 112 // 选择模式下,鼠标对着未勾选项按右键弹框时,移动和复制菜单点击事件的标识位 113 private isMvOrCpSeparatesItem: boolean = false; 114 private mvOrCpSeparatesItem: MediaItem = new MediaItem(); 115 private photoTotalCount: number = 0; 116 private params: Params | null = null; 117 private scrollIndex: number = 0; 118 private onWindowSizeChangeCallBack: Function = () => { 119 // 后续phone缩略图支持横竖屏后再放开 120 } 121 private selectFunc: Function = (position: number, key: string, value: boolean, callback: Function): void => 122 this.select(position, key, value, callback); 123 private jumpPhotoBrowserFunc: Function = (name: string, item: MediaItem, 124 geometryTapIndex: number, geometryTransitionString: string): void => 125 this.jumpPhotoBrowser(name, item, geometryTapIndex, geometryTransitionString); 126 private jumpThirdPhotoBrowserFunc: Function = (name: string, item: MediaItem, 127 geometryTapIndex: number, geometryTransitionString: string): void => 128 this.jumpThirdPhotoBrowser(name, item, geometryTapIndex, geometryTransitionString); 129 private onLoadingFinishedFunc: Function = (size: number): void => this.onLoadingFinished(size); 130 private onDataReloadedFunc: Function = (): void => this.onDataReloaded(); 131 private onUpdateFavorStateFunc: Function = (item: MediaItem): void => this.onUpdateFavorState(item); 132 private onDoAnimationFunc: Function = (): void => this.onDoAnimation(); 133 134 onPlaceholderChanged() { 135 Log.debug(TAG, 'onPlaceholderChanged placeholderIndex is ' + this.placeholderIndex); 136 if (this.placeholderIndex != -1) { 137 this.scroller.scrollToIndex(this.placeholderIndex); 138 } 139 } 140 141 initParams(): void { 142 this.isSelectedMode = false; 143 this.isShow = true; 144 } 145 146 onIndexChange(): void { 147 Log.info(TAG, `onIndexChange ${this.photoGridPageIndex}`) 148 if (this.photoGridPageIndex != Constants.INVALID) { 149 this.scroller.scrollToIndex(this.photoGridPageIndex); 150 } 151 } 152 153 doAnimation(): void { 154 animateTo({ 155 duration: BrowserConstants.PHONE_LINK_ALBUM_ACTIONBAR_DURATION, 156 delay: BrowserConstants.PHONE_LINK_ALBUM_ACTIONBAR_DELAY, 157 curve: Curve.Sharp 158 }, () => { 159 AppStorage.setOrCreate<number>(Constants.KEY_OF_ALBUM_ACTIONBAR_OPACITY, 1); 160 }) 161 animateTo({ 162 duration: BrowserConstants.PHONE_LINK_OUT_PHOTO_GRID_ACTIONBAR_DURATION, 163 curve: Curve.Sharp 164 }, () => { 165 AppStorage.setOrCreate<number>(Constants.KEY_OF_PHOTO_GRID_ACTIONBAR_OPACITY, 0); 166 AppStorage.setOrCreate<number>(Constants.KEY_OF_PHOTO_GRID_VIEW_OPACITY, 0); 167 AppStorage.setOrCreate<number>(Constants.KEY_OF_ALBUM_OPACITY, 1); 168 }) 169 animateTo({ 170 duration: BrowserConstants.PHONE_LINK_PHOTO_GRID_TO_ALBUM_DURATION, 171 curve: Curve.Friction 172 }, () => { 173 AppStorage.setOrCreate<number>(Constants.KEY_OF_SELECTED_ALBUM_INDEX, -1); 174 AppStorage.setOrCreate<boolean>(Constants.KEY_OF_IS_SHOW_PHOTO_GRID_VIEW, false); 175 AppStorage.setOrCreate<string>(Constants.KEY_OF_SELECTED_ALBUM_URI, ''); 176 }) 177 animateTo({ 178 duration: BrowserConstants.PHONE_LINK_PHOTO_GRID_TO_ALBUM_SCALE_DURATION, 179 curve: Curve.Friction 180 }, () => { 181 AppStorage.setOrCreate<number>(Constants.KEY_OF_ALBUM_OTHER_SCALE, 1); 182 }) 183 } 184 185 onMenuClicked(action: Action): void { 186 Log.info(TAG, `onMenuClicked, action: ${action.actionID}`); 187 let menuContext: MenuContext; 188 let menuOperation: MenuOperation; 189 if (action.actionID === Action.BACK.actionID) { 190 if (this.isFromFACard) { 191 router.replaceUrl({ 192 url: 'pages/index', 193 params: { 194 jumpSource: JumpSourceToMain.ALBUM, 195 } 196 }); 197 } else { 198 if (router.getState().name === Constants.USER_FILE_MANAGER_PHOTO_TRANSITION_ALBUM) { 199 router.back(); 200 } else { 201 this.doAnimation(); 202 } 203 } 204 } else if (action.actionID === Action.CANCEL.actionID) { 205 this.onModeChange(); 206 } else if (action.actionID === Action.MULTISELECT.actionID) { 207 this.isSelectedMode = true; 208 } else if (action.actionID === Action.SELECT_ALL.actionID) { 209 this.mSelectManager.selectAll(true); 210 } else if (action.actionID === Action.DESELECT_ALL.actionID) { 211 this.mSelectManager.deSelectAll(); 212 } else if (action.actionID === Action.DELETE.actionID) { 213 menuContext = new MenuContext(); 214 menuContext 215 .withSelectManager(this.mSelectManager) 216 .withOperationStartCallback((): void => this.onDeleteStart()) 217 .withOperationEndCallback((): void => this.onDeleteEnd()) 218 .withBroadCast(this.broadCast) 219 .withAlbumUri(this.albumInfo.uri) 220 .withFromSelectMode(this.isSelectedMode) 221 .withAlbumInfo(this.albumInfo) 222 menuOperation = MenuOperationFactory.getInstance() 223 .createMenuOperation(BatchDeleteMenuOperation, menuContext); 224 menuOperation.doAction(); 225 } else if (action.actionID === Action.SHARE.actionID) { 226 menuContext = new MenuContext(); 227 menuContext.withFromSelectMode(true).withSelectManager(this.mSelectManager); 228 menuOperation = MenuOperationFactory.getInstance() 229 .createMenuOperation(ShareMenuOperation, menuContext); 230 menuOperation.doAction(); 231 } else if (action.actionID === Action.INFO.actionID) { 232 this.hidePopup = true; 233 this.openDetailsDialog(); 234 } else if (action.actionID === Action.CLEAR_RECYCLE.actionID) { 235 menuContext = new MenuContext(); 236 menuContext 237 .withSelectManager(this.mSelectManager) 238 .withOperationStartCallback((): void => this.onDeleteStart()) 239 .withOperationEndCallback((): void => this.onDeleteEnd()) 240 .withBroadCast(this.broadCast) 241 .withAlbumUri(UserFileManagerAccess.getInstance() 242 .getSystemAlbumUri(UserFileManagerAccess.TRASH_ALBUM_SUB_TYPE)) 243 .withAlbumInfo(this.albumInfo) 244 menuOperation = MenuOperationFactory.getInstance() 245 .createMenuOperation(ClearRecycleMenuOperation, menuContext); 246 menuOperation.doAction(); 247 } else if (action.actionID === Action.RECOVER.actionID) { 248 menuContext = new MenuContext(); 249 menuContext 250 .withAlbumUri(UserFileManagerAccess.getInstance() 251 .getSystemAlbumUri(UserFileManagerAccess.TRASH_ALBUM_SUB_TYPE)) 252 .withSelectManager(this.mSelectManager) 253 .withOperationStartCallback((): void => this.onDeleteStart()) 254 .withOperationEndCallback((): void => this.onDeleteEnd()) 255 .withBroadCast(this.broadCast) 256 .withAlbumInfo(this.albumInfo) 257 menuOperation = MenuOperationFactory.getInstance() 258 .createMenuOperation(BatchRecoverMenuOperation, menuContext); 259 menuOperation.doAction(); 260 } else if (action.actionID === Action.MOVE.actionID) { 261 this.mSelectManager.getSelectedItems((selectedItems: Array<MediaItem>) => { 262 Log.info(TAG, `Get selected items success, size: ${selectedItems.length}, start route to select album page`); 263 this.routeToSelectAlbumPage(MediaOperationType.Move, selectedItems); 264 }) 265 } else if (action.actionID === Action.ADD.actionID) { 266 this.mSelectManager.getSelectedItems((selectedItems: Array<MediaItem>) => { 267 Log.info(TAG, `Get selected items success, size: ${selectedItems.length}, start route to select album page`); 268 this.routeToSelectAlbumPage(MediaOperationType.Add, selectedItems); 269 }) 270 } else if (action.actionID === Action.REMOVE_FROM.actionID) { 271 menuContext = new MenuContext(); 272 menuContext 273 .withSelectManager(this.mSelectManager) 274 .withOperationStartCallback((): void => this.onRemoveStart()) 275 .withOperationEndCallback((): void => this.onRemoveEnd()) 276 .withBroadCast(this.broadCast) 277 .withAlbumUri(this.albumInfo.uri) 278 .withFromSelectMode(this.isSelectedMode) 279 menuOperation = MenuOperationFactory.getInstance() 280 .createMenuOperation(BatchRemoveMenuOperation, menuContext); 281 menuOperation.doAction(); 282 } else if (action.actionID === Action.NEW.actionID) { 283 this.routeToAddMediaPage(); 284 } else if (action.actionID === Action.DOWNLOAD.actionID) { 285 menuContext = new MenuContext(); 286 menuContext 287 .withSelectManager(this.mSelectManager) 288 .withOperationStartCallback((): void => this.onDownloadStart()) 289 .withOperationEndCallback(async (err: Error, count: number, total: number): Promise<void> => 290 this.onDownloadEnd(err as Object, count, total)) 291 .withBroadCast(this.broadCast) 292 menuOperation = MenuOperationFactory.getInstance().createMenuOperation(AddMenuOperation, menuContext); 293 menuOperation.doAction(); 294 } 295 } 296 297 async openDetailsDialog(): Promise<void> { 298 if (this.totalSelectedCount == 0) { 299 Log.error(TAG, 'no select error'); 300 return; 301 } else if (this.totalSelectedCount == 1) { 302 Log.info(TAG, 'totalSelectedCount is 1'); 303 await this.mSelectManager.getSelectedItems((selectItems: MediaItem[]) => { 304 if (selectItems.length != 1) { 305 Log.error(TAG, 'get selectItems is error'); 306 return; 307 } 308 this.broadCast.emit(BroadCastConstants.SHOW_DETAIL_DIALOG, [selectItems[0], this.isDistributedAlbum]); 309 }); 310 } else { 311 await this.mSelectManager.getSelectedItems((selectItems: MediaItem[]) => { 312 if (selectItems.length <= 1) { 313 Log.error(TAG, 'get selectItems is error'); 314 return; 315 } 316 let size = 0; 317 selectItems.forEach((item) => { 318 size = size + item.size; 319 }) 320 321 Log.info(TAG, `openDetailsDialog size: ${size}`); 322 this.broadCast.emit(BroadCastConstants.SHOW_MULTI_SELECT_DIALOG, [this.totalSelectedCount, size]); 323 }); 324 return; 325 } 326 } 327 328 routeToSelectAlbumPage(pageType: string, selectedItems: Array<MediaItem>): void { 329 this.routerStart = true; 330 router.pushUrl({ 331 url: 'pages/MediaOperationPage', 332 params: { 333 pageFrom: Constants.MEDIA_OPERATION_FROM_PHOTO_GRID, 334 pageType: pageType, 335 albumInfo: this.albumInfo, 336 selectedItems: selectedItems 337 } 338 }); 339 } 340 341 routeToAddMediaPage(): void { 342 router.pushUrl({ 343 url: 'pages/AlbumSelect', 344 params: { 345 albumName: this.albumInfo.albumName, 346 albumUri: this.albumInfo.uri 347 } 348 }); 349 } 350 351 onCopyStart(): void { 352 Log.info(TAG, `onCopyStart`); 353 this.isDataFreeze = true; 354 MediaObserver.getInstance().unregisterObserver(this.dataObserver); 355 this.dataSource.freeze(); 356 } 357 358 onCopyEnd(err: Object, count: number, total: number): void { 359 Log.info(TAG, `onCopyEnd count: ${count}, total: ${total}`); 360 this.isDataFreeze = false; 361 this.onModeChange(); 362 MediaObserver.getInstance().registerObserver(this.dataObserver); 363 this.dataSource.onChange('image'); 364 this.dataSource.unfreeze(); 365 if (err) { 366 UiUtil.showToast($r('app.string.copy_failed_single')); 367 } 368 } 369 370 onDownloadStart(): void { 371 Log.info(TAG, `onDownloadStart`); 372 this.isDataFreeze = true; 373 MediaObserver.getInstance().unregisterObserver(this.dataObserver); 374 this.dataSource.freeze(); 375 } 376 377 async onDownloadEnd(err: Object, count: number, total: number): Promise<void> { 378 Log.info(TAG, `onDownloadEnd count: ${count}, total: ${total}`); 379 this.isDataFreeze = false; 380 this.onModeChange(); 381 MediaObserver.getInstance().registerObserver(this.dataObserver); 382 this.dataSource.onChange('image'); 383 this.dataSource.unfreeze(); 384 if (err) { 385 if (total > 1) { 386 Log.error(TAG, `get selectItems is error ${count}`); 387 let str = await UiUtil.getResourceString($r('app.string.download_failed_multi')); 388 let message = str.replace('%d', count.toString()); 389 prompt.showToast({ 390 message: message, 391 duration: UiUtil.TOAST_DURATION, 392 bottom: '200vp' 393 }); 394 } else { 395 UiUtil.showToast($r('app.string.download_failed_single')) 396 } 397 } else { 398 UiUtil.showToast($r('app.string.download_progress_done')); 399 } 400 } 401 402 onMoveStart(): void { 403 Log.info(TAG, `onMoveStart`); 404 this.isDataFreeze = true; 405 MediaObserver.getInstance().unregisterObserver(this.dataObserver); 406 this.dataSource.freeze(); 407 } 408 409 onMoveEnd(err: Object, count: number, total: number): void { 410 Log.info(TAG, `onMoveEnd count: ${count}, total: ${total}`); 411 this.isDataFreeze = false; 412 this.onModeChange(); 413 MediaObserver.getInstance().registerObserver(this.dataObserver); 414 this.dataSource.switchRefreshOn(); 415 this.dataSource.onChange('image'); 416 this.dataSource.unfreeze(); 417 if (err) { 418 UiUtil.showToast($r('app.string.move_failed_single')); 419 } 420 } 421 422 onDeleteStart(): void { 423 Log.info(TAG, `onDeleteStart`); 424 this.deleteMode = true; 425 this.isDataFreeze = true; 426 this.onModeChange(); 427 MediaObserver.getInstance().unregisterObserver(this.dataObserver); 428 this.dataSource.freeze(); 429 MediaObserver.getInstance().freezeNotify(); 430 } 431 432 onDeleteEnd(): void { 433 Log.info(TAG, `onDeleteEnd`); 434 this.isDataFreeze = false; 435 MediaObserver.getInstance().unfreezeNotify(); 436 MediaObserver.getInstance().forceNotify(); 437 MediaObserver.getInstance().registerObserver(this.dataObserver); 438 this.dataSource.onChange('image'); 439 this.dataSource.unfreeze(); 440 } 441 442 onRemoveStart(): void { 443 Log.info(TAG, `onRemoveStart`); 444 this.deleteMode = true; 445 this.isDataFreeze = true; 446 MediaObserver.getInstance().unregisterObserver(this.dataObserver); 447 this.dataSource.freeze(); 448 } 449 450 onRemoveEnd(): void { 451 Log.info(TAG, `onRemoveEnd`); 452 this.isDataFreeze = false; 453 this.onModeChange(); 454 MediaObserver.getInstance().registerObserver(this.dataObserver); 455 this.dataSource.onChange('image'); 456 this.dataSource.unfreeze(); 457 } 458 459 onModeChange(): void { 460 Log.info(TAG, 'onModeChange'); 461 this.isSelectedMode = false; 462 this.isAllSelected = false; 463 this.mSelectManager.onModeChange(false); 464 AppStorage.delete(Constants.PHOTO_GRID_SELECT_MANAGER); 465 } 466 467 onPageChanged(): void { 468 this.params = router.getParams() as Params; 469 if (this.pageStatus) { 470 this.onPageShow(); 471 } else { 472 this.onPageHide(); 473 } 474 } 475 476 onPageShow(): void { 477 this.appBroadCast.emit(BroadCastConstants.THIRD_ROUTE_PAGE, []); 478 this.isShow = true; 479 if (this.routerStart && this.params != null && this.params.pageType != null) { 480 Log.info(TAG, 'MediaOperation back'); 481 if (this.params.pageType === MediaOperationType.Move) { 482 this.moveOperation(this.params.albumName, this.params.albumUri); 483 } else if (this.params.pageType === MediaOperationType.Add) { 484 this.addOperation(this.params.albumName, this.params.albumUri); 485 } 486 } 487 MediaObserver.getInstance().registerObserver(this.dataObserver); 488 this.isMvOrCpSeparatesItem = false; 489 this.mvOrCpSeparatesItem = new MediaItem(); 490 this.routerStart = false; 491 this.onActive(); 492 } 493 494 onPageHide(): void { 495 this.isShow = false; 496 this.onInActive(); 497 } 498 499 onActive(): void { 500 if (!this.isActive) { 501 Log.info(TAG, 'onActive'); 502 this.isActive = true; 503 this.dataSource && this.dataSource.onActive(); 504 if (this.isSelectedMode) { 505 this.totalSelectedCount = this.mSelectManager.getSelectedCount(); 506 this.dataSource.forceUpdate(); 507 } 508 } 509 } 510 511 onInActive(): void { 512 if (this.isActive) { 513 Log.info(TAG, 'onInActive'); 514 this.isActive = false; 515 } 516 } 517 518 updateRightClickMenuList(): void { 519 if (!this.isSelectedMode) { 520 this.onModeChange(); 521 } 522 this.rightClickMenuList = []; 523 if (this.albumInfo) { 524 let isRecycleAlbum: boolean = this.albumInfo.isTrashAlbum; 525 if (isRecycleAlbum) { 526 this.rightClickMenuList = [Action.RECOVER, Action.DELETE, 527 this.isSelectedMode ? Action.MULTISELECT_INVALID : Action.MULTISELECT]; 528 } else { 529 if (!this.isSelectedMode) { 530 this.rightClickMenuList.push(Action.MULTISELECT) 531 } 532 this.rightClickMenuList.push(Action.DELETE); 533 if (!this.albumInfo.isSystemAlbum) { 534 this.rightClickMenuList.push(Action.MOVE); 535 this.rightClickMenuList.push(Action.REMOVE_FROM); 536 } 537 this.rightClickMenuList.push(Action.ADD, Action.INFO); 538 } 539 } 540 } 541 542 aboutToAppear(): void { 543 Log.debug(TAG, `aboutToAppear`); 544 TraceControllerUtils.startTrace('PhotoGridPageAboutToAppear'); 545 this.initParams(); 546 if (router.getState().name === Constants.USER_FILE_MANAGER_PHOTO_TRANSITION_ALBUM) { 547 this.photoGridActionBarOpacity = 1; 548 this.photoGridViewOpacity = 1; 549 } 550 let param: ParamAlbumInfo; 551 param = router.getParams() as ParamAlbumInfo; 552 if (!param || (param && !param.item)) { 553 param = AppStorage.get<ParamAlbumInfo>(Constants.KEY_OF_PHOTO_GRID_VIEW_ALBUM_ITEM) as ParamAlbumInfo; 554 } 555 if (param != null) { 556 if (param.isFromFACard) { 557 this.isFromFACard = param.isFromFACard; 558 } 559 this.albumInfo = JSON.parse(param.item); 560 this.title = this.albumInfo.albumName; 561 this.dataSource.setAlbumUri(this.albumInfo.uri); 562 if (this.albumInfo.mediaItem) { 563 let mediaItem = this.albumInfo.mediaItem; 564 this.dataSource.items = [mediaItem]; 565 this.dataSource.size = 1; 566 this.dataSource.dataIndexes = [0]; 567 this.photoTotalCount = this.albumInfo.count; 568 } 569 } 570 571 let self = this; 572 this.dataSource.setBroadCast(this.broadCast) 573 this.mSelectManager.setPhotoDataImpl(); 574 this.mSelectManager.setAlbumUri(this.albumInfo.uri); 575 this.mSelectManager.setGetMediaItemFunc( 576 (uri: string, itemNotifyCallback: Function): MediaItem | undefined => { 577 return this.dataSource?.getMediaItemByUriFromAll(uri, itemNotifyCallback); 578 }); 579 MediaObserver.getInstance().registerObserver(this.dataObserver); 580 581 this.broadCast.on(BroadCastConstants.SELECT, this.selectFunc); 582 this.broadCast.on(BroadCastConstants.JUMP_PHOTO_BROWSER, this.jumpPhotoBrowserFunc); 583 this.broadCast.on(BroadCastConstants.JUMP_THIRD_PHOTO_BROWSER, this.jumpThirdPhotoBrowserFunc); 584 this.broadCast.on(Constants.ON_LOADING_FINISHED, this.onLoadingFinishedFunc); 585 this.appBroadCast.on(BroadCastConstants.UPDATE_DATA_SOURCE, this.onUpdateFavorStateFunc); 586 this.appBroadCast.on(BroadCastConstants.DO_ANIMATION, this.onDoAnimationFunc); 587 588 AppStorage.setOrCreate(Constants.PHOTO_GRID_SELECT_MANAGER, this.mSelectManager); 589 this.mSelectManager.registerCallback('allSelect', (newState: boolean) => { 590 Log.info(TAG, `allSelect ${newState}`); 591 if (this.isDataFreeze) { 592 return; 593 } 594 this.isAllSelected = newState; 595 this.dataSource.forceUpdate(); 596 }); 597 this.mSelectManager.registerCallback('updateCount', (newState: number) => { 598 Log.info(TAG, `updateSelectedCount ${newState}`); 599 if (this.isDataFreeze) { 600 return; 601 } 602 this.moreMenuList = Boolean(newState) ? (this.albumInfo.isSystemAlbum ? 603 [Action.ADD, Action.INFO] : [Action.MOVE, Action.ADD, Action.REMOVE_FROM, Action.INFO]) 604 : (this.albumInfo.isSystemAlbum ? [Action.ADD_INVALID, Action.INFO_INVALID] : 605 [Action.MOVE_INVALID, Action.ADD_INVALID, Action.REMOVE_FROM_INVALID, Action.INFO_INVALID]); 606 this.totalSelectedCount = newState; 607 }); 608 this.mSelectManager.registerCallback('select', (newState: number) => { 609 Log.info(TAG, `select ${newState}`); 610 if (this.isDataFreeze) { 611 return; 612 } 613 this.dataSource.onDataChanged(newState); 614 }); 615 this.dataSource.registerCallback('updateCount', (newState: number) => { 616 Log.info(TAG, `updateTotalCount ${newState}`); 617 self.isShowScrollBar = (newState > Constants.PHOTOS_CNT_FOR_HIDE_SCROLL_BAR); 618 self.isEmpty = !Boolean(newState) 619 self.mSelectManager.setTotalCount(newState); 620 }); 621 622 this.broadCast.on(BroadCastConstants.ON_DATA_RELOADED, this.onDataReloadedFunc); 623 624 ScreenManager.getInstance().on(ScreenManager.ON_WIN_SIZE_CHANGED, this.onWindowSizeChangeCallBack); 625 626 this.initGridRowCount(); 627 this.moreMenuList = this.albumInfo.isSystemAlbum ? 628 [Action.ADD, Action.INFO] : [Action.MOVE, Action.ADD, Action.REMOVE_FROM, Action.INFO]; 629 this.updateRightClickMenuList(); 630 TraceControllerUtils.finishTrace('PhotoGridPageAboutToAppear'); 631 } 632 633 private onDoAnimation(): void { 634 this.doAnimation(); 635 this.appBroadCast.off(BroadCastConstants.DO_ANIMATION, undefined); 636 } 637 638 private select(position: number, key: string, value: boolean, callback: Function): void { 639 if (this.mSelectManager.toggle(key, value, position)) { 640 Log.info(TAG, 'enter event process') 641 if (!this.isSelectedMode) { 642 this.isSelectedMode = true; 643 } 644 callback(); 645 } 646 } 647 648 private jumpPhotoBrowser(name: string, item: MediaItem, 649 geometryTapIndex: number, geometryTransitionString: string): void { 650 let targetIndex = this.dataSource.getDataIndex(item); 651 if (targetIndex == Constants.NOT_FOUND) { 652 Log.error(TAG, 'targetIndex is not found'); 653 return; 654 } 655 Log.info(TAG, `jump to photo browser at index: ${targetIndex}`); 656 let pageEntryFrom = Constants.ENTRY_FROM.NORMAL; 657 if (this.albumInfo.isTrashAlbum) { 658 pageEntryFrom = Constants.ENTRY_FROM.RECYCLE; 659 } else if (this.isDistributedAlbum) { 660 pageEntryFrom = Constants.ENTRY_FROM.DISTRIBUTED; 661 } 662 663 AppStorage.setOrCreate(Constants.APP_KEY_PHOTO_BROWSER, this.dataSource); 664 if (geometryTapIndex !== undefined && geometryTransitionString !== undefined) { 665 this.jumpToPhotoBrowserGeometryTransition( 666 targetIndex, name, pageEntryFrom, geometryTapIndex, geometryTransitionString); 667 } else { 668 this.jumpToPhotoBrowserNormal(targetIndex, name, pageEntryFrom); 669 } 670 } 671 672 private jumpThirdPhotoBrowser(name: string, item: MediaItem, 673 geometryTapIndex: number, geometryTransitionString: string): void { 674 Log.info(TAG, 'JUMP_THIRD_PHOTO_BROWSER'); 675 let targetIndex = this.dataSource.getDataIndex(item); 676 if (targetIndex == Constants.NOT_FOUND) { 677 Log.error(TAG, 'targetIndex is not found'); 678 return; 679 } 680 Log.info(TAG, `jump to photo browser at index: ${targetIndex} ${name}`); 681 let pageEntryFrom = Constants.ENTRY_FROM.NORMAL; 682 if (this.albumInfo.isTrashAlbum) { 683 pageEntryFrom = Constants.ENTRY_FROM.RECYCLE; 684 } else if (this.isDistributedAlbum) { 685 pageEntryFrom = Constants.ENTRY_FROM.DISTRIBUTED; 686 } 687 AppStorage.setOrCreate(Constants.PHOTO_GRID_SELECT_MANAGER, this.mSelectManager); 688 AppStorage.setOrCreate(Constants.APP_KEY_PHOTO_BROWSER, this.dataSource); 689 if (geometryTapIndex !== undefined && geometryTransitionString !== undefined) { 690 this.jumpToSelectPhotoBrowserGeometryTransition( 691 targetIndex, name, pageEntryFrom, geometryTapIndex, geometryTransitionString); 692 } else { 693 this.jumpToSelectPhotoBrowserNormal(targetIndex, name, pageEntryFrom); 694 } 695 } 696 697 private onLoadingFinished(size: number): void { 698 Log.info(TAG, `ON_LOADING_FINISHED size: ${size}`); 699 } 700 701 private onDataReloaded(): void { 702 Log.info(TAG, 'ON_DATA_RELOADED'); 703 if (this.deleteMode) { 704 animateTo({ duration: 300 }, () => { 705 this.dataSource.onDataReloaded(); 706 }) 707 this.deleteMode = false; 708 } else { 709 this.dataSource.onDataReloaded(); 710 } 711 } 712 713 714 updateFirstPhotoItemInfo(item: MediaItem, isFirstPhotoItem: boolean): void { 715 if (item) { 716 AppStorage.setOrCreate<boolean>(Constants.KEY_OF_IS_FIRST_PHOTO_ITEM, isFirstPhotoItem); 717 let albumUri = AppStorage.Get<string>(Constants.KEY_OF_ALBUM_URI); 718 let transitionId = `${item.hashCode}_${albumUri}`; 719 Log.info(TAG, `updateFirstPhotoItemInfo transitionId: ${transitionId}`); 720 AppStorage.Set<string>(Constants.KEY_OF_GEOMETRY_TRANSITION_ID_HEIGHT, transitionId); 721 } 722 } 723 724 jumpToPhotoBrowserNormal(targetIndex: number, name: string, pageEntryFrom: number) { 725 Log.debug(TAG, 'start jump to photo browser in normal'); 726 router.pushUrl({ 727 url: 'pages/PhotoBrowser', 728 params: { 729 position: targetIndex, 730 transition: name, 731 leftBlank: this.leftBlank, 732 pageFrom: pageEntryFrom, 733 deviceName: this.deviceName, 734 albumInfo: this.albumInfo 735 } 736 }); 737 } 738 739 jumpToPhotoBrowserGeometryTransition(targetIndex: number, name: string, pageEntryFrom: number, 740 geometryTapIndex: number, geometryTransitionString: string) { 741 Log.debug(TAG, 'start jump to photo browser in geometry transition'); 742 743 interface Params { 744 position: number; 745 transition: string; 746 leftBlank: number[]; 747 pageFrom: number; 748 deviceName: string; 749 albumInfo: AlbumInfo; 750 } 751 752 let params: Params = { 753 position: targetIndex, 754 transition: name, 755 leftBlank: this.leftBlank, 756 pageFrom: pageEntryFrom, 757 deviceName: this.deviceName, 758 albumInfo: this.albumInfo 759 } 760 this.browserController.showBrowser(geometryTapIndex, geometryTransitionString, TAG, params); 761 } 762 763 jumpToSelectPhotoBrowserNormal(targetIndex: number, name: string, pageEntryFrom: number) { 764 Log.debug(TAG, 'start jump to select photo browser in normal'); 765 router.pushUrl({ 766 url: 'pages/SelectPhotoBrowser', 767 params: { 768 position: targetIndex, 769 transition: name, 770 pageFrom: pageEntryFrom, 771 } 772 }); 773 } 774 775 jumpToSelectPhotoBrowserGeometryTransition(targetIndex: number, name: string, pageEntryFrom: number, 776 geometryTapIndex: number, geometryTransitionString: string) { 777 Log.debug(TAG, 'start jump to select photo browser in geometry transition'); 778 interface Params { 779 position: number; 780 transition: string; 781 pageFrom: number; 782 } 783 784 const params: Params = { 785 position: targetIndex, 786 transition: name, 787 pageFrom: pageEntryFrom, 788 }; 789 this.browserController.showSelectBrowser(geometryTapIndex, geometryTransitionString, TAG, params); 790 } 791 792 onMediaLibDataChange(changeType: string): void { 793 Log.info(TAG, `onMediaLibDataChange type: ${changeType}`); 794 this.dataSource.switchRefreshOn(); 795 this.dataSource.onChange(changeType); 796 } 797 798 aboutToDisappear(): void { 799 Log.info(TAG, `aboutToDisappear`); 800 ScreenManager.getInstance().off(ScreenManager.ON_WIN_SIZE_CHANGED, this.onWindowSizeChangeCallBack); 801 this.broadCast.off(BroadCastConstants.SELECT, this.selectFunc); 802 this.broadCast.off(BroadCastConstants.JUMP_PHOTO_BROWSER, this.jumpPhotoBrowserFunc); 803 this.broadCast.off(BroadCastConstants.JUMP_THIRD_PHOTO_BROWSER, this.jumpThirdPhotoBrowserFunc); 804 this.broadCast.off(Constants.ON_LOADING_FINISHED, this.onLoadingFinishedFunc); 805 this.broadCast.off(BroadCastConstants.ON_DATA_RELOADED, this.onDataReloadedFunc); 806 this.appBroadCast.off(BroadCastConstants.UPDATE_DATA_SOURCE, this.onUpdateFavorStateFunc); 807 this.appBroadCast.off(BroadCastConstants.DO_ANIMATION, this.onDoAnimationFunc); 808 this.dataSource.releaseBroadCast(); 809 MediaObserver.getInstance().unregisterObserver(this.dataObserver); 810 this.dataObserver.clearSource(); 811 this.mSelectManager?.releaseGetMediaItemFunc(); 812 this.mSelectManager?.unregisterCallback('allSelect'); 813 this.mSelectManager?.unregisterCallback('updateCount'); 814 this.mSelectManager?.unregisterCallback('select'); 815 } 816 817 isSameTransitionId(item: MediaItem): boolean { 818 return AppStorage.get<string>(Constants.KEY_OF_GEOMETRY_TRANSITION_ID_HEIGHT) as string === 819 `${item.hashCode}_${this.dataSource.albumUri}`; 820 } 821 822 getGeometryTransitionId(item: ViewData): string { 823 return TAG + (item.mediaItem as MediaItem).hashCode + 824 this.mSelectManager.isItemSelected((item.mediaItem as MediaItem).uri); 825 } 826 827 build() { 828 Column() { 829 PhotoGridPageActionBar({ 830 title: this.title, 831 albumInfo: this.albumInfo, 832 isSystemAlbum: this.albumInfo.isSystemAlbum, 833 onMenuClicked: (action: Action): void => this.onMenuClicked(action), 834 isRecycle: this.albumInfo.isTrashAlbum, 835 isDistributedAlbum: this.isDistributedAlbum, 836 totalSelectedCount: $totalSelectedCount 837 }) 838 .opacity(this.photoGridActionBarOpacity) 839 840 if (this.isEmpty) { 841 NoPhotoComponent({ title: $r('app.string.no_distributed_photo_head_title_album') }) 842 } else { 843 if (this.albumInfo.isTrashAlbum) { 844 Text($r('app.string.recycle_prompt_message', Constants.RECYCLE_DAYS_MAX)) 845 .fontColor($r('sys.color.ohos_id_color_text_secondary')) 846 .fontSize($r('sys.float.ohos_id_text_size_body2')) 847 .fontWeight(FontWeight.Regular) 848 .width(Constants.PERCENT_100) 849 .padding(this.isHorizontal ? { 850 left: $r('sys.float.ohos_id_max_padding_start'), 851 top: $r('app.float.recycle_prompt_message_margin_tb'), 852 bottom: $r('app.float.recycle_prompt_message_margin_tb') 853 } : { 854 left: $r('sys.float.ohos_id_max_padding_start'), 855 right: $r('sys.float.ohos_id_max_padding_end'), 856 top: $r('app.float.recycle_prompt_message_margin_tb'), 857 bottom: $r('app.float.recycle_prompt_message_margin_tb') 858 } 859 ) 860 } 861 Stack() { 862 Grid(this.scroller) { 863 LazyForEach(this.dataSource, (item: ViewData, index?: number) => { 864 if (!!item) { 865 GridItem() { 866 ImageGridItemComponent({ 867 dataSource: this.dataSource, 868 item: item.mediaItem, 869 isSelected: this.isSelectedMode ? 870 this.mSelectManager.isItemSelected((item.mediaItem as MediaItem).uri) : false, 871 isRecycle: this.albumInfo.isTrashAlbum, 872 pageName: Constants.PHOTO_TRANSITION_ALBUM, 873 onMenuClicked: (action: Action): void => this.onMenuClicked(action), 874 onMenuClickedForSingleItem: (action: Action, currentPhoto: MediaItem): void => { 875 this.onMenuClickedForSingleItem(action, currentPhoto); 876 }, 877 geometryTransitionString: this.getGeometryTransitionId(item), 878 mPosition: index, 879 selectedCount: $totalSelectedCount 880 }) 881 } 882 .zIndex(this.isSameTransitionId(item.mediaItem as MediaItem) || index === this.placeholderIndex ? 1 : 0) 883 .width(this.gridItemWidth) 884 .aspectRatio(1) 885 .key('AlbumGridImage' + index) 886 } 887 }, (item: ViewData, index?: number) => { 888 if (item == null || item == undefined) { 889 return JSON.stringify(item); 890 } 891 // Update animation object 892 if (index === 0) { 893 if (this.scrollIndex === 0) { 894 this.updateFirstPhotoItemInfo(item.mediaItem as MediaItem, true); 895 } else { 896 this.updateFirstPhotoItemInfo(( 897 this.dataSource.getData(this.scrollIndex) as ViewData)?.mediaItem as MediaItem, false); 898 } 899 } 900 return this.getGeometryTransitionId(item) 901 }) 902 } 903 .zIndex(-1) 904 .clip(false) 905 .onScrollIndex((index: number) => { 906 this.scrollIndex = index; 907 this.updateFirstPhotoItemInfo((this.dataSource.getData(index) as ViewData)?.mediaItem as MediaItem, false); 908 }) 909 .edgeEffect(EdgeEffect.Spring) 910 .scrollBar(BarState.Off) 911 .columnsTemplate('1fr '.repeat(this.gridRowCount)) 912 .columnsGap(Constants.GRID_GUTTER) 913 .rowsGap(Constants.GRID_GUTTER) 914 .cachedCount(Constants.GRID_CACHE_ROW_COUNT) 915 .transition(TransitionEffect.scale({ 916 x: BrowserConstants.PHOTO_GRID_Scale, 917 y: BrowserConstants.PHOTO_GRID_Scale, 918 z: BrowserConstants.PHOTO_GRID_Scale 919 })) 920 921 if (this.isShowScrollBar) { 922 GridScrollBar({ scroller: this.scroller }); 923 } 924 925 if (this.albumInfo.isTrashAlbum) { 926 Column() { 927 Row() { 928 Button({ type: ButtonType.Capsule, stateEffect: true }) { 929 Text($r('app.string.action_clear_recycle')) 930 .fontWeight(FontWeight.Medium) 931 .fontSize($r('sys.float.ohos_id_text_size_button1')) 932 .fontColor($r('sys.color.ohos_id_color_text_primary_activated')) 933 .margin({ 934 left: $r('app.float.dialog_double_buttons_margin'), 935 right: $r('app.float.dialog_double_buttons_margin') 936 }) 937 } 938 .key('ClearRecycleButton') 939 .height($r('app.float.details_dialog_button_height')) 940 .borderRadius($r('sys.float.ohos_id_corner_radius_button')) 941 .backgroundColor($r('sys.color.ohos_id_color_button_normal')) 942 .onClick(() => { 943 this.onMenuClicked && this.onMenuClicked(Action.CLEAR_RECYCLE); 944 }) 945 } 946 .borderRadius($r('sys.float.ohos_id_corner_radius_button')) 947 .backgroundColor($r('sys.color.ohos_id_color_sub_background')) 948 } 949 .hitTestBehavior(HitTestMode.Transparent) 950 .width(`100%`) 951 .height('100%') 952 .alignItems(HorizontalAlign.Center) 953 .justifyContent(FlexAlign.End) 954 .padding({ bottom: $r('sys.float.ohos_id_default_padding_bottom_fixed') }) 955 .visibility(this.isSelectedMode ? Visibility.Hidden : Visibility.Visible) 956 } 957 } 958 .clip(true) 959 .zIndex(-1) 960 .layoutWeight(1) 961 .padding({ 962 bottom: ((this.isSelectedMode) && !this.isHorizontal) ? Constants.ActionBarHeight : 0 963 }) 964 } 965 CustomDialogView({ broadCast: $broadCast }); 966 967 if (this.isSelectedMode) { 968 PhotoGridPageToolBar({ 969 onMenuClicked: (action: Action): void => this.onMenuClicked(action), 970 isRecycleAlbum: (this.albumInfo.isTrashAlbum), 971 isDistributedAlbum: this.isDistributedAlbum, 972 totalSelectedCount: $totalSelectedCount 973 }); 974 } 975 } 976 .clip(true) 977 .opacity(this.photoGridViewOpacity) 978 .backgroundColor($r('app.color.default_background_color')) 979 .padding({ 980 top: this.leftBlank[1] 981 }) 982 } 983 984 private onUpdateFavorState(item: MediaItem): void { 985 Log.debug(TAG, 'onUpdateFavorState'); 986 let index = this.dataSource.getIndexByMediaItem(item); 987 if (index != -1) { 988 this.dataSource.onDataChanged(index); 989 } 990 } 991 992 private moveOperation(albumName: string, albumUri: string): void { 993 let menuContext = new MenuContext(); 994 if (this.isMvOrCpSeparatesItem) { 995 menuContext.withMediaItem(this.mvOrCpSeparatesItem); 996 this.onMoveStart && this.onMoveStart(); 997 } else { 998 menuContext.withSelectManager(this.mSelectManager).withOperationStartCallback((): void => this.onMoveStart()); 999 } 1000 menuContext.withOperationEndCallback((err: Error, count: number, total: number): void => 1001 this.onMoveEnd(err as Object, count, total)) 1002 .withBroadCast(this.broadCast) 1003 .withTargetAlbumName(albumName) 1004 .withAlbumUri(albumUri); 1005 let menuOperation = MenuOperationFactory.getInstance().createMenuOperation(MoveMenuOperation, menuContext); 1006 AppStorage.setOrCreate(Constants.APP_KEY_NEW_ALBUM_SOURCE, this.albumInfo.uri); 1007 menuOperation.doAction(); 1008 } 1009 1010 private addOperation(albumName: string, albumUri: string): void { 1011 let menuContext = new MenuContext(); 1012 if (this.isMvOrCpSeparatesItem) { 1013 menuContext.withMediaItem(this.mvOrCpSeparatesItem); 1014 this.onCopyStart && this.onCopyStart(); 1015 } else { 1016 menuContext.withSelectManager(this.mSelectManager).withOperationStartCallback((): void => this.onCopyStart()); 1017 } 1018 menuContext.withOperationEndCallback((err: Error, count: number, total: number): void => 1019 this.onCopyEnd(err as Object, count, total)) 1020 .withBroadCast(this.broadCast) 1021 .withTargetAlbumName(albumName) 1022 .withAlbumUri(albumUri); 1023 let menuOperation = MenuOperationFactory.getInstance().createMenuOperation(AddMenuOperation, menuContext); 1024 menuOperation.doAction(); 1025 } 1026 1027 private onMenuClickedForSingleItem(action: Action, currentPhoto: MediaItem) { 1028 Log.info(TAG, `single menu click, action: ${action?.actionID}, currentUri: ${currentPhoto?.uri}`); 1029 if (currentPhoto == undefined) { 1030 return; 1031 } 1032 let menuOperation: MenuOperation; 1033 let menuContext: MenuContext; 1034 if (action.actionID === Action.RECOVER.actionID) { 1035 menuContext = new MenuContext(); 1036 menuContext.withMediaItem(currentPhoto).withBroadCast(this.broadCast); 1037 menuOperation = MenuOperationFactory.getInstance() 1038 .createMenuOperation(RecoverMenuOperation, menuContext); 1039 menuOperation.doAction(); 1040 } else if (action.actionID === Action.DELETE.actionID) { 1041 menuContext = new MenuContext(); 1042 if (this.dataSource.albumUri == UserFileManagerAccess.getInstance() 1043 .getSystemAlbumUri(UserFileManagerAccess.TRASH_ALBUM_SUB_TYPE)) { 1044 menuContext.withAlbumUri(UserFileManagerAccess.getInstance() 1045 .getSystemAlbumUri(UserFileManagerAccess.TRASH_ALBUM_SUB_TYPE)); 1046 } 1047 menuContext.withMediaItem(currentPhoto).withBroadCast(this.broadCast); 1048 menuOperation = MenuOperationFactory.getInstance() 1049 .createMenuOperation(DeleteMenuOperation, menuContext); 1050 menuOperation.doAction(); 1051 } else if (action.actionID === Action.MOVE.actionID) { 1052 this.isMvOrCpSeparatesItem = true; 1053 this.mvOrCpSeparatesItem = currentPhoto; 1054 this.routeToSelectAlbumPage(MediaOperationType.Move, [currentPhoto]); 1055 } else if (action.actionID === Action.ADD.actionID) { 1056 this.isMvOrCpSeparatesItem = true; 1057 this.mvOrCpSeparatesItem = currentPhoto; 1058 this.routeToSelectAlbumPage(MediaOperationType.Add, [currentPhoto]); 1059 } else if (action.actionID === Action.REMOVE_FROM.actionID) { 1060 menuContext = new MenuContext(); 1061 menuContext.withMediaItem(currentPhoto).withBroadCast(this.broadCast); 1062 menuOperation = MenuOperationFactory.getInstance() 1063 .createMenuOperation(RemoveMenuOperation, menuContext); 1064 menuOperation.doAction(); 1065 } else if (action.actionID === Action.INFO.actionID) { 1066 this.broadCast.emit(BroadCastConstants.SHOW_DETAIL_DIALOG, [currentPhoto, false]); 1067 } 1068 } 1069 1070 private initGridRowCount(): void { 1071 let contentWidth = ScreenManager.getInstance().getWinWidth(); 1072 let margin = 0; 1073 let maxThumbWidth = px2vp(Constants.GRID_IMAGE_SIZE) * Constants.GRID_MAX_SIZE_RATIO; 1074 // 原型机竖屏为4不变,横屏需计算: currentBreakpoint == 'lg' 表示横屏 1075 const currentBreakpoint: string = AppStorage.get<string>('currentBreakpoint') as string; 1076 this.gridRowCount = currentBreakpoint == Constants.BREAKPOINT_LG ? 1077 Math.max(Constants.GRID_MIN_COUNT, Math.ceil(((contentWidth - Constants.NUMBER_2 * margin) + 1078 Constants.GRID_GUTTER) / (maxThumbWidth + Constants.GRID_GUTTER))) : Constants.GRID_MIN_COUNT; 1079 this.gridItemWidth = (contentWidth - (this.gridRowCount - 1) * Constants.GRID_GUTTER - 1080 Constants.NUMBER_2 * margin) / this.gridRowCount; 1081 Log.info(TAG, `initGridRowCount contentWidth: ${contentWidth}`); 1082 } 1083 1084 private onUpdateRemoteDevice(res: string, deviceId: string): void { 1085 Log.info(TAG, `onUpdateRemoteDevice`); 1086 if (res == 'offline') { 1087 Log.debug(TAG, `device offline route to album main`); 1088 router.back({ 1089 url: 'pages/index', 1090 params: { 1091 jumpSource: JumpSourceToMain.ALBUM, 1092 } 1093 }); 1094 } else { 1095 Log.error(TAG, `res code is err ${res}`); 1096 return; 1097 } 1098 } 1099} 1100 1101interface Params { 1102 albumName: string; 1103 albumUri: string; 1104 pageType: string; 1105}; 1106 1107interface ParamAlbumInfo { 1108 item: string; 1109 isFromFACard: boolean; 1110};