1/* 2 * Copyright (c) 2022 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 '@system.router'; 17import Want from '@ohos.application.Want'; 18import MediaLib from '@ohos.multimedia.mediaLibrary'; 19import { Log } from '@ohos/base/src/main/ets/utils/Log'; 20import { Action } from '../../../common/view/browserOperation/Action'; 21import type { MenuOperation } from '@ohos/base/src/main/ets/operation/MenuOperation'; 22import { MenuContext } from '@ohos/base/src/main/ets/operation/MenuContext'; 23import { 24 GotoPhotosMenuOperation 25} from '@ohos/browser/src/main/ets/operation/GotoPhotosMenuOperation'; 26import { BatchDeleteMenuOperation } from '@ohos/base/src/main/ets/operation/BatchDeleteMenuOperation'; 27import { BatchRecoverMenuOperation } from '@ohos/base/src/main/ets/operation/BatchRecoverMenuOperation'; 28import { ClearRecycleMenuOperation } from '@ohos/base/src/main/ets/operation/ClearRecycleMenuOperation'; 29import { MediaConstants } from '@ohos/base/src/main/ets/constants/MediaConstants'; 30import { MoveMenuOperation } from '@ohos/base/src/main/ets/operation/MoveMenuOperation'; 31import { CopyMenuOperation } from '@ohos/base/src/main/ets/operation/CopyMenuOperation'; 32import { DateUtil } from '@ohos/base/src/main/ets/utils/DateUtil'; 33import { CustomDialogView } from '../../../common/view/dialog/CustomDialogView'; 34import { Constants } from '../../../common/model/common/Constants'; 35import { Broadcast } from '@ohos/base/src/main/ets/utils/Broadcast'; 36import { BroadcastConstants } from '@ohos/base/src/main/ets/constants/BroadcastConstants'; 37import broadcastManager from '@ohos/base/src/main/ets/manager/BroadcastManager'; 38import { Constants as PhotoConstants } from '@ohos/browser/src/main/ets/constants/Constants'; 39import { PhotoBrowserBg } from '@ohos/browser/src/main/ets/components/PhotoBrowserBg'; 40import { PhotoBrowserActionBar } from './PhotoBrowserActionBar'; 41import { ToolBar } from '../../../common/view/actionbar/ToolBar'; 42import { PhotoSwiper } from '@ohos/browser/src/main/ets/components/PhotoSwiper'; 43import screenManager from '@ohos/base/src/main/ets/manager/ScreenManager'; 44import { JumpSourceToMain } from '@ohos/base/src/main/ets/data/JumpSourceToMain'; 45import { RenameMenuOperation } from '@ohos/browser/src/main/ets/operation/RenameMenuOperation'; 46import { MediaOperationType } from '@ohos/base/src/main/ets/data/MediaOperationType'; 47import { showToast } from '@ohos/base/src/main/ets/utils/UiUtil'; 48import { getResourceString } from '@ohos/base/src/main/ets/utils/ResourceUtils'; 49import { CommonObserverCallback } from '@ohos/base/src/main/ets/observer/CommonObserverCallback'; 50import mediaObserver from '@ohos/base/src/main/ets/observer/MediaObserver'; 51import mMultimodalInputManager from '@ohos/base/src/main/ets/manager/MultimodalInputManager'; 52import { startTrace, finishTrace } from '@ohos/base/src/main/ets/utils/TraceControllerUtils'; 53import { GroupItemDataSource } from '@ohos/base/src/main/ets/vm/GroupItemDataSource'; 54import { MediaDataItem } from '@ohos/base/src/main/ets/data/MediaDataItem'; 55import { InnerMediaDataItem } from '@ohos/browser/src/main/ets/data/InnerMediaDataItem'; 56import { SimpleAlbumDataItem } from '@ohos/base/src/main/ets/data/SimpleAlbumDataItem'; 57import { getAlbumDisplayName } from '@ohos/base/src/main/ets/helper/MediaDataHelper'; 58import { startAbility, terminateSelf } from '@ohos/base/src/main/ets/utils/AbilityUtils'; 59import mediaDataItemCache from '@ohos/base/src/main/ets/data/MediaDataItemCache'; 60import { PhotoEditorManager } from '../../editor/PhotoEditorManager'; 61// page of large photo 62 63const TAG = "PhotoBrowser" 64 65@Entry 66@Component 67struct PhotoBrowser { 68 @State mOpacity: number = 1; 69 @Provide browserBackgroundColor: Resource = $r('app.color.default_background_color'); 70 @Provide('dateTitle') photoDate: string = ''; 71 @Provide('timeLocationTitle') timeAndLocation: string = ''; 72 @Provide menuList: Array<Action> = new Array<Action>(); 73 @State toolMenuList: Array<Action> = new Array<Action>(); 74 @Provide topMenuList: Array<Action> = new Array<Action>(); 75 @Provide moreMenuList: Array<Action> = new Array<Action>(); 76 @Provide broadCast: Broadcast = new Broadcast(); 77 @Provide isShowBar: boolean = true; 78 @Provide isPullingDown: boolean = false; 79 @Provide pageFrom: number = Constants.ENTRY_FROM.NORMAL; 80 @Provide canSwipe: boolean = false; 81 private timeoutId: number = 0; 82 @State @Watch('currentShowChange') currentShow: boolean = true; 83 @StorageLink('isHorizontal') isHorizontal: boolean = screenManager.isHorizontal(); 84 @StorageLink('TimelinePageIndex') TimelinePageIndex: number = Constants.INVALID; 85 @StorageLink('PhotoGridPageIndex') PhotoGridPageIndex: number = Constants.INVALID; 86 @StorageLink('isSplitMode') isSplitMode: boolean = screenManager.isSplitMode(); 87 @StorageLink('leftBlank') leftBlank: [number, number, number, number] = [0, 0, 0, 0]; 88 @StorageLink('entryFromHap') entryFromHap: number = Constants.ENTRY_FROM_NONE; 89 photoBrowserTransition: string; 90 @State isDataChanged:boolean = true; 91 private isFromCard = false; 92 93 // swiper currentIndex, there may not be onChanged callback during data refresh, so mediaItem cannot be saved 94 @Provide('transitionIndex') currentIndex: number = 0; 95 controller: SwiperController = new SwiperController(); 96 private dataObserver: CommonObserverCallback = new CommonObserverCallback(this); 97 98 // The global Broadcast of the application process. Event registration and destruction should be paired 99 private appBroadcast: Broadcast = broadcastManager.getBroadcast(); 100 private isFromCamera = false; 101 private isFromViewData = false; 102 103 // the source of jump to the index page 104 private jumpSourceToMain: number = JumpSourceToMain.None; 105 106 // time to view the current picture 107 private checkedTransition: string; 108 109 // When clicking quickly, only run aboutToAppear for the first time 110 private hasAppeared: boolean; 111 private albumInfo: SimpleAlbumDataItem; 112 private deviceName = ''; 113 private backFromCopy = false; 114 private pullDownFlag: boolean = false; 115 private browserDataSource: GroupItemDataSource = new GroupItemDataSource() 116 private isToEdit = false; 117 118 onMenuClicked(action: Action) { 119 Log.info(TAG, `onMenuClicked, action: ${action.actionID}, isPullingDown: ${this.isPullingDown}`); 120 if (this.isPullingDown) { 121 return; 122 } 123 let menuOperation: MenuOperation; 124 let menuContext: MenuContext = new MenuContext(); 125 let currentPhoto = this.getCurrentPhoto(); 126 switch (action) { 127 case Action.BACK: 128 this.onBackPress(); 129 return; 130 case Action.INFO: 131 if (currentPhoto == undefined) { 132 return; 133 } 134 this.broadCast.emit(BroadcastConstants.SHOW_DETAIL_DIALOG, [currentPhoto, this.pageFrom == Constants.ENTRY_FROM.DISTRIBUTED]); 135 return; 136 case Action.SHARE: 137 if (currentPhoto == undefined) { 138 return; 139 } 140 let want: Want = { 141 'action': 'com.huawei.intent.action.hwCHOOSER', 142 'parameters': { 143 'ability.want.params.INTENT': { 144 'action': 'ability.intent.SEND_DATA', 145 'type': '*/*', 146 'parameters': { 147 'ability.params.stream': currentPhoto.uri 148 } 149 } 150 } 151 } 152 startAbility(want) 153 return; 154 case Action.NOT_FAVORITE: 155 case Action.FAVORITE: 156 if (currentPhoto == undefined) { 157 return; 158 } 159 currentPhoto.setFavor().then((isSuccess: boolean) => this.setFavourite(isSuccess)) 160 return; 161 case Action.DELETE: 162 if (currentPhoto == undefined) { 163 return; 164 } 165 menuContext.withItems([currentPhoto]) 166 .withDeletePageFromType(BroadcastConstants.DELETE_FROM_BROWSER) 167 .withAlbumId(this.albumInfo && this.albumInfo.id) 168 .withBroadCast(this.broadCast) 169 .withOperationEndCallback(this.onDeleteEnd.bind(this)) 170 menuOperation = new BatchDeleteMenuOperation(menuContext); 171 break; 172 case Action.CLEAR_RECYCLE: 173 if (currentPhoto == undefined) { 174 return; 175 } 176 menuContext.withItems([currentPhoto]) 177 .withBroadCast(this.broadCast) 178 .withOperationEndCallback(this.onDeleteEnd.bind(this)) 179 menuOperation = new ClearRecycleMenuOperation(menuContext); 180 break; 181 case Action.RECOVER: 182 if (currentPhoto == undefined) { 183 return; 184 } 185 menuContext = new MenuContext(); 186 this.onDeleteEnd = this.onDeleteEnd.bind(this); 187 menuContext.withItems([currentPhoto]) 188 .withOperationEndCallback(this.onDeleteEnd) 189 .withBroadCast(this.broadCast) 190 menuOperation = new BatchRecoverMenuOperation(menuContext); 191 break; 192 case Action.GOTO_PHOTOS: 193 menuContext.withJumpSourceToMain(this.jumpSourceToMain); 194 menuOperation = new GotoPhotosMenuOperation(menuContext); 195 break; 196 case Action.EDIT: 197 if (currentPhoto == undefined || currentPhoto.size == 0) { 198 return; 199 } 200 this.isToEdit = true 201 globalThis.EditorMediaItem = currentPhoto; 202 router.push({ 203 uri: 'feature/editor/view/EditMain' 204 }) 205 return; 206 case Action.RENAME: 207 if (currentPhoto == undefined) { 208 return; 209 } 210 menuContext.withItems([currentPhoto]) 211 .withBroadCast(this.broadCast) 212 .withAlbumInfo(this.albumInfo); 213 menuOperation = new RenameMenuOperation(menuContext); 214 break; 215 case Action.ROTATE: 216 if (currentPhoto == undefined) { 217 return; 218 } 219 currentPhoto.setOrientation().then(() => this.setOrientation()) 220 return; 221 case Action.MOVE: 222 this.backFromCopy = true; 223 this.routeSelectAlbumPage(MediaOperationType.Move); 224 return; 225 case Action.COPY: 226 this.backFromCopy = true; 227 this.routeSelectAlbumPage(MediaOperationType.Copy); 228 return; 229 case Action.DOWNLOAD: 230 this.downLoad(); 231 return; 232 default: 233 return; 234 } 235 menuOperation.doAction(); 236 } 237 238 private setFavourite(isSuccess: boolean) { 239 Log.debug(TAG, 'set favor !'); 240 241 if (isSuccess) { 242 let currentPhoto = this.getCurrentPhoto(); 243 if (currentPhoto == undefined) { 244 return; 245 } 246 if (mediaDataItemCache.hasKey(currentPhoto.uri)) { 247 mediaDataItemCache.get(currentPhoto.uri).favouriteStatus = currentPhoto.favouriteStatus; 248 } 249 // 收藏相册进入大图,点击取消收藏会导致Item成员变少,所以要dataRemove 250 this.browserDataSource.reloadGroupItemData(false).then(() => { 251 this.operateEnd(); 252 }); 253 this.updateMenu(); 254 this.appBroadcast.emit(BroadcastConstants.UPDATE_DATA_SOURCE, [currentPhoto]); 255 } 256 } 257 258 private operateEnd() { 259 if (this.currentIndex == 0 || AppStorage.Get("isLeftSwiper") == 0) { 260 this.broadCast.emit(BroadcastConstants.ON_DATA_RELOADED, []); 261 } else { 262 Log.info(TAG, `operateEnd curIndex : ` + this.currentIndex); 263 this.broadCast.emit(BroadcastConstants.ON_DATA_RELOADED, []); 264 this.currentIndex--; 265 } 266 } 267 268 private onDeleteEnd() { 269 Log.debug(TAG, `onDeleteEnd start`); 270 AppStorage.SetOrCreate("isDelete", 0); 271 this.operateEnd(); 272 } 273 274 private setOrientation() { 275 Log.debug(TAG, `setOrientation`); 276 let currentPhoto = this.getCurrentPhoto(); 277 if (currentPhoto == undefined) { 278 return; 279 } 280 this.browserDataSource.notifyDataChange(this.currentIndex); 281 this.appBroadcast.emit(BroadcastConstants.UPDATE_DATA_SOURCE, [currentPhoto]); 282 } 283 284 onToggleBars() { 285 if (this.isShowBar) { 286 this.hideBars(); 287 } else { 288 this.showBars(); 289 } 290 Log.info(TAG, `Toggle bars, isShowBar: ${this.isShowBar}`); 291 } 292 293 showBars(): void { 294 if (!this.isShowBar) { 295 this.isShowBar = true; 296 this.browserBackgroundColor = $r('app.color.default_background_color'); 297 screenManager.setSystemUi(true); 298 } 299 } 300 301 hideBars(): void { 302 if (this.isShowBar) { 303 this.isShowBar = false; 304 this.browserBackgroundColor = $r('app.color.black'); 305 screenManager.setSystemUi(false); 306 } 307 } 308 309 routeSelectAlbumPage(pageType: string): void { 310 router.push({ 311 uri: 'common/view/browserOperation/MediaOperationPage', 312 params: { 313 pageType: pageType, 314 albumInfo: JSON.stringify(this.albumInfo) 315 } 316 }); 317 } 318 319 onPhotoChanged(index: number): void{ 320 index = Math.min(index, this.browserDataSource.totalCount() - 1); 321 Log.info(TAG, `onPhotoChanged start ${index}`); 322 this.currentIndex = this.isToEdit ? 0 : index; 323 this.updateActionBar(); 324 } 325 326 onDataSizeChanged(size: number): void { 327 Log.info(TAG, `onDataSizeChanged, size is ${size}`); 328 if (size == 0) { 329 if (this.pageFrom == Constants.ENTRY_FROM.CARD) { 330 let menuContext: MenuContext = new MenuContext(); 331 menuContext.withJumpSourceToMain(this.jumpSourceToMain); 332 let menuOperation = new GotoPhotosMenuOperation(menuContext); 333 menuOperation.doAction(); 334 } else { 335 this.onBackPress(); 336 } 337 } 338 } 339 340 updateActionBar() { 341 let currentPhoto = this.getCurrentPhoto(); 342 if (currentPhoto == undefined || this.isFromViewData) { 343 Log.warn(TAG, `currentPhoto is undefined:${currentPhoto == undefined} this.isFromViewData:${this.isFromViewData} `) 344 return; 345 } 346 347 // PhotoItems 和 这里都会有load, 极端情况下可能产生一次无效的load 348 currentPhoto.load(false).then(() => { 349 this.photoDate = DateUtil.getLocalizedDate(currentPhoto.dateAdded); 350 if (this.pageFrom == Constants.ENTRY_FROM.DISTRIBUTED) { 351 this.timeAndLocation = `${this.deviceName}/${DateUtil.getLocalizedTime(currentPhoto.dateAdded)}`; 352 } else { 353 this.timeAndLocation = DateUtil.getLocalizedTime(currentPhoto.dateAdded); 354 } 355 this.updateMenu(); 356 }) 357 } 358 359 updateMenu(): void{ 360 let currentPhoto = this.getCurrentPhoto(); 361 if (currentPhoto == undefined) { 362 return; 363 } 364 this.toolMenuList = []; 365 this.getActionList(currentPhoto).then((list: Array<Action>) => { 366 if (this.pageFrom == Constants.ENTRY_FROM.CAMERA || this.pageFrom == Constants.ENTRY_FROM.CARD) { 367 this.menuList = [Action.GOTO_PHOTOS, Action.INFO]; 368 } else if (this.pageFrom == Constants.ENTRY_FROM.RECYCLE) { 369 this.menuList = []; 370 } else { 371 this.menuList = [Action.INFO]; 372 } 373 if (this.isHorizontal) { 374 this.menuList = this.menuList.concat(list); 375 } else { 376 this.toolMenuList = list; 377 } 378 this.updateMoreMenu(); 379 }) 380 } 381 382 private async getActionList(currentPhoto: MediaDataItem): Promise<Array<Action>> { 383 let list: Array<Action> = new Array<Action>(); 384 if (this.pageFrom == Constants.ENTRY_FROM.RECYCLE) { 385 list.push(Action.RECOVER, Action.DELETE); 386 } else if (this.pageFrom == Constants.ENTRY_FROM.DISTRIBUTED) { 387 list.push(Action.SHARE, Action.DOWNLOAD); 388 } else { 389 let isFavor = await currentPhoto.isFavor(); 390 list.push(Action.SHARE, 391 isFavor ? Action.FAVORITE : Action.NOT_FAVORITE, 392 currentPhoto.mediaType == MediaLib.MediaType.IMAGE ? Action.EDIT : Action.EDIT_INVALID, 393 Action.DELETE, 394 Action.MORE); // TODO: delete edit 395 } 396 return list; 397 } 398 399 private currentShowChange() { 400 this.updateMoreMenu(); 401 } 402 403 private updateMoreMenu() { 404 let currentPhoto = this.getCurrentPhoto(); 405 this.moreMenuList = [Action.MOVE, Action.COPY, Action.RENAME]; 406 if (currentPhoto == undefined) { 407 return; 408 } 409 if (currentPhoto.mediaType == MediaLib.MediaType.IMAGE) { 410 if (this.currentShow) { 411 this.moreMenuList.push(Action.ROTATE); 412 } 413 } 414 } 415 416 getCurrentPhoto(): MediaDataItem { 417 return this.browserDataSource.getDataByIndex(this.currentIndex); 418 } 419 420 getPhotoByIndex(index: number): MediaDataItem { 421 return this.browserDataSource.getDataByIndex(index); 422 } 423 424 async onMoveEnd(err, count, total) { 425 Log.debug(TAG, `onMoveEnd count: ${count}, total: ${total}`); 426 if (err) { 427 getResourceString($r('app.string.move_failed_single')).then((message: string) => { 428 showToast(message) 429 }) 430 return; 431 } 432 let currentPhoto = this.getCurrentPhoto(); 433 if (currentPhoto == undefined) { 434 return; 435 } 436 currentPhoto.path = (await currentPhoto.loadFileAsset()).relativePath; 437 this.appBroadcast.emit(BroadcastConstants.UPDATE_DATA_SOURCE, [currentPhoto]); 438 } 439 440 onCopyEnd(err, count, total): void { 441 Log.debug(TAG, `onCopyEnd count: ${count}, total: ${total}`); 442 this.dataSourceLoadFinish() 443 if (err) { 444 getResourceString($r('app.string.copy_failed_single')).then((message: string) => { 445 showToast(message); 446 }) 447 } 448 } 449 450 async onDownloadEnd(err, count, total) { 451 Log.debug(TAG, `onDownloadEnd count: ${count}, total: ${total}`); 452 if (err) { 453 getResourceString($r('app.string.download_failed_single')).then((message: string) => { 454 showToast(message); 455 }) 456 } else { 457 getResourceString($r('app.string.download_progress_done')).then((message: string) => { 458 showToast(message); 459 }) 460 } 461 } 462 463 onBackPress() { 464 Log.info(TAG, 'onBackPress'); 465 this.controller.finishAnimation(this.onBackPressInner.bind(this)); 466 return true; 467 } 468 469 onBackPressInner(): void { 470 Log.info(TAG, `onBackPressInner ${this.checkedTransition}`); 471 switch (this.checkedTransition) { 472 case Constants.PHOTO_TRANSITION_TIMELINE: 473 Log.info(TAG, 'onBackPress TimelinePage'); 474 this.TimelinePageIndex = this.currentIndex; // call scrollTo 475 break; 476 case Constants.PHOTO_TRANSITION_ALBUM: 477 Log.info(TAG, 'onBackPress PhotoGridPage'); 478 this.PhotoGridPageIndex = this.currentIndex; // call scrollTo 479 break; 480 case Constants.PHOTO_TRANSITION_CAMERA: 481 Log.info(TAG, 'onBackPress Camera'); 482 if (this.pageFrom == Constants.ENTRY_FROM.CARD && !this.pullDownFlag) { 483 this.routerGridPaged(); 484 } else { 485 if (this.pullDownFlag) { 486 this.pullDownFlag = false; 487 } 488 // Entering from the camera does not need to return to close directly 489 terminateSelf(); 490 } 491 return; 492 default: 493 break 494 } 495 router.back({ 496 params: { 497 index: this.currentIndex 498 } 499 }); 500 } 501 502 aboutToDisappear(): void { 503 Log.info(TAG, 'aboutToDisappear'); 504 screenManager.setNavigationBarColor('#00FFFFFF', '#FF000000'); 505 if (!this.isShowBar) { 506 screenManager.setSystemUi(true); 507 } 508 // Click the thumbnail quickly, hasAppeared is false if it is not the first click. Return directly 509 if (!this.hasAppeared) { 510 return; 511 } 512 mediaObserver.unregisterObserver(this.dataObserver); 513 mMultimodalInputManager.unregisterListener(); 514 } 515 516 aboutToAppear(): void { 517 startTrace('PhotoBrowserAboutToAppear'); 518 Log.info(TAG, 'photoBrowser aboutToAppear'); 519 AppStorage.SetOrCreate("isDelete", 0); 520 AppStorage.SetOrCreate("isLeftSwiper", 0); 521 screenManager.setNavigationBarColor('#FFF1F3F5', '#FF000000'); 522 this.hasAppeared = true; 523 mMultimodalInputManager.registerListener((control: number) => { 524 Log.info(TAG, `key control: ${control} index ${this.currentIndex}`); 525 if (control == 0) { 526 if (this.currentIndex > 0) { 527 this.onPhotoChanged(this.currentIndex - 1); 528 } 529 } else if (control == 1) { 530 if (this.currentIndex < this.browserDataSource.totalCount() - 1) { 531 this.onPhotoChanged(this.currentIndex + 1); 532 } 533 } else { 534 this.onBackPress(); 535 } 536 }); 537 let param = router.getParams(); 538 if (param) { 539 Log.info(TAG, `photoBrowser start with param`); 540 Log.debug(TAG, `param: ${JSON.stringify(param)}`); 541 if (param.pageFrom) { 542 this.pageFrom = parseInt(param.pageFrom.toString()); 543 } 544 if (this.pageFrom == Constants.ENTRY_FROM.CAMERA) { 545 this.isFromCamera = true; 546 this.albumInfo = new SimpleAlbumDataItem(MediaConstants.ALBUM_ID_CAMERA, "", "", "", "") 547 this.browserDataSource.setAlbumId(this.albumInfo.id) 548 this.jumpSourceToMain = JumpSourceToMain.CAMERA; 549 } else if (this.pageFrom == Constants.ENTRY_FROM.VIEW_DATA) { 550 this.isFromViewData = true; 551 } 552 553 if (param.albumInfo) { 554 this.albumInfo = param.albumInfo as SimpleAlbumDataItem; 555 this.deviceName = this.albumInfo.deviceName; 556 this.browserDataSource.setAlbumId(this.albumInfo.id) 557 this.browserDataSource.setDeviceId(this.albumInfo.deviceId); 558 } 559 560 let items: MediaDataItem[]; 561 if (param.viewData) { 562 items = [] 563 let uriArr: string[] = String(param.viewData).split(','); 564 for (let i = 0;i < uriArr.length; i++) { 565 items.push(new InnerMediaDataItem(uriArr[i], i)); 566 } 567 } else { 568 items = AppStorage.Get<MediaDataItem[]>(Constants.APP_KEY_PHOTO_BROWSER); 569 } 570 571 if (items && !this.isFromCamera) { 572 this.browserDataSource.groupDataItem = items; 573 this.onPhotoChanged(new Number(param.position).valueOf() || 0); 574 } else { 575 this.browserDataSource.reloadGroupItemData(false).then((isEmpty: boolean) => { 576 this.onPhotoChanged(0); 577 this.browserDataSource.notifyDataReload(); 578 }) 579 } 580 581 this.photoBrowserTransition = (this.isFromCamera || this.isFromViewData) 582 ? Constants.PHOTO_TRANSITION_CAMERA : (param.transition ? param.transition.toString() : ''); 583 } else { 584 Log.info(TAG, `photoBrowser start without param`); 585 if (this.entryFromHap == Constants.ENTRY_FROM_FORM_ABILITY) { 586 this.isFromCard = true; 587 this.pageFrom = Constants.ENTRY_FROM.CARD; 588 this.albumInfo = new SimpleAlbumDataItem(AppStorage.Get(Constants.FROM_ALBUM_ID), "", "", "", ""); 589 } else { 590 this.pageFrom = Constants.ENTRY_FROM.CAMERA; 591 this.albumInfo = new SimpleAlbumDataItem(MediaConstants.ALBUM_ID_CAMERA, "", "", "", ""); 592 } 593 AppStorage.SetOrCreate(Constants.ENTRY_FROM_HAP, Constants.ENTRY_FROM_NONE); 594 this.browserDataSource.setAlbumId(this.albumInfo.id); 595 this.browserDataSource.reloadGroupItemData(false).then((isEmpty: boolean) => { 596 this.isDataChanged = isEmpty; 597 this.onPhotoChanged(AppStorage.Get(Constants.FROM_CURRENT_INDEX) || 0); 598 this.browserDataSource.notifyDataReload() 599 }); 600 this.isFromCamera = true; 601 this.jumpSourceToMain = JumpSourceToMain.CAMERA; 602 603 this.photoBrowserTransition = Constants.PHOTO_TRANSITION_CAMERA; 604 } 605 606 mediaObserver.registerObserver(this.dataObserver); 607 this.checkedTransition = this.photoBrowserTransition; 608 609 this.onMenuClicked = this.onMenuClicked.bind(this); 610 611 // register event handling 612 this.broadCast.on(PhotoConstants.TOGGLE_BAR, () => { 613 this.onToggleBars(); 614 }); 615 616 this.broadCast.on(PhotoConstants.HIDE_BARS, () => { 617 this.hideBars(); 618 }); 619 620 this.broadCast.on(PhotoConstants.PULL_DOWN_START, () => { 621 Log.info(TAG, 'pulling down start'); 622 }); 623 624 this.broadCast.on(PhotoConstants.PULL_DOWN_END, () => { 625 this.pullDownFlag = true; 626 this.onBackPress(); 627 }); 628 629 this.broadCast.on(PhotoConstants.DATA_SIZE_CHANGED, (size: number) => { 630 this.onDataSizeChanged(size); 631 }); 632 633 this.broadCast.on(PhotoConstants.DATA_CONTENT_CHANGED, () => { 634 this.onPhotoChanged(this.currentIndex); 635 }); 636 637 this.broadCast.on(PhotoConstants.RENAME, (result: string[]) => { 638 Log.info(TAG, `rename refresh: ${result[0]}, ${result[1]}`); 639 let currentPhoto = this.getCurrentPhoto(); 640 if (currentPhoto == undefined) { 641 return; 642 } 643 currentPhoto.title = result[0]; 644 currentPhoto.displayName = result[1]; 645 this.appBroadcast.emit(BroadcastConstants.UPDATE_DATA_SOURCE, [currentPhoto]); 646 }); 647 648 this.broadCast.on(PhotoConstants.PULL_DOWN_START, (event) => { 649 Log.debug(TAG, `pulling down start : ${JSON.stringify(event)}`); 650 this.isPullingDown = true; 651 }) 652 653 this.broadCast.on(PhotoConstants.PULL_DOWN_CANCEL, () => { 654 Log.info(TAG, 'pulling down cancel'); 655 this.isPullingDown = false; 656 }) 657 658 this.broadCast.on(PhotoConstants.PHOTO_SHOW_STATE, (state: boolean) => { 659 Log.debug(TAG, 'current photo show state change'); 660 this.currentShow = state; 661 }); 662 663 this.broadCast.on(PhotoConstants.SET_DISABLE_SWIPE, (value: boolean) => { 664 Log.info(TAG, `set swiper swipe ${value}`); 665 this.canSwipe = value; 666 }); 667 668 finishTrace('PhotoBrowserAboutToAppear'); 669 } 670 671 private async dataSourceLoadFinish() { 672 await this.browserDataSource.reloadGroupItemData(false); 673 for(let i = 0;i < this.browserDataSource.groupDataItem.length;i++) { 674 await this.browserDataSource.groupDataItem[i].load(false); 675 } 676 this.onPhotoChanged(this.currentIndex); 677 this.browserDataSource.notifyDataChange(this.currentIndex); 678 if (this.isToEdit) { 679 this.isToEdit = false; 680 this.appBroadcast.emit(BroadcastConstants.PHOTO_EDIT_SAVE_COMPLETE, []); 681 } 682 } 683 684 onPageShow() { 685 startTrace('PhotoBrowserOnPageShow'); 686 this.appBroadcast.emit(BroadcastConstants.THIRD_ROUTE_PAGE, []); 687 this.broadCast.emit(BroadcastConstants.CHANGE_SWIPER_DURATION, [400]); 688 let params = router.getParams(); 689 if (params != null && params.pageType != null && this.backFromCopy) { 690 Log.debug(TAG, `MediaOperation back ${JSON.stringify(params)}`) 691 let menuContext = new MenuContext(); 692 let menuOperation: MenuOperation; 693 let currentPhoto = this.getCurrentPhoto(); 694 if (currentPhoto == undefined) { 695 Log.warn(TAG, 'MediaOperation currentPhoto is undefined'); 696 return; 697 } 698 switch (params.pageType) { 699 case MediaOperationType.Move: 700 this.onMoveEnd = this.onMoveEnd.bind(this); 701 menuContext.withItems([currentPhoto]) 702 .withBroadCast(this.broadCast) 703 .withAlbumInfo(JSON.parse(params.albumInfo ? params.albumInfo.toString() : '')) 704 .withOperationEndCallback(this.onMoveEnd); 705 menuOperation = new MoveMenuOperation(menuContext); 706 break; 707 case MediaOperationType.Copy: 708 this.onCopyEnd = this.onCopyEnd.bind(this); 709 menuContext.withItems([currentPhoto]) 710 .withBroadCast(this.broadCast) 711 .withAlbumInfo(JSON.parse(params.albumInfo ? params.albumInfo.toString() : '')) 712 .withOperationEndCallback(this.onCopyEnd); 713 menuOperation = new CopyMenuOperation(menuContext); 714 break; 715 } 716 menuOperation.doAction(); 717 } 718 this.backFromCopy = false; 719 finishTrace('PhotoBrowserOnPageShow'); 720 } 721 722 private downLoad() { 723 Log.info(TAG, 'downLoad run'); 724 let menuContext = new MenuContext(); 725 let menuOperation: MenuOperation; 726 let currentPhoto = this.getCurrentPhoto(); 727 this.onDownloadEnd = this.onDownloadEnd.bind(this); 728 if (currentPhoto == undefined) { 729 Log.warn(TAG, 'MediaOperation currentPhoto is undefined'); 730 return; 731 } 732 menuContext.withItems([currentPhoto]) 733 .withBroadCast(this.broadCast) 734 .withRemoteDevice(this.albumInfo.deviceId) 735 .withOperationEndCallback(this.onDownloadEnd) 736 menuOperation = new CopyMenuOperation(menuContext); 737 menuOperation.doAction(); 738 } 739 740 onPageHide() { 741 this.showBars(); 742 } 743 744 onMediaLibDataChange(changeType) { 745 Log.info(TAG, `onMediaLibDataChange type: ${changeType}`); 746 if (!PhotoEditorManager.getInstance().isSaving) { 747 this.dataSourceLoadFinish(); 748 } 749 } 750 751 async routerGridPaged() { 752 AppStorage.SetOrCreate(Constants.BACK_FROM_FORM_DETAIL, true); 753 let displayName = await getAlbumDisplayName(MediaConstants.ALBUM_ID_CAMERA) 754 let item: SimpleAlbumDataItem = new SimpleAlbumDataItem(MediaConstants.ALBUM_ID_CAMERA, displayName, "", "", "") 755 Log.info(TAG, `item.displayName: ${item.displayName} item ${JSON.stringify(item)}`); 756 router.replace({ 757 uri: 'feature/photoGrid/view/PhotoGridPage', 758 params: { 759 item: JSON.stringify(item) 760 } 761 }); 762 } 763 764 build() { 765 Stack({ alignContent: Alignment.TopStart }) { 766 PhotoBrowserBg() 767 if (!this.isDataChanged || !this.isFromCard == true) { 768 PhotoSwiper({ 769 dataSource: this.browserDataSource, 770 photoSwiperTransition: this.photoBrowserTransition, 771 swiperController: this.controller, 772 onPhotoChanged: this.onPhotoChanged.bind(this) 773 }) 774 } 775 if (!this.isFromViewData) { 776 if (this.isShowBar) { 777 PhotoBrowserActionBar({ 778 onMenuClicked: this.onMenuClicked, 779 }) 780 ToolBar({ 781 toolMenuList: $toolMenuList, 782 onMenuClicked: this.onMenuClicked, 783 isFromPhotoBrowser: true 784 }) 785 } 786 CustomDialogView() 787 } else { 788 Column() { 789 if (this.isShowBar) { 790 PhotoBrowserActionBar({ 791 onMenuClicked: (action) => this.onMenuClicked(action) 792 }) 793 } 794 Text(`${this.currentIndex + 1}/${this.browserDataSource.totalCount()}`) 795 .height($r('app.float.menu_height')) 796 .fontColor($r('app.color.text_color_secondary')) 797 .fontSize($r('sys.float.ohos_id_text_size_body1')) 798 .markAnchor({ x: '0%', y: '0%' }) 799 .position({ 800 x: '0%', 801 y: screenManager.getStatusBarHeight() + Constants.ActionBarHeight 802 }) 803 }.alignItems(HorizontalAlign.Start) 804 } 805 } 806 } 807 808 pageTransition() { 809 PageTransitionEnter({ type: RouteType.None, duration: PhotoConstants.PAGE_SHOW_ANIMATION_DURATION }) 810 .opacity(0) 811 PageTransitionExit({ duration: PhotoConstants.PAGE_SHOW_ANIMATION_DURATION }) 812 .opacity(0) 813 } 814}