1/* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import Matrix4 from '@ohos.matrix4'; 17import { PhotoItem } from './PhotoItem'; 18import { BroadCastConstants } from '../model/common/BroadCastConstants'; 19import { Log } from '../utils/Log'; 20import { BroadCast } from '../utils/BroadCast'; 21import Curves from '@ohos.curves'; 22import { Constants } from '../model/common/Constants'; 23import { Constants as BrowserConstants } from '../model/browser/photo/Constants'; 24import { PhotoDataSource } from '../model/browser/photo/PhotoDataSource'; 25import { MediaItem } from '../model/browser/photo/MediaItem'; 26 27const TAG: string = 'common_PhotoSwiper'; 28 29export interface Results { 30 data: MediaItem; 31 pos: number; 32 thumbnail: string; 33}; 34 35@Component 36export struct PhotoSwiper { 37 mTransition: string = ''; 38 @Consume currentIndex: number; 39 @Link broadCast: BroadCast; 40 @State mDuration: number = 300; 41 onPhotoChanged: Function = (): void => {}; 42 swiperController?: SwiperController; 43 isInSelectedMode: boolean = false; 44 @Consume canSwipe: boolean; 45 swiperItemSpace: number = Constants.NUMBER_8; 46 verifyPhotoScaledFunc: (matrix?: Matrix4.Matrix4Transit) => void = (matrix?: Matrix4.Matrix4Transit): void => {} 47 @Link isRunningAnimation: boolean; 48 isLeftSwiper: boolean = false; 49 @Consume isDeleting: boolean; 50 @State isOnSwiperAnimation: boolean = false; 51 private dataSource?: PhotoDataSource; 52 private geometryTransitionEnable: boolean = false; 53 private isFromFACard: boolean = false; 54 private SWIPE_CACHE_COUNT: number = 2; 55 private onDataReloadFunc: Function = (addCount: number): void => this.onDataReload(addCount); 56 private onChangeSwiperDurationFunc: Function = (value: number): void => this.onChangeSwiperDuration(value); 57 58 private onDataReload(addCount: number): void { 59 let totalCount = this.dataSource == null ? 0 : this.dataSource.totalCount(); 60 let add = addCount; 61 if (add > Constants.NUMBER_0) { 62 if (this.dataSource != null) { 63 this.dataSource.onDataReloaded(); 64 } 65 if (this.currentIndex + add < totalCount) { 66 this.currentIndex += add; 67 } 68 Log.info(TAG, `ON_DATA_RELOADED: ${this.currentIndex}, ${add}`); 69 return; 70 } 71 Log.debug(TAG, 'animate to data reloaded start'); 72 animateTo({ 73 duration: 300, // 删除动画时长 74 curve: Curves.cubicBezier(0.0, 0.0, 0.2, 1.0), // 减速曲线参数 75 onFinish: () => { 76 if (this.dataSource != null) { 77 let totalCount = this.dataSource.totalCount(); 78 this.dataSource.onDataChanged(this.currentIndex); 79 // UPDATE NEXT TWO DATA FOR AVOID NOT LOADING DATA 80 if (this.currentIndex + 1 < totalCount) { 81 this.dataSource.onDataChanged(this.currentIndex + 1); 82 } 83 if (this.currentIndex + 2 < totalCount) { 84 this.dataSource.onDataChanged(this.currentIndex + 2); 85 } 86 this.dataSource.onDataReloaded(); 87 } 88 } }, () => { 89 if (this.dataSource != null && this.isDeleting) { 90 this.dataSource.deleteData(this.currentIndex); 91 } 92 if (this.dataSource != null && this.currentIndex === this.dataSource.totalCount() || 93 (this.isDeleting && this.isLeftSwiper && this.currentIndex > 0)) { 94 this.currentIndex--; 95 } 96 this.isDeleting = false; 97 }) 98 } 99 100 private onChangeSwiperDuration(value: number): void { 101 Log.debug(TAG, `change duration start ${value}`); 102 this.mDuration = value; 103 } 104 105 aboutToAppear() { 106 this.broadCast.on(BroadCastConstants.ON_DATA_RELOADED, this.onDataReloadFunc); 107 this.broadCast.on(BroadCastConstants.CHANGE_SWIPER_DURATION, this.onChangeSwiperDurationFunc); 108 } 109 110 aboutToDisappear(): void { 111 this.swiperController = undefined; 112 this.broadCast.off(BroadCastConstants.ON_DATA_RELOADED, this.onDataReloadFunc); 113 this.broadCast.off(BroadCastConstants.CHANGE_SWIPER_DURATION, this.onChangeSwiperDurationFunc); 114 } 115 116 build() { 117 Swiper(this.swiperController) { 118 LazyForEach(this.dataSource as PhotoDataSource, (item: Results, index?: number) => { 119 if (!!item) { 120 Column() { 121 PhotoItem({ 122 item: item.data, 123 mPosition: item.pos, 124 thumbnail: item.thumbnail, 125 transitionTag: this.mTransition ? this.mTransition : 'default_id', 126 verifyPhotoScaled: this.verifyPhotoScaledFunc, 127 albumUri: (this.dataSource == null ? '' : this.dataSource.getAlbumUri()), 128 geometryTransitionEnable: this.geometryTransitionEnable, 129 broadCast: $broadCast, 130 isRunningAnimation: $isRunningAnimation, 131 isFromFACard: this.isFromFACard, 132 isInSelectedMode: this.isInSelectedMode, 133 isOnSwiperAnimation: $isOnSwiperAnimation, 134 dataSource: this.dataSource 135 }) 136 }.zIndex(item.pos == this.currentIndex ? 2 : 1) 137 } 138 }, (item: Results, index?: number) => { 139 if (item == null || item == undefined) { 140 return JSON.stringify(item) + index; 141 } 142 return `${item.data.path}_${item.data.size}_${item.data.orientation}_${index}`; 143 }) 144 } 145 .cachedCount(this.SWIPE_CACHE_COUNT) 146 .duration(BrowserConstants.PHOTO_SWIPE_DURATION) 147 .itemSpace(this.swiperItemSpace) 148 .onGestureSwipe(() => { 149 if (!this.isOnSwiperAnimation) { 150 this.isOnSwiperAnimation = true; 151 } 152 }) 153 .index(this.currentIndex) 154 .indicator(false) 155 .loop(false) 156 .onChange((index: number) => { 157 if (this.currentIndex - index == 1) { 158 this.isLeftSwiper = true; 159 } else if (this.currentIndex - index == -1) { 160 this.isLeftSwiper = false; 161 } 162 if (this.mDuration != 0) { 163 this.onPhotoChanged(index); 164 165 if (!!this.verifyPhotoScaledFunc) { 166 this.verifyPhotoScaledFunc(undefined) 167 } 168 } 169 }) 170 .disableSwipe(this.canSwipe) 171 .onAnimationStart((index: number) => { 172 this.isOnSwiperAnimation = true; 173 }) 174 .onAnimationEnd(() => { 175 this.isOnSwiperAnimation = false; 176 }) 177 } 178}