100aff185Sopenharmony_ci/**
200aff185Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
300aff185Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
400aff185Sopenharmony_ci * you may not use this file except in compliance with the License.
500aff185Sopenharmony_ci * You may obtain a copy of the License at
600aff185Sopenharmony_ci *
700aff185Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
800aff185Sopenharmony_ci *
900aff185Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1000aff185Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1100aff185Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1200aff185Sopenharmony_ci * See the License for the specific language governing permissions and
1300aff185Sopenharmony_ci * limitations under the License.
1400aff185Sopenharmony_ci */
1500aff185Sopenharmony_ci
1600aff185Sopenharmony_ciimport Curves from '@ohos.curves';
1700aff185Sopenharmony_ciimport { MenuOperation, WindowUtil } from '@ohos/common';
1800aff185Sopenharmony_ciimport {
1900aff185Sopenharmony_ci  Action,
2000aff185Sopenharmony_ci  AddMenuOperation,
2100aff185Sopenharmony_ci  BatchDeleteMenuOperation,
2200aff185Sopenharmony_ci  BroadCast,
2300aff185Sopenharmony_ci  BroadCastConstants,
2400aff185Sopenharmony_ci  BroadCastManager,
2500aff185Sopenharmony_ci  Constants,
2600aff185Sopenharmony_ci  DateUtil,
2700aff185Sopenharmony_ci  DeleteMenuOperation,
2800aff185Sopenharmony_ci  Log,
2900aff185Sopenharmony_ci  MediaItem,
3000aff185Sopenharmony_ci  MediaOperationType,
3100aff185Sopenharmony_ci  MenuContext,
3200aff185Sopenharmony_ci  MenuOperationFactory,
3300aff185Sopenharmony_ci  ScreenManager,
3400aff185Sopenharmony_ci  ShareMenuOperation,
3500aff185Sopenharmony_ci  TimelineData,
3600aff185Sopenharmony_ci  TimelineSelectManager,
3700aff185Sopenharmony_ci  TraceControllerUtils,
3800aff185Sopenharmony_ci  UiUtil,
3900aff185Sopenharmony_ci  ViewData,
4000aff185Sopenharmony_ci  ViewType
4100aff185Sopenharmony_ci} from '@ohos/common';
4200aff185Sopenharmony_ciimport {
4300aff185Sopenharmony_ci  BrowserController,
4400aff185Sopenharmony_ci  CustomDialogView,
4500aff185Sopenharmony_ci  ImageGridItemComponent,
4600aff185Sopenharmony_ci  NoPhotoIndexComponent,
4700aff185Sopenharmony_ci} from '@ohos/common/CommonComponents';
4800aff185Sopenharmony_ciimport { TimelineDataSource } from '../model/TimelineDataSource';
4900aff185Sopenharmony_ciimport { TimelineTitleComponent } from './TimelineTitleComponent';
5000aff185Sopenharmony_ciimport { TimelinePageActionBar } from './TimelinePageActionBar';
5100aff185Sopenharmony_ciimport { TimelinePageToolBar } from './TimelinePageToolBar';
5200aff185Sopenharmony_ciimport router from '@ohos.router';
5300aff185Sopenharmony_ciimport { TimelineDataSourceManager } from '../model/TimelineDataSourceManager';
5400aff185Sopenharmony_ciimport { TimelineScrollBar } from './TimelineScrollBar';
5500aff185Sopenharmony_ci
5600aff185Sopenharmony_ciconst TAG: string = 'TimelinePage';
5700aff185Sopenharmony_ciAppStorage.setOrCreate('timelinePageIndex', Constants.INVALID);
5800aff185Sopenharmony_ci
5900aff185Sopenharmony_ciinterface Params {
6000aff185Sopenharmony_ci  albumName: string;
6100aff185Sopenharmony_ci  albumUri: string;
6200aff185Sopenharmony_ci  pageType: string;
6300aff185Sopenharmony_ci  pageFrom: number;
6400aff185Sopenharmony_ci};
6500aff185Sopenharmony_ci
6600aff185Sopenharmony_ci// PHOTO Page
6700aff185Sopenharmony_ci@Component
6800aff185Sopenharmony_ciexport struct TimelinePage {
6900aff185Sopenharmony_ci  @Provide isEmpty: boolean = false;
7000aff185Sopenharmony_ci  @State isShowScrollBar: boolean = false;
7100aff185Sopenharmony_ci  @StorageLink('isHorizontal') isHorizontal: boolean = ScreenManager.getInstance().isHorizontal();
7200aff185Sopenharmony_ci  @State gridRowCount: number = 0;
7300aff185Sopenharmony_ci  @Consume @Watch('updateRightClickMenuList') isSelectedMode: boolean;
7400aff185Sopenharmony_ci  @Consume('isShowSideBar') @Watch('initGridRowCount') isSidebar: boolean;
7500aff185Sopenharmony_ci  @Provide isAllSelected: boolean = false;
7600aff185Sopenharmony_ci  @State totalSelectedCount: number = 0;
7700aff185Sopenharmony_ci  @Provide broadCast: BroadCast = TimelineDataSourceManager.getInstance().getBroadCast();
7800aff185Sopenharmony_ci  @Consume @Watch('onIndexPageShow') isShow: boolean;
7900aff185Sopenharmony_ci  @StorageLink('timelinePageIndex') @Watch('onIndexChange') timelinePageIndex: number = Constants.INVALID;
8000aff185Sopenharmony_ci  @StorageLink('isSplitMode') isSplitMode: boolean = ScreenManager.getInstance().isSplitMode();
8100aff185Sopenharmony_ci  @StorageLink('leftBlank') leftBlank: number[] =
8200aff185Sopenharmony_ci    [0, ScreenManager.getInstance().getStatusBarHeight(), 0, ScreenManager.getInstance().getNaviBarHeight()];
8300aff185Sopenharmony_ci  dataSource: TimelineDataSource | null = null;
8400aff185Sopenharmony_ci  mSelectManager: TimelineSelectManager = new TimelineSelectManager();
8500aff185Sopenharmony_ci  scroller: Scroller = new Scroller();
8600aff185Sopenharmony_ci  appBroadCast: BroadCast = BroadCastManager.getInstance().getBroadCast();
8700aff185Sopenharmony_ci  isInCurrentTab = true; // Is it on the current tab page
8800aff185Sopenharmony_ci  isDataFreeze = false; // Is the page data frozen
8900aff185Sopenharmony_ci  deleteMode = false; // Is delete mode
9000aff185Sopenharmony_ci  isActive = false; // Is the page active
9100aff185Sopenharmony_ci  routerStart = false; // Is move or copy router page
9200aff185Sopenharmony_ci  @Provide moreMenuList: Action[] = [];
9300aff185Sopenharmony_ci  @Provide rightClickMenuList: Action[] = [];
9400aff185Sopenharmony_ci  @State groupSelectMode: boolean[] = [];
9500aff185Sopenharmony_ci  @Provide yearData: TimelineData[] = [];
9600aff185Sopenharmony_ci  @Provide dateText: string = '';
9700aff185Sopenharmony_ci  @Provide isShowBar: boolean = true;
9800aff185Sopenharmony_ci  @StorageLink('placeholderIndex') @Watch('onPlaceholderChanged') placeholderIndex: number = -1;
9900aff185Sopenharmony_ci  @ObjectLink browserController: BrowserController;
10000aff185Sopenharmony_ci  @Provide hidePopup: boolean = false;
10100aff185Sopenharmony_ci  // 选择模式下,鼠标对着未勾选项按右键弹框时,移动和复制菜单点击事件的标识位
10200aff185Sopenharmony_ci  private isMvOrCpSeparatesItem: boolean = false;
10300aff185Sopenharmony_ci  private mvOrCpSeparatesItem?: MediaItem;
10400aff185Sopenharmony_ci  private onWindowSizeChangeCallBack: Function = (): void => this.initGridRowCount();
10500aff185Sopenharmony_ci  private backPressEventFunc: Function = (callback: Function): void => this.onIndexBackPress(callback);
10600aff185Sopenharmony_ci  private onTableChangedFunc: Function = (index: number): void => this.onTabChanged(index);
10700aff185Sopenharmony_ci  private resetStateEventFunc: Function = (index: number): void => this.onStateReset(index);
10800aff185Sopenharmony_ci  private updateDataSourceFunc: Function = (item: MediaItem): void => this.onUpdateFavorState(item);
10900aff185Sopenharmony_ci  private resetZeroFunc: Function = (pageNumber: number): void => this.resetZero(pageNumber);
11000aff185Sopenharmony_ci  private onLoadingFinishedFunc: Function = (size: number): void => this.onLoadingFinished(size);
11100aff185Sopenharmony_ci  private selectFunc: Function = (index: number, id: string, isSelected: boolean, callback?: Function): void =>
11200aff185Sopenharmony_ci  this.select(index, id, isSelected, callback);
11300aff185Sopenharmony_ci  private groupSelectFunc: Function = (position: number): void => this.groupSelect(position);
11400aff185Sopenharmony_ci  private jumpPhotoBrowserFunc: Function = (name: string, item: MediaItem,
11500aff185Sopenharmony_ci                                            geometryTapIndex: number, geometryTransitionString: string): void =>
11600aff185Sopenharmony_ci  this.jumpPhotoBrowser(name, item, geometryTapIndex, geometryTransitionString);
11700aff185Sopenharmony_ci  private jumpThirdPhotoBrowserFunc: Function = (name: string, item: MediaItem,
11800aff185Sopenharmony_ci                                                 geometryTapIndex: number, geometryTransitionString: string): void =>
11900aff185Sopenharmony_ci  this.jumpThirdPhotoBrowser(name, item, geometryTapIndex, geometryTransitionString);
12000aff185Sopenharmony_ci  private onDataReloadedFunc: Function = (): void => this.onDataReloaded();
12100aff185Sopenharmony_ci  private initDateTextFunc: Function = (): void => this.initDateText();
12200aff185Sopenharmony_ci  @State layoutOptions: GridLayoutOptions = {
12300aff185Sopenharmony_ci    regularSize: [1, 1],
12400aff185Sopenharmony_ci    irregularIndexes: [],
12500aff185Sopenharmony_ci  }
12600aff185Sopenharmony_ci
12700aff185Sopenharmony_ci  onPlaceholderChanged() {
12800aff185Sopenharmony_ci    Log.debug(TAG, 'onPlaceholderChanged placeholderIndex is ' + this.placeholderIndex);
12900aff185Sopenharmony_ci    if (this.placeholderIndex != -1) {
13000aff185Sopenharmony_ci      this.scroller.scrollToIndex(this.placeholderIndex);
13100aff185Sopenharmony_ci    }
13200aff185Sopenharmony_ci  }
13300aff185Sopenharmony_ci
13400aff185Sopenharmony_ci  aboutToAppear(): void {
13500aff185Sopenharmony_ci    TraceControllerUtils.startTrace('TimelinePageAboutToAppear');
13600aff185Sopenharmony_ci    Log.info(TAG, 'aboutToAppear begin');
13700aff185Sopenharmony_ci    let self = this;
13800aff185Sopenharmony_ci    this.dataSource = TimelineDataSourceManager.getInstance().getDataSource();
13900aff185Sopenharmony_ci    let params: Params = router.getParams() as Params;
14000aff185Sopenharmony_ci    if (params != null && params.pageFrom && params.pageFrom == Constants.ENTRY_FROM.CAMERA) {
14100aff185Sopenharmony_ci      this.dataSource.initData();
14200aff185Sopenharmony_ci    }
14300aff185Sopenharmony_ci    this.mSelectManager.setGroupData(this.dataSource.getGroupData());
14400aff185Sopenharmony_ci    this.mSelectManager.setTotalCount(this.dataSource.getMediaCount());
14500aff185Sopenharmony_ci    this.moreMenuList = [Action.ADD, Action.INFO];
14600aff185Sopenharmony_ci    this.updateRightClickMenuList();
14700aff185Sopenharmony_ci    this.dataSource.registerCallback('updateGroupData', (newState: TimelineData[]) => {
14800aff185Sopenharmony_ci      self.mSelectManager.updateGroupData(newState);
14900aff185Sopenharmony_ci      self.updateYearMap();
15000aff185Sopenharmony_ci      self.updateLayoutOptions(newState);
15100aff185Sopenharmony_ci    });
15200aff185Sopenharmony_ci    this.dataSource.registerCallback('updateCount', (newState: number) => {
15300aff185Sopenharmony_ci      Log.info(TAG, `updateCount ${newState}`);
15400aff185Sopenharmony_ci      self.isEmpty = !Boolean(newState);
15500aff185Sopenharmony_ci      self.isShowScrollBar = (newState > Constants.PHOTOS_CNT_FOR_HIDE_SCROLL_BAR);
15600aff185Sopenharmony_ci      self.mSelectManager.setTotalCount(newState);
15700aff185Sopenharmony_ci    });
15800aff185Sopenharmony_ci
15900aff185Sopenharmony_ci    // 后续phone缩略图支持横竖屏后再放开
16000aff185Sopenharmony_ci    if (AppStorage.Get('deviceType') as string !== Constants.DEFAULT_DEVICE_TYPE) {
16100aff185Sopenharmony_ci      ScreenManager.getInstance().on(ScreenManager.ON_WIN_SIZE_CHANGED, this.onWindowSizeChangeCallBack);
16200aff185Sopenharmony_ci    }
16300aff185Sopenharmony_ci
16400aff185Sopenharmony_ci    this.appBroadCast.on(BroadCastConstants.BACK_PRESS_EVENT, this.backPressEventFunc);
16500aff185Sopenharmony_ci    this.appBroadCast.on(BroadCastConstants.ON_TAB_CHANGED, this.onTableChangedFunc);
16600aff185Sopenharmony_ci    this.appBroadCast.on(BroadCastConstants.RESET_STATE_EVENT, this.resetStateEventFunc);
16700aff185Sopenharmony_ci    this.appBroadCast.on(BroadCastConstants.UPDATE_DATA_SOURCE, this.updateDataSourceFunc);
16800aff185Sopenharmony_ci    this.appBroadCast.on(BroadCastConstants.RESET_ZERO, this.resetZeroFunc);
16900aff185Sopenharmony_ci    this.broadCast.on(Constants.ON_LOADING_FINISHED, this.onLoadingFinishedFunc);
17000aff185Sopenharmony_ci
17100aff185Sopenharmony_ci    Log.info(TAG, 'aboutToAppear doing');
17200aff185Sopenharmony_ci    this.mSelectManager.setPhotoDataImpl();
17300aff185Sopenharmony_ci
17400aff185Sopenharmony_ci    this.broadCast.on(BroadCastConstants.SELECT, this.selectFunc);
17500aff185Sopenharmony_ci    this.broadCast.on(BroadCastConstants.GROUP_SELECT, this.groupSelectFunc);
17600aff185Sopenharmony_ci    this.broadCast.on(BroadCastConstants.JUMP_PHOTO_BROWSER, this.jumpPhotoBrowserFunc);
17700aff185Sopenharmony_ci    this.broadCast.on(BroadCastConstants.JUMP_THIRD_PHOTO_BROWSER, this.jumpThirdPhotoBrowserFunc);
17800aff185Sopenharmony_ci    this.broadCast.on(BroadCastConstants.ON_DATA_RELOADED, this.onDataReloadedFunc);
17900aff185Sopenharmony_ci    this.broadCast.on(BroadCastConstants.INIT_DATE_TEXT, this.initDateTextFunc);
18000aff185Sopenharmony_ci
18100aff185Sopenharmony_ci    this.mSelectManager.registerCallback('allSelect', (newState: boolean) => {
18200aff185Sopenharmony_ci      Log.info(TAG, `allSelect ${newState}`);
18300aff185Sopenharmony_ci      if (this.isDataFreeze) {
18400aff185Sopenharmony_ci        return;
18500aff185Sopenharmony_ci      }
18600aff185Sopenharmony_ci      this.isAllSelected = newState;
18700aff185Sopenharmony_ci      if (this.dataSource != null) {
18800aff185Sopenharmony_ci          this.dataSource.forceUpdate();
18900aff185Sopenharmony_ci      }
19000aff185Sopenharmony_ci    });
19100aff185Sopenharmony_ci
19200aff185Sopenharmony_ci    this.mSelectManager.registerCallback('updateGroupCount', () => {
19300aff185Sopenharmony_ci      Log.info(TAG, 'updateGroupCount');
19400aff185Sopenharmony_ci      if (this.isDataFreeze) {
19500aff185Sopenharmony_ci        return;
19600aff185Sopenharmony_ci      }
19700aff185Sopenharmony_ci      this.updateGroupSelectMode();
19800aff185Sopenharmony_ci    });
19900aff185Sopenharmony_ci
20000aff185Sopenharmony_ci    this.mSelectManager.registerCallback('updateCount', (newState: number) => {
20100aff185Sopenharmony_ci      Log.info(TAG, `mSelectManager updateCount ${newState}`);
20200aff185Sopenharmony_ci      if (this.isDataFreeze) {
20300aff185Sopenharmony_ci        return;
20400aff185Sopenharmony_ci      }
20500aff185Sopenharmony_ci      this.totalSelectedCount = newState;
20600aff185Sopenharmony_ci      this.moreMenuList = Boolean(newState) ? [Action.ADD, Action.INFO]
20700aff185Sopenharmony_ci        : [Action.ADD_INVALID, Action.INFO_INVALID];
20800aff185Sopenharmony_ci    });
20900aff185Sopenharmony_ci    this.initGridRowCount();
21000aff185Sopenharmony_ci    this.updateGroupSelectMode();
21100aff185Sopenharmony_ci    this.updateYearMap();
21200aff185Sopenharmony_ci    this.onActive();
21300aff185Sopenharmony_ci    this.updateLayoutOptions(this.dataSource.groups);
21400aff185Sopenharmony_ci    TraceControllerUtils.finishTrace('TimelinePageAboutToAppear');
21500aff185Sopenharmony_ci  }
21600aff185Sopenharmony_ci
21700aff185Sopenharmony_ci  updateLayoutOptions(groups: TimelineData[]): void {
21800aff185Sopenharmony_ci    this.layoutOptions.irregularIndexes && this.layoutOptions.irregularIndexes.pop();
21900aff185Sopenharmony_ci    let currentTitleIndex = 0;
22000aff185Sopenharmony_ci    let count: number[] = [];
22100aff185Sopenharmony_ci    count.push(currentTitleIndex);
22200aff185Sopenharmony_ci    for (let index = 0; index < groups.length - 1; index++) {
22300aff185Sopenharmony_ci      currentTitleIndex = currentTitleIndex + groups[index].count + 1;
22400aff185Sopenharmony_ci      count.push(currentTitleIndex);
22500aff185Sopenharmony_ci    }
22600aff185Sopenharmony_ci    this.layoutOptions = {
22700aff185Sopenharmony_ci      regularSize: [1, 1],
22800aff185Sopenharmony_ci      irregularIndexes: count,
22900aff185Sopenharmony_ci    };
23000aff185Sopenharmony_ci  }
23100aff185Sopenharmony_ci
23200aff185Sopenharmony_ci  private onLoadingFinished(size: number): void {
23300aff185Sopenharmony_ci    Log.info(TAG, `ON_LOADING_FINISHED size: ${size}`);
23400aff185Sopenharmony_ci  }
23500aff185Sopenharmony_ci
23600aff185Sopenharmony_ci  private select(index: number, id: string, isSelected: boolean, callback?: Function): void {
23700aff185Sopenharmony_ci    if (this.mSelectManager.toggle(id, isSelected, index)) {
23800aff185Sopenharmony_ci      if (!this.isSelectedMode) {
23900aff185Sopenharmony_ci        this.isSelectedMode = true;
24000aff185Sopenharmony_ci      }
24100aff185Sopenharmony_ci    }
24200aff185Sopenharmony_ci    if (callback) {
24300aff185Sopenharmony_ci      callback();
24400aff185Sopenharmony_ci    }
24500aff185Sopenharmony_ci  }
24600aff185Sopenharmony_ci
24700aff185Sopenharmony_ci  private groupSelect(position: number): void {
24800aff185Sopenharmony_ci    Log.info(TAG, `GROUP_SELECT ${position}`);
24900aff185Sopenharmony_ci    if (this.mSelectManager.toggleGroup(this.mSelectManager.getTitleCoordinate(position))) {
25000aff185Sopenharmony_ci      this.totalSelectedCount = this.mSelectManager.getSelectedCount();
25100aff185Sopenharmony_ci    }
25200aff185Sopenharmony_ci  }
25300aff185Sopenharmony_ci
25400aff185Sopenharmony_ci  private jumpPhotoBrowser(name: string, item: MediaItem,
25500aff185Sopenharmony_ci                           geometryTapIndex: number, geometryTransitionString: string): void {
25600aff185Sopenharmony_ci    let targetIndex = this.dataSource == null ? Constants.NOT_FOUND : this.dataSource.getDataIndex(item);
25700aff185Sopenharmony_ci    if (targetIndex == Constants.NOT_FOUND) {
25800aff185Sopenharmony_ci      Log.error(TAG, 'targetIndex is not found');
25900aff185Sopenharmony_ci      return;
26000aff185Sopenharmony_ci    }
26100aff185Sopenharmony_ci    AppStorage.setOrCreate(Constants.APP_KEY_PHOTO_BROWSER, this.dataSource);
26200aff185Sopenharmony_ci    if (geometryTapIndex !== undefined && geometryTransitionString !== undefined) {
26300aff185Sopenharmony_ci      this.jumpToPhotoBrowserGeometryTransition(targetIndex, name, item, geometryTapIndex, geometryTransitionString);
26400aff185Sopenharmony_ci    } else {
26500aff185Sopenharmony_ci      this.jumpToPhotoBrowserNormal(targetIndex, name, item);
26600aff185Sopenharmony_ci    }
26700aff185Sopenharmony_ci  }
26800aff185Sopenharmony_ci
26900aff185Sopenharmony_ci  private jumpThirdPhotoBrowser(name: string, item: MediaItem,
27000aff185Sopenharmony_ci                                geometryTapIndex: number, geometryTransitionString: string): void {
27100aff185Sopenharmony_ci    let targetIndex = this.dataSource == null ? Constants.NOT_FOUND : this.dataSource.getDataIndex(item);
27200aff185Sopenharmony_ci    if (targetIndex == Constants.NOT_FOUND) {
27300aff185Sopenharmony_ci      Log.error(TAG, 'targetIndex is not found');
27400aff185Sopenharmony_ci      return;
27500aff185Sopenharmony_ci    }
27600aff185Sopenharmony_ci    Log.info(TAG, `JUMP_THIRD_PHOTO_BROWSER.index: ${targetIndex} transition: ${name}`);
27700aff185Sopenharmony_ci    AppStorage.setOrCreate(Constants.PHOTO_GRID_SELECT_MANAGER, this.mSelectManager);
27800aff185Sopenharmony_ci    AppStorage.setOrCreate(Constants.APP_KEY_PHOTO_BROWSER, this.dataSource);
27900aff185Sopenharmony_ci    if (geometryTapIndex !== undefined && geometryTransitionString !== undefined) {
28000aff185Sopenharmony_ci      this.jumpToSelectPhotoBrowserGeometryTransition(
28100aff185Sopenharmony_ci        targetIndex, name, item, geometryTapIndex, geometryTransitionString);
28200aff185Sopenharmony_ci    } else {
28300aff185Sopenharmony_ci      this.jumpToSelectPhotoBrowserNormal(targetIndex, name, item);
28400aff185Sopenharmony_ci    }
28500aff185Sopenharmony_ci  }
28600aff185Sopenharmony_ci
28700aff185Sopenharmony_ci  private onDataReloaded(): void {
28800aff185Sopenharmony_ci    Log.info(TAG, 'ON_DATA_RELOADED');
28900aff185Sopenharmony_ci    if (this.deleteMode) {
29000aff185Sopenharmony_ci      animateTo({
29100aff185Sopenharmony_ci        duration: 300, // 删除动画时长
29200aff185Sopenharmony_ci        curve: Curves.cubicBezier(0.0, 0.0, 0.2, 1.0) // 减速曲线参数
29300aff185Sopenharmony_ci      }, (): void => {
29400aff185Sopenharmony_ci        this.dataSource?.onDataReloaded();
29500aff185Sopenharmony_ci      })
29600aff185Sopenharmony_ci      this.deleteMode = false;
29700aff185Sopenharmony_ci    } else {
29800aff185Sopenharmony_ci      if (this.dataSource != null) {
29900aff185Sopenharmony_ci          this.dataSource.onDataReloaded();
30000aff185Sopenharmony_ci      }
30100aff185Sopenharmony_ci    }
30200aff185Sopenharmony_ci  }
30300aff185Sopenharmony_ci
30400aff185Sopenharmony_ci  private initDateText(): void {
30500aff185Sopenharmony_ci    let scrollMediaItem: MediaItem = this.dataSource == null ? new MediaItem() :
30600aff185Sopenharmony_ci      this.dataSource.getMediaItemByPosition(0) as MediaItem;
30700aff185Sopenharmony_ci    this.dateText = DateUtil.getLocalizedYearAndMonth(scrollMediaItem.getDataTaken());
30800aff185Sopenharmony_ci  }
30900aff185Sopenharmony_ci
31000aff185Sopenharmony_ci  jumpToPhotoBrowserNormal(targetIndex: number, name: string, item: MediaItem) {
31100aff185Sopenharmony_ci    router.pushUrl({
31200aff185Sopenharmony_ci      url: 'pages/PhotoBrowser',
31300aff185Sopenharmony_ci      params: {
31400aff185Sopenharmony_ci        position: targetIndex,
31500aff185Sopenharmony_ci        transition: name,
31600aff185Sopenharmony_ci        leftBlank: this.leftBlank,
31700aff185Sopenharmony_ci      }
31800aff185Sopenharmony_ci    });
31900aff185Sopenharmony_ci  }
32000aff185Sopenharmony_ci
32100aff185Sopenharmony_ci  jumpToPhotoBrowserGeometryTransition(targetIndex: number, name: string, item: MediaItem, geometryTapIndex: number,
32200aff185Sopenharmony_ci                                       geometryTransitionString: string) {
32300aff185Sopenharmony_ci    interface Msg {
32400aff185Sopenharmony_ci      position: number;
32500aff185Sopenharmony_ci      transition: string;
32600aff185Sopenharmony_ci      leftBlank: number[];
32700aff185Sopenharmony_ci    }
32800aff185Sopenharmony_ci
32900aff185Sopenharmony_ci    const params: Msg = {
33000aff185Sopenharmony_ci      position: targetIndex,
33100aff185Sopenharmony_ci      transition: name,
33200aff185Sopenharmony_ci      leftBlank: this.leftBlank,
33300aff185Sopenharmony_ci    };
33400aff185Sopenharmony_ci    this.browserController.showBrowser(geometryTapIndex, geometryTransitionString, TAG, params);
33500aff185Sopenharmony_ci  }
33600aff185Sopenharmony_ci
33700aff185Sopenharmony_ci  jumpToSelectPhotoBrowserNormal(targetIndex: number, name: string, item: MediaItem) {
33800aff185Sopenharmony_ci    router.pushUrl({
33900aff185Sopenharmony_ci      url: 'pages/SelectPhotoBrowser',
34000aff185Sopenharmony_ci      params: {
34100aff185Sopenharmony_ci        position: targetIndex,
34200aff185Sopenharmony_ci        transition: name,
34300aff185Sopenharmony_ci      }
34400aff185Sopenharmony_ci    });
34500aff185Sopenharmony_ci  }
34600aff185Sopenharmony_ci
34700aff185Sopenharmony_ci  jumpToSelectPhotoBrowserGeometryTransition(targetIndex: number, name: string, item: MediaItem,
34800aff185Sopenharmony_ci                                             geometryTapIndex: number, geometryTransitionString: string) {
34900aff185Sopenharmony_ci    interface Params {
35000aff185Sopenharmony_ci      position: number;
35100aff185Sopenharmony_ci      transition: string;
35200aff185Sopenharmony_ci      leftBlank: number[];
35300aff185Sopenharmony_ci    }
35400aff185Sopenharmony_ci
35500aff185Sopenharmony_ci    const params: Params = {
35600aff185Sopenharmony_ci      position: targetIndex,
35700aff185Sopenharmony_ci      transition: name,
35800aff185Sopenharmony_ci      leftBlank: this.leftBlank,
35900aff185Sopenharmony_ci    };
36000aff185Sopenharmony_ci    this.browserController.showSelectBrowser(geometryTapIndex, geometryTransitionString, TAG, params);
36100aff185Sopenharmony_ci  }
36200aff185Sopenharmony_ci
36300aff185Sopenharmony_ci  onPageShow() {
36400aff185Sopenharmony_ci  }
36500aff185Sopenharmony_ci
36600aff185Sopenharmony_ci  aboutToDisappear(): void {
36700aff185Sopenharmony_ci    Log.debug(TAG, 'aboutToDisappear');
36800aff185Sopenharmony_ci    ScreenManager.getInstance().off(ScreenManager.ON_WIN_SIZE_CHANGED, this.onWindowSizeChangeCallBack);
36900aff185Sopenharmony_ci    this.dataSource?.unregisterCallback('updateGroupData');
37000aff185Sopenharmony_ci    this.dataSource?.unregisterCallback('updateCount');
37100aff185Sopenharmony_ci    if (this.appBroadCast != null) {
37200aff185Sopenharmony_ci      this.appBroadCast.off(BroadCastConstants.BACK_PRESS_EVENT, this.backPressEventFunc);
37300aff185Sopenharmony_ci      this.appBroadCast.off(BroadCastConstants.ON_TAB_CHANGED, this.onTableChangedFunc);
37400aff185Sopenharmony_ci      this.appBroadCast.off(BroadCastConstants.RESET_STATE_EVENT, this.resetStateEventFunc);
37500aff185Sopenharmony_ci      this.appBroadCast.off(BroadCastConstants.UPDATE_DATA_SOURCE, this.updateDataSourceFunc);
37600aff185Sopenharmony_ci      this.appBroadCast.off(BroadCastConstants.RESET_ZERO, this.resetZeroFunc);
37700aff185Sopenharmony_ci    }
37800aff185Sopenharmony_ci    if (this.broadCast != null) {
37900aff185Sopenharmony_ci      this.broadCast.off(Constants.ON_LOADING_FINISHED, this.onLoadingFinishedFunc);
38000aff185Sopenharmony_ci      this.broadCast.off(BroadCastConstants.SELECT, this.selectFunc);
38100aff185Sopenharmony_ci      this.broadCast.off(BroadCastConstants.GROUP_SELECT, this.groupSelectFunc);
38200aff185Sopenharmony_ci      this.broadCast.off(BroadCastConstants.JUMP_PHOTO_BROWSER, this.jumpPhotoBrowserFunc);
38300aff185Sopenharmony_ci      this.broadCast.off(BroadCastConstants.JUMP_THIRD_PHOTO_BROWSER, this.jumpThirdPhotoBrowserFunc);
38400aff185Sopenharmony_ci      this.broadCast.off(BroadCastConstants.ON_DATA_RELOADED, this.onDataReloadedFunc);
38500aff185Sopenharmony_ci      this.broadCast.off(BroadCastConstants.INIT_DATE_TEXT, this.initDateTextFunc);
38600aff185Sopenharmony_ci    }
38700aff185Sopenharmony_ci  }
38800aff185Sopenharmony_ci
38900aff185Sopenharmony_ci  updateGroupSelectMode(): void {
39000aff185Sopenharmony_ci    let groups: TimelineData[] = this.dataSource == null ? [] : this.dataSource.groups;
39100aff185Sopenharmony_ci    if (this.groupSelectMode.length == 0) {
39200aff185Sopenharmony_ci      Log.info(TAG, 'first updateGroupSelectMode');
39300aff185Sopenharmony_ci      for (let i = 0; i < groups.length; i++) {
39400aff185Sopenharmony_ci        this.groupSelectMode.push(this.mSelectManager.isGroupSelected(i));
39500aff185Sopenharmony_ci      }
39600aff185Sopenharmony_ci    } else {
39700aff185Sopenharmony_ci      Log.info(TAG, 'no first updateGroupSelectMode');
39800aff185Sopenharmony_ci      for (let i = 0; i < groups.length; i++) {
39900aff185Sopenharmony_ci        Log.info(TAG, 'update one');
40000aff185Sopenharmony_ci        this.groupSelectMode[i] = this.mSelectManager.isGroupSelected(i);
40100aff185Sopenharmony_ci      }
40200aff185Sopenharmony_ci    }
40300aff185Sopenharmony_ci  }
40400aff185Sopenharmony_ci
40500aff185Sopenharmony_ci  updateRightClickMenuList() {
40600aff185Sopenharmony_ci    this.rightClickMenuList = this.isSelectedMode
40700aff185Sopenharmony_ci      ? [Action.DELETE, Action.ADD, Action.INFO]
40800aff185Sopenharmony_ci      : [Action.MULTISELECT, Action.DELETE, Action.ADD, Action.INFO];
40900aff185Sopenharmony_ci  }
41000aff185Sopenharmony_ci
41100aff185Sopenharmony_ci  updateYearMap(): void {
41200aff185Sopenharmony_ci    Log.info(TAG, 'updateYearMap');
41300aff185Sopenharmony_ci    let groups: TimelineData[] = this.dataSource == null ? [] : this.dataSource.groups;
41400aff185Sopenharmony_ci    if (groups.length == 0) {
41500aff185Sopenharmony_ci      Log.error(TAG, 'year length is 0');
41600aff185Sopenharmony_ci      return;
41700aff185Sopenharmony_ci    }
41800aff185Sopenharmony_ci    this.yearData = [];
41900aff185Sopenharmony_ci
42000aff185Sopenharmony_ci    let startGroup: TimelineData = groups[0];
42100aff185Sopenharmony_ci    let count: number = startGroup.count as number;
42200aff185Sopenharmony_ci    let startTime: number = startGroup.startDate as number;
42300aff185Sopenharmony_ci    let endTime: number = startGroup.startDate as number;
42400aff185Sopenharmony_ci
42500aff185Sopenharmony_ci    for (let i = 1; i < groups.length; i++) {
42600aff185Sopenharmony_ci      let dateTaken: number = groups[i].startDate as number;
42700aff185Sopenharmony_ci      if (DateUtil.isTheSameYear(startTime, dateTaken)) {
42800aff185Sopenharmony_ci        count = count + groups[i].count as number;
42900aff185Sopenharmony_ci        endTime = dateTaken;
43000aff185Sopenharmony_ci      } else {
43100aff185Sopenharmony_ci        let groupData = new TimelineData(startTime, endTime, count);
43200aff185Sopenharmony_ci        this.yearData.push(groupData);
43300aff185Sopenharmony_ci        count = groups[i].count as number;
43400aff185Sopenharmony_ci        startTime = dateTaken;
43500aff185Sopenharmony_ci        endTime = dateTaken;
43600aff185Sopenharmony_ci      }
43700aff185Sopenharmony_ci    }
43800aff185Sopenharmony_ci    let groupData = new TimelineData(startTime, endTime, count);
43900aff185Sopenharmony_ci    this.yearData.push(groupData);
44000aff185Sopenharmony_ci    Log.info(TAG, 'updateYearMap end');
44100aff185Sopenharmony_ci  }
44200aff185Sopenharmony_ci
44300aff185Sopenharmony_ci  onIndexChange(): void {
44400aff185Sopenharmony_ci    Log.info(TAG, `onIndexChange ${this.timelinePageIndex}`);
44500aff185Sopenharmony_ci    if (this.timelinePageIndex != Constants.INVALID && this.dataSource != null) {
44600aff185Sopenharmony_ci      this.scroller.scrollToIndex(this.dataSource.getPositionByIndex(this.timelinePageIndex));
44700aff185Sopenharmony_ci    }
44800aff185Sopenharmony_ci  }
44900aff185Sopenharmony_ci
45000aff185Sopenharmony_ci  onIndexBackPress(callback: Function): void {
45100aff185Sopenharmony_ci    if (this.isInCurrentTab) {
45200aff185Sopenharmony_ci      callback(this.onModeChange());
45300aff185Sopenharmony_ci    }
45400aff185Sopenharmony_ci  }
45500aff185Sopenharmony_ci
45600aff185Sopenharmony_ci  onTabChanged(index: number): void {
45700aff185Sopenharmony_ci    if (index == Constants.TIMELINE_PAGE_INDEX) {
45800aff185Sopenharmony_ci      this.isInCurrentTab = true;
45900aff185Sopenharmony_ci      this.onActive();
46000aff185Sopenharmony_ci    } else {
46100aff185Sopenharmony_ci      this.isInCurrentTab = false;
46200aff185Sopenharmony_ci      this.onModeChange();
46300aff185Sopenharmony_ci      this.onInActive();
46400aff185Sopenharmony_ci    }
46500aff185Sopenharmony_ci  }
46600aff185Sopenharmony_ci
46700aff185Sopenharmony_ci  onStateReset(index: number): void {
46800aff185Sopenharmony_ci    if (index == Constants.TIMELINE_PAGE_INDEX) {
46900aff185Sopenharmony_ci      this.onModeChange();
47000aff185Sopenharmony_ci    }
47100aff185Sopenharmony_ci  }
47200aff185Sopenharmony_ci
47300aff185Sopenharmony_ci  resetZero(pageNumber: number): void {
47400aff185Sopenharmony_ci    if (pageNumber == Constants.TIMELINE_PAGE_INDEX) {
47500aff185Sopenharmony_ci      this.scroller.scrollEdge(Edge.Top);
47600aff185Sopenharmony_ci    }
47700aff185Sopenharmony_ci  }
47800aff185Sopenharmony_ci
47900aff185Sopenharmony_ci  onMenuClicked(action: Action): void {
48000aff185Sopenharmony_ci    Log.info(TAG, `onMenuClicked, actionID: ${action.actionID}`);
48100aff185Sopenharmony_ci    let menuContext: MenuContext;
48200aff185Sopenharmony_ci    let menuOperation: MenuOperation;
48300aff185Sopenharmony_ci    if (action === Action.CANCEL) {
48400aff185Sopenharmony_ci      this.onModeChange();
48500aff185Sopenharmony_ci    } else if (action === Action.MULTISELECT) {
48600aff185Sopenharmony_ci      this.isSelectedMode = true;
48700aff185Sopenharmony_ci    } else if (action === Action.SELECT_ALL) {
48800aff185Sopenharmony_ci      this.mSelectManager.selectAll(true);
48900aff185Sopenharmony_ci    } else if (action === Action.DESELECT_ALL) {
49000aff185Sopenharmony_ci      this.mSelectManager.deSelectAll();
49100aff185Sopenharmony_ci    } else if (action === Action.DELETE) {
49200aff185Sopenharmony_ci      menuContext = new MenuContext();
49300aff185Sopenharmony_ci      menuContext
49400aff185Sopenharmony_ci        .withSelectManager(this.mSelectManager)
49500aff185Sopenharmony_ci        .withFromSelectMode(this.isSelectedMode)
49600aff185Sopenharmony_ci        .withOperationStartCallback((): void => this.onDeleteStart())
49700aff185Sopenharmony_ci        .withOperationEndCallback((): void => this.onDeleteEnd())
49800aff185Sopenharmony_ci        .withBroadCast(this.broadCast);
49900aff185Sopenharmony_ci      menuOperation = MenuOperationFactory.getInstance()
50000aff185Sopenharmony_ci        .createMenuOperation(BatchDeleteMenuOperation, menuContext);
50100aff185Sopenharmony_ci      menuOperation.doAction();
50200aff185Sopenharmony_ci    } else if (action === Action.SHARE) {
50300aff185Sopenharmony_ci      menuContext = new MenuContext();
50400aff185Sopenharmony_ci      menuContext.withFromSelectMode(true).withSelectManager(this.mSelectManager);
50500aff185Sopenharmony_ci      menuOperation = MenuOperationFactory.getInstance()
50600aff185Sopenharmony_ci        .createMenuOperation(ShareMenuOperation, menuContext);
50700aff185Sopenharmony_ci      menuOperation.doAction();
50800aff185Sopenharmony_ci    } else if (action === Action.INFO) {
50900aff185Sopenharmony_ci      this.hidePopup = true;
51000aff185Sopenharmony_ci      this.openDetailsDialog();
51100aff185Sopenharmony_ci    } else if (action === Action.ADD) {
51200aff185Sopenharmony_ci      this.mSelectManager.getSelectedItems((selectedItems: Array<MediaItem>) => {
51300aff185Sopenharmony_ci        Log.info(TAG, `Get selected items success, size: ${selectedItems.length}`);
51400aff185Sopenharmony_ci        this.routeToSelectAlbumPage(MediaOperationType.Add, selectedItems);
51500aff185Sopenharmony_ci      })
51600aff185Sopenharmony_ci    }
51700aff185Sopenharmony_ci  }
51800aff185Sopenharmony_ci
51900aff185Sopenharmony_ci  routeToSelectAlbumPage(pageType: string, selectedItems: Array<MediaItem>): void {
52000aff185Sopenharmony_ci    Log.info(TAG, 'Route to select album page');
52100aff185Sopenharmony_ci    router.pushUrl({
52200aff185Sopenharmony_ci      url: 'pages/MediaOperationPage',
52300aff185Sopenharmony_ci      params: {
52400aff185Sopenharmony_ci        pageFrom: Constants.MEDIA_OPERATION_FROM_TIMELINE,
52500aff185Sopenharmony_ci        pageType: pageType,
52600aff185Sopenharmony_ci        selectedItems: selectedItems
52700aff185Sopenharmony_ci      }
52800aff185Sopenharmony_ci    });
52900aff185Sopenharmony_ci    this.routerStart = true;
53000aff185Sopenharmony_ci  }
53100aff185Sopenharmony_ci
53200aff185Sopenharmony_ci  async openDetailsDialog(): Promise<void> {
53300aff185Sopenharmony_ci    if (this.totalSelectedCount == 0) {
53400aff185Sopenharmony_ci      Log.error(TAG, 'no select error');
53500aff185Sopenharmony_ci      return;
53600aff185Sopenharmony_ci    } else if (this.totalSelectedCount == 1) {
53700aff185Sopenharmony_ci      Log.info(TAG, 'totalSelectedCount is 1');
53800aff185Sopenharmony_ci      await this.mSelectManager.getSelectedItems((selectItems: MediaItem[]) => {
53900aff185Sopenharmony_ci        Log.info(TAG, `openDetailsDialog selectItems.length: ${selectItems.length}`);
54000aff185Sopenharmony_ci        if (selectItems.length != 1) {
54100aff185Sopenharmony_ci          Log.error(TAG, 'get selectItems is error');
54200aff185Sopenharmony_ci          return;
54300aff185Sopenharmony_ci        }
54400aff185Sopenharmony_ci        this.broadCast.emit(BroadCastConstants.SHOW_DETAIL_DIALOG, [selectItems[0], false]);
54500aff185Sopenharmony_ci      });
54600aff185Sopenharmony_ci    } else {
54700aff185Sopenharmony_ci      await this.mSelectManager.getSelectedItems((selectItems: MediaItem[]) => {
54800aff185Sopenharmony_ci        Log.info(TAG, `openDetailsDialog selectItems.length: ${selectItems.length}`);
54900aff185Sopenharmony_ci        if (selectItems.length <= 1) {
55000aff185Sopenharmony_ci          Log.error(TAG, 'get selectItems is error');
55100aff185Sopenharmony_ci          return;
55200aff185Sopenharmony_ci        }
55300aff185Sopenharmony_ci        let size = 0;
55400aff185Sopenharmony_ci        selectItems.forEach((item) => {
55500aff185Sopenharmony_ci          Log.info(TAG, `openDetailsDialog item.size: ${item.size}`);
55600aff185Sopenharmony_ci          size = size + item.size;
55700aff185Sopenharmony_ci        })
55800aff185Sopenharmony_ci
55900aff185Sopenharmony_ci        Log.info(TAG, `openDetailsDialog size: ${size}`);
56000aff185Sopenharmony_ci        this.broadCast.emit(BroadCastConstants.SHOW_MULTI_SELECT_DIALOG, [this.totalSelectedCount, size]);
56100aff185Sopenharmony_ci      });
56200aff185Sopenharmony_ci      return;
56300aff185Sopenharmony_ci    }
56400aff185Sopenharmony_ci  }
56500aff185Sopenharmony_ci
56600aff185Sopenharmony_ci  onDeleteStart(): void {
56700aff185Sopenharmony_ci    Log.info(TAG, `onDeleteStart`);
56800aff185Sopenharmony_ci    this.deleteMode = true;
56900aff185Sopenharmony_ci    this.isDataFreeze = true;
57000aff185Sopenharmony_ci    if (this.dataSource != null) {
57100aff185Sopenharmony_ci      this.dataSource.unregisterTimelineObserver();
57200aff185Sopenharmony_ci      this.dataSource.freeze();
57300aff185Sopenharmony_ci    }
57400aff185Sopenharmony_ci  }
57500aff185Sopenharmony_ci
57600aff185Sopenharmony_ci  onDeleteEnd(): void {
57700aff185Sopenharmony_ci    Log.info(TAG, `onDeleteEnd`);
57800aff185Sopenharmony_ci    this.isDataFreeze = false;
57900aff185Sopenharmony_ci    this.onModeChange();
58000aff185Sopenharmony_ci    if (this.dataSource != null) {
58100aff185Sopenharmony_ci      this.dataSource.registerTimelineObserver();
58200aff185Sopenharmony_ci      this.dataSource.onChange('image');
58300aff185Sopenharmony_ci      this.dataSource.unfreeze();
58400aff185Sopenharmony_ci    }
58500aff185Sopenharmony_ci  }
58600aff185Sopenharmony_ci
58700aff185Sopenharmony_ci  onCopyStart(): void {
58800aff185Sopenharmony_ci    Log.info(TAG, `onCopyStart`);
58900aff185Sopenharmony_ci    this.isDataFreeze = true;
59000aff185Sopenharmony_ci    if (this.dataSource != null) {
59100aff185Sopenharmony_ci      this.dataSource.unregisterTimelineObserver();
59200aff185Sopenharmony_ci      this.dataSource.freeze();
59300aff185Sopenharmony_ci    }
59400aff185Sopenharmony_ci
59500aff185Sopenharmony_ci  }
59600aff185Sopenharmony_ci
59700aff185Sopenharmony_ci  onCopyEnd(err: Object, count: number, total: number): void {
59800aff185Sopenharmony_ci    Log.info(TAG, `onCopyEnd count: ${count}, total: ${total}`);
59900aff185Sopenharmony_ci    this.isDataFreeze = false;
60000aff185Sopenharmony_ci    this.onModeChange();
60100aff185Sopenharmony_ci    if (this.dataSource != null) {
60200aff185Sopenharmony_ci      this.dataSource.registerTimelineObserver();
60300aff185Sopenharmony_ci      this.dataSource.onChange('image');
60400aff185Sopenharmony_ci      this.dataSource.unfreeze();
60500aff185Sopenharmony_ci    }
60600aff185Sopenharmony_ci    if (err) {
60700aff185Sopenharmony_ci      UiUtil.showToast($r('app.string.copy_failed_single'));
60800aff185Sopenharmony_ci    }
60900aff185Sopenharmony_ci  }
61000aff185Sopenharmony_ci
61100aff185Sopenharmony_ci  onMoveStart(): void {
61200aff185Sopenharmony_ci    Log.info(TAG, `onMoveStart`);
61300aff185Sopenharmony_ci    this.isDataFreeze = true;
61400aff185Sopenharmony_ci    if (this.dataSource != null) {
61500aff185Sopenharmony_ci      this.dataSource.unregisterTimelineObserver();
61600aff185Sopenharmony_ci      this.dataSource.freeze();
61700aff185Sopenharmony_ci    }
61800aff185Sopenharmony_ci  }
61900aff185Sopenharmony_ci
62000aff185Sopenharmony_ci  onMoveEnd(err: Object, count: number, total: number): void {
62100aff185Sopenharmony_ci    Log.info(TAG, `onMoveEnd count: ${count}, total: ${total}`);
62200aff185Sopenharmony_ci    this.isDataFreeze = false;
62300aff185Sopenharmony_ci    this.onModeChange();
62400aff185Sopenharmony_ci    if (this.dataSource != null) {
62500aff185Sopenharmony_ci      this.dataSource.registerTimelineObserver();
62600aff185Sopenharmony_ci      this.dataSource.unfreeze();
62700aff185Sopenharmony_ci      this.dataSource.switchRefreshOn();
62800aff185Sopenharmony_ci      this.dataSource.onChange('image');
62900aff185Sopenharmony_ci    }
63000aff185Sopenharmony_ci    if (err) {
63100aff185Sopenharmony_ci      UiUtil.showToast($r('app.string.move_failed_single'));
63200aff185Sopenharmony_ci    }
63300aff185Sopenharmony_ci  }
63400aff185Sopenharmony_ci
63500aff185Sopenharmony_ci  onModeChange() {
63600aff185Sopenharmony_ci    Log.debug(TAG, `onModeChange current mode ${this.isSelectedMode}`);
63700aff185Sopenharmony_ci    if (this.isSelectedMode) {
63800aff185Sopenharmony_ci      this.isSelectedMode = false;
63900aff185Sopenharmony_ci      this.isAllSelected = false;
64000aff185Sopenharmony_ci      this.mSelectManager.onModeChange(false);
64100aff185Sopenharmony_ci      this.updateGroupSelectMode();
64200aff185Sopenharmony_ci      AppStorage.delete(Constants.PHOTO_GRID_SELECT_MANAGER);
64300aff185Sopenharmony_ci      return true;
64400aff185Sopenharmony_ci    }
64500aff185Sopenharmony_ci    return false;
64600aff185Sopenharmony_ci  }
64700aff185Sopenharmony_ci
64800aff185Sopenharmony_ci  // The callbacks after index page shows
64900aff185Sopenharmony_ci  onIndexPageShow() {
65000aff185Sopenharmony_ci    Log.info(TAG, `[onIndexPageShow] isShow=${this.isShow}, isInCurrentTab=${this.isInCurrentTab}`);
65100aff185Sopenharmony_ci    if (this.isShow && this.isInCurrentTab) {
65200aff185Sopenharmony_ci      let params: Params = router.getParams() as Params;
65300aff185Sopenharmony_ci      if (this.routerStart && params != null && params.pageType != null) {
65400aff185Sopenharmony_ci        Log.info(TAG, `MediaOperation back ${JSON.stringify(params)}`)
65500aff185Sopenharmony_ci        if (params.pageType === MediaOperationType.Add) {
65600aff185Sopenharmony_ci          this.addOperation(params.albumName, params.albumUri);
65700aff185Sopenharmony_ci        }
65800aff185Sopenharmony_ci      }
65900aff185Sopenharmony_ci      this.routerStart = false;
66000aff185Sopenharmony_ci      this.onActive();
66100aff185Sopenharmony_ci    } else if (!this.isShow && this.isInCurrentTab) {
66200aff185Sopenharmony_ci      this.onInActive();
66300aff185Sopenharmony_ci    } else {
66400aff185Sopenharmony_ci    }
66500aff185Sopenharmony_ci  }
66600aff185Sopenharmony_ci
66700aff185Sopenharmony_ci  // The callback when current page is in the foreground
66800aff185Sopenharmony_ci  onActive() {
66900aff185Sopenharmony_ci    if (!this.isActive) {
67000aff185Sopenharmony_ci      Log.info(TAG, 'onActive');
67100aff185Sopenharmony_ci      this.isActive = true;
67200aff185Sopenharmony_ci
67300aff185Sopenharmony_ci      this.dataSource?.onActive();
67400aff185Sopenharmony_ci      if (this.isSelectedMode) {
67500aff185Sopenharmony_ci        this.totalSelectedCount = this.mSelectManager.getSelectedCount();
67600aff185Sopenharmony_ci        this.dataSource?.forceUpdate();
67700aff185Sopenharmony_ci      }
67800aff185Sopenharmony_ci    }
67900aff185Sopenharmony_ci  }
68000aff185Sopenharmony_ci
68100aff185Sopenharmony_ci  // The callback when current page is in the background
68200aff185Sopenharmony_ci  onInActive() {
68300aff185Sopenharmony_ci    if (this.isActive) {
68400aff185Sopenharmony_ci      Log.info(TAG, 'onInActive');
68500aff185Sopenharmony_ci      this.isActive = false;
68600aff185Sopenharmony_ci      this.dataSource?.onInActive();
68700aff185Sopenharmony_ci    }
68800aff185Sopenharmony_ci  }
68900aff185Sopenharmony_ci
69000aff185Sopenharmony_ci  getGeometryTransitionId(item: ViewData, index: number): string {
69100aff185Sopenharmony_ci    let mediaItem = item.mediaItem as MediaItem;
69200aff185Sopenharmony_ci    if (mediaItem) {
69300aff185Sopenharmony_ci      return TAG + mediaItem.getHashCode() + this.mSelectManager.isItemSelected(mediaItem.uri, item.viewIndex);
69400aff185Sopenharmony_ci    } else {
69500aff185Sopenharmony_ci      return TAG + item.viewIndex;
69600aff185Sopenharmony_ci    }
69700aff185Sopenharmony_ci  }
69800aff185Sopenharmony_ci
69900aff185Sopenharmony_ci  build() {
70000aff185Sopenharmony_ci    Stack() {
70100aff185Sopenharmony_ci      Column() {
70200aff185Sopenharmony_ci        if (this.isEmpty) {
70300aff185Sopenharmony_ci          NoPhotoIndexComponent({ index: Constants.TIMELINE_PAGE_INDEX, hasBarSpace: true })
70400aff185Sopenharmony_ci        } else {
70500aff185Sopenharmony_ci          TimelinePageActionBar({
70600aff185Sopenharmony_ci            onMenuClicked: (action: Action): void => this.onMenuClicked(action),
70700aff185Sopenharmony_ci            totalSelectedCount: $totalSelectedCount
70800aff185Sopenharmony_ci          });
70900aff185Sopenharmony_ci
71000aff185Sopenharmony_ci          Stack() {
71100aff185Sopenharmony_ci            Grid(this.scroller, this.layoutOptions) {
71200aff185Sopenharmony_ci              LazyForEach(this.dataSource as TimelineDataSource, (item: ViewData, index?: number) => {
71300aff185Sopenharmony_ci                if (!!item) {
71400aff185Sopenharmony_ci                  if (item.viewType == ViewType.GROUP_TITLE) {
71500aff185Sopenharmony_ci                    GridItem() {
71600aff185Sopenharmony_ci                      TimelineTitleComponent({
71700aff185Sopenharmony_ci                        groupData: item.viewData,
71800aff185Sopenharmony_ci                        mPosition: item.viewIndex,
71900aff185Sopenharmony_ci                        isSelected: this.groupSelectMode[item.viewIndex]
72000aff185Sopenharmony_ci                      })
72100aff185Sopenharmony_ci                    }
72200aff185Sopenharmony_ci                    .key('TimelinePage_GridItem' + index)
72300aff185Sopenharmony_ci                  } else if (item.viewType == ViewType.ITEM) {
72400aff185Sopenharmony_ci                    GridItem() {
72500aff185Sopenharmony_ci                      ImageGridItemComponent({
72600aff185Sopenharmony_ci                        dataSource: this.dataSource,
72700aff185Sopenharmony_ci                        item: item.mediaItem,
72800aff185Sopenharmony_ci                        mPosition: item.viewIndex,
72900aff185Sopenharmony_ci                        isSelected: this.isSelectedMode ?
73000aff185Sopenharmony_ci                        this.mSelectManager.isItemSelected((item.mediaItem as MediaItem).uri as string,
73100aff185Sopenharmony_ci                          item.viewIndex) : false,
73200aff185Sopenharmony_ci                        pageName: Constants.PHOTO_TRANSITION_TIMELINE,
73300aff185Sopenharmony_ci                        onMenuClicked: (action: Action): void => this.onMenuClicked(action),
73400aff185Sopenharmony_ci                        onMenuClickedForSingleItem: (action: Action, currentPhoto: MediaItem): void =>
73500aff185Sopenharmony_ci                        this.onMenuClickedForSingleItem(action, currentPhoto),
73600aff185Sopenharmony_ci                        geometryTransitionString: this.getGeometryTransitionId(item, index as number),
73700aff185Sopenharmony_ci                        selectedCount: $totalSelectedCount
73800aff185Sopenharmony_ci                      })
73900aff185Sopenharmony_ci                    }
74000aff185Sopenharmony_ci                    .aspectRatio(1)
74100aff185Sopenharmony_ci                    .key('TimelinePage_GridItem' + index)
74200aff185Sopenharmony_ci                    .zIndex(index === this.placeholderIndex ? 1 : 0)
74300aff185Sopenharmony_ci                  }
74400aff185Sopenharmony_ci                }
74500aff185Sopenharmony_ci              }, (item: ViewData, index?: number) => {
74600aff185Sopenharmony_ci                if (item == null || item == undefined) {
74700aff185Sopenharmony_ci                  return (JSON.stringify(item) + index) as string;
74800aff185Sopenharmony_ci                }
74900aff185Sopenharmony_ci                if (item.viewType == ViewType.GROUP_TITLE) {
75000aff185Sopenharmony_ci                  return (JSON.stringify(item.viewData) + this.groupSelectMode[item.viewIndex]) as string;
75100aff185Sopenharmony_ci                } else {
75200aff185Sopenharmony_ci                  return this.getGeometryTransitionId(item, index as number) as string;
75300aff185Sopenharmony_ci                }
75400aff185Sopenharmony_ci              })
75500aff185Sopenharmony_ci            }
75600aff185Sopenharmony_ci            .edgeEffect(EdgeEffect.Spring)
75700aff185Sopenharmony_ci            .columnsTemplate('1fr '.repeat(this.gridRowCount))
75800aff185Sopenharmony_ci            .scrollBar(BarState.Off)
75900aff185Sopenharmony_ci            .columnsGap(Constants.GRID_GUTTER)
76000aff185Sopenharmony_ci            .rowsGap(Constants.GRID_GUTTER)
76100aff185Sopenharmony_ci            .cachedCount(Constants.GRID_CACHE_ROW_COUNT)
76200aff185Sopenharmony_ci            .onScrollIndex((first) => {
76300aff185Sopenharmony_ci              let scrollMediaItem: MediaItem | null = this.dataSource == null ?
76400aff185Sopenharmony_ci                null : this.dataSource.getMediaItemByPosition(first) as MediaItem;
76500aff185Sopenharmony_ci              if (scrollMediaItem?.getDataTaken()) {
76600aff185Sopenharmony_ci                this.dateText = DateUtil.getLocalizedYearAndMonth(scrollMediaItem.getDataTaken());
76700aff185Sopenharmony_ci                Log.debug(TAG, `scrollIndex=${first}, dateTaken=${scrollMediaItem.getDataTaken()}`);
76800aff185Sopenharmony_ci              } else {
76900aff185Sopenharmony_ci                Log.warn(TAG, `scrollIndex ${first} out of active window`);
77000aff185Sopenharmony_ci              }
77100aff185Sopenharmony_ci            })
77200aff185Sopenharmony_ci
77300aff185Sopenharmony_ci            if (this.isShowScrollBar) {
77400aff185Sopenharmony_ci              TimelineScrollBar({ scroller: this.scroller })
77500aff185Sopenharmony_ci            }
77600aff185Sopenharmony_ci          }
77700aff185Sopenharmony_ci          .layoutWeight(1)
77800aff185Sopenharmony_ci        }
77900aff185Sopenharmony_ci      }
78000aff185Sopenharmony_ci      .alignItems(HorizontalAlign.Start)
78100aff185Sopenharmony_ci      .justifyContent(FlexAlign.Start)
78200aff185Sopenharmony_ci      .margin({
78300aff185Sopenharmony_ci        bottom: this.isHorizontal ? 0 : $r('app.float.tab_bar_vertical_height')
78400aff185Sopenharmony_ci      })
78500aff185Sopenharmony_ci
78600aff185Sopenharmony_ci      if (this.isSelectedMode) {
78700aff185Sopenharmony_ci        TimelinePageToolBar({
78800aff185Sopenharmony_ci          onMenuClicked: (action: Action): void => this.onMenuClicked(action),
78900aff185Sopenharmony_ci          totalSelectedCount: $totalSelectedCount
79000aff185Sopenharmony_ci        })
79100aff185Sopenharmony_ci      }
79200aff185Sopenharmony_ci      CustomDialogView({ broadCast: $broadCast })
79300aff185Sopenharmony_ci    }
79400aff185Sopenharmony_ci  }
79500aff185Sopenharmony_ci
79600aff185Sopenharmony_ci  private onMenuClickedForSingleItem(action: Action, currentPhoto: MediaItem) {
79700aff185Sopenharmony_ci    Log.info(TAG, `single menu click, action: ${action?.actionID}, currentUri: ${currentPhoto?.uri}`);
79800aff185Sopenharmony_ci    if (currentPhoto == undefined) {
79900aff185Sopenharmony_ci      return;
80000aff185Sopenharmony_ci    }
80100aff185Sopenharmony_ci    let menuOperation: MenuOperation;
80200aff185Sopenharmony_ci    let menuContext: MenuContext;
80300aff185Sopenharmony_ci    if (action === Action.DELETE) {
80400aff185Sopenharmony_ci      menuContext = new MenuContext();
80500aff185Sopenharmony_ci      menuContext.withMediaItem(currentPhoto).withBroadCast(this.broadCast);
80600aff185Sopenharmony_ci      menuOperation = MenuOperationFactory.getInstance()
80700aff185Sopenharmony_ci        .createMenuOperation(DeleteMenuOperation, menuContext);
80800aff185Sopenharmony_ci      menuOperation.doAction();
80900aff185Sopenharmony_ci    } else if (action === Action.ADD) {
81000aff185Sopenharmony_ci      this.isMvOrCpSeparatesItem = true;
81100aff185Sopenharmony_ci      this.mvOrCpSeparatesItem = currentPhoto;
81200aff185Sopenharmony_ci      this.routeToSelectAlbumPage(MediaOperationType.Add, [currentPhoto]);
81300aff185Sopenharmony_ci    } else if (action === Action.INFO) {
81400aff185Sopenharmony_ci      this.broadCast.emit(BroadCastConstants.SHOW_DETAIL_DIALOG, [currentPhoto, false]);
81500aff185Sopenharmony_ci    }
81600aff185Sopenharmony_ci  }
81700aff185Sopenharmony_ci
81800aff185Sopenharmony_ci  // Calculate the number of squares per row
81900aff185Sopenharmony_ci  private initGridRowCount(): void {
82000aff185Sopenharmony_ci    let sideBarWidth = this.isSidebar ? Constants.TAB_BAR_WIDTH : 0;
82100aff185Sopenharmony_ci    let contentWidth = ScreenManager.getInstance().getWinWidth() - sideBarWidth;
82200aff185Sopenharmony_ci    let margin = 0;
82300aff185Sopenharmony_ci    let maxThumbWidth = px2vp(Constants.GRID_IMAGE_SIZE) * Constants.GRID_MAX_SIZE_RATIO;
82400aff185Sopenharmony_ci    let newCount = Math.max(Constants.GRID_MIN_COUNT,
82500aff185Sopenharmony_ci      Math.round(((contentWidth - Constants.NUMBER_2 * margin) +
82600aff185Sopenharmony_ci      Constants.GRID_GUTTER) / (maxThumbWidth + Constants.GRID_GUTTER)));
82700aff185Sopenharmony_ci    if (newCount != this.gridRowCount) {
82800aff185Sopenharmony_ci      this.gridRowCount = newCount;
82900aff185Sopenharmony_ci    }
83000aff185Sopenharmony_ci    Log.info(TAG, `initGridRowCount contentWidth: ${contentWidth}`);
83100aff185Sopenharmony_ci  }
83200aff185Sopenharmony_ci
83300aff185Sopenharmony_ci  private async addOperation(albumName: string, albumUri: string) {
83400aff185Sopenharmony_ci    let menuContext = new MenuContext();
83500aff185Sopenharmony_ci    let onCopyStartFunc = (): void => this.onCopyStart();
83600aff185Sopenharmony_ci    if (this.isMvOrCpSeparatesItem) {
83700aff185Sopenharmony_ci      menuContext.withMediaItem(this.mvOrCpSeparatesItem as MediaItem);
83800aff185Sopenharmony_ci      this.onCopyStart && this.onCopyStart();
83900aff185Sopenharmony_ci      this.isMvOrCpSeparatesItem = false;
84000aff185Sopenharmony_ci      this.mvOrCpSeparatesItem = undefined;
84100aff185Sopenharmony_ci    } else {
84200aff185Sopenharmony_ci      menuContext.withSelectManager(this.mSelectManager).withOperationStartCallback(onCopyStartFunc);
84300aff185Sopenharmony_ci    }
84400aff185Sopenharmony_ci    menuContext.withOperationEndCallback((err: Object, count: number, total: number): void =>
84500aff185Sopenharmony_ci    this.onCopyEnd(err as Object, count, total))
84600aff185Sopenharmony_ci      .withBroadCast(this.broadCast)
84700aff185Sopenharmony_ci      .withTargetAlbumName(albumName).withAlbumUri(albumUri);
84800aff185Sopenharmony_ci    let menuOperation = MenuOperationFactory.getInstance().createMenuOperation(AddMenuOperation, menuContext);
84900aff185Sopenharmony_ci    menuOperation.doAction();
85000aff185Sopenharmony_ci  }
85100aff185Sopenharmony_ci
85200aff185Sopenharmony_ci  private onUpdateFavorState(item: MediaItem): void {
85300aff185Sopenharmony_ci    Log.debug(TAG, 'onUpdateFavorState favor');
85400aff185Sopenharmony_ci    if (this.dataSource != null) {
85500aff185Sopenharmony_ci      let index = this.dataSource.getIndexByMediaItem(item);
85600aff185Sopenharmony_ci      if (index == Constants.NOT_FOUND) {
85700aff185Sopenharmony_ci          return;
85800aff185Sopenharmony_ci      }
85900aff185Sopenharmony_ci      let flushIndex = this.dataSource.getPositionByIndex(index);
86000aff185Sopenharmony_ci      Log.debug(TAG, `onUpdateFavorState favor flushIndex ${flushIndex}`);
86100aff185Sopenharmony_ci      this.dataSource.onDataChanged(flushIndex);
86200aff185Sopenharmony_ci    }
86300aff185Sopenharmony_ci  }
86400aff185Sopenharmony_ci}
865