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 { Log } from '@ohos/base/src/main/ets/utils/Log'; 18import { ImageGridItemComponent } from '@ohos/base/src/main/ets/components/ImageGridItemComponent'; 19import { Action } from '../../../common/view/browserOperation/Action'; 20import { ActionBar } from '../../../common/view/actionbar/ActionBar'; 21import { ActionBarProp } from '../../../common/view/browserOperation/ActionBarProp'; 22import { Broadcast } from '@ohos/base/src/main/ets/utils/Broadcast'; 23import { BroadcastConstants } from '@ohos/base/src/main/ets/constants/BroadcastConstants'; 24import { Constants } from '../../../common/model/common/Constants'; 25import { NoPhotoComponent } from '../../../common/view/NoPhotoComponent'; 26import screenManager from '@ohos/base/src/main/ets/manager/ScreenManager'; 27import { GridScrollBar } from '@ohos/base/src/main/ets/components/scrollBar/GridScrollBar'; 28import broadcastManager from '@ohos/base/src/main/ets/manager/BroadcastManager'; 29import { ThirdSelectBarModel } from '../model/ThirdSelectBarModel'; 30import { GroupItemDataSource } from '@ohos/base/src/main/ets/vm/GroupItemDataSource'; 31import { MediaDataItem } from '@ohos/base/src/main/ets/data/MediaDataItem'; 32import { MediaConstants } from '@ohos/base/src/main/ets/constants/MediaConstants'; 33import { terminateSelfWithResult } from '@ohos/base/src/main/ets/utils/AbilityUtils'; 34import { LazyItem } from '@ohos/base/src/main/ets/vm/ItemDataSource'; 35import { CameraGridItemComponent } from './CameraGridItemComponent' 36import { SelectUtil } from '@ohos/base/src/main/ets/utils/SelectUtil'; 37import { ThirdSelectedPanel } from './ThirdSelectedPanel'; 38import { showToast } from '@ohos/base/src/main/ets/utils/UiUtil'; 39import { getResourceString } from '@ohos/base/src/main/ets/utils/ResourceUtils'; 40// Third Select Album Page 41 42const TAG = "ThirdSelectPhotoGridPage" 43 44@Entry 45@Component 46struct ThirdSelectPhotoGridPage { 47 @Provide @Watch('updateActionBar') selectedCount: number = 0; 48 @Provide('isSelectedMode') @Watch('updateActionBar') isMultiPick: boolean = false; 49 @Provide moreMenuList: Array<Action> = new Array<Action>(); 50 @Provide broadCast: Broadcast = new Broadcast(); 51 @Provide isShow: boolean = true; 52 isActive = false; 53 title: any; 54 @State isEmpty: boolean = false; 55 @StorageLink('isSplitMode') isSplitMode: boolean = screenManager.isSplitMode(); 56 @StorageLink('leftBlank') leftBlank: [number, number, number, number] = [0, 0, 0, 0]; 57 DEFAULT_TOAST_DURATION = 2000; 58 isFromWallpaper: boolean; 59 @Provide @Watch('updateActionBar') maxSelectCount: number = Constants.DEFAULT_MAX_THIRD_SELECT_COUNT; 60 @State gridRowCount: number = 0; 61 @State isHideScrollBar: boolean = true; 62 isFromFa: boolean = false; 63 isFromFaPhoto: boolean = false; 64 scroller: Scroller = new Scroller(); 65 private appBroadcast: Broadcast = broadcastManager.getBroadcast(); 66 private barModel: ThirdSelectBarModel = new ThirdSelectBarModel(); 67 private groupDataSource: GroupItemDataSource = new GroupItemDataSource(); 68 private albumId: string; 69 @State actionBarProp: ActionBarProp = new ActionBarProp(); 70 bundleName: string = ""; 71 filterMediaType: number = MediaConstants.SELECT_TYPE_ALL; 72 isSelectPhotoGrid: boolean = true; 73 @Provide isOriginalChecked: boolean = false; 74 @State isSelectUpperLimited: boolean = false; 75 76 updateActionBar(): void { 77 this.actionBarProp = this.barModel.createActionBar(this.bundleName == "" ? Action.BACK : Action.CANCEL, this.title, this.isMultiPick, 78 this.selectedCount, this.maxSelectCount, this.isSelectPhotoGrid); 79 } 80 81 onMenuClicked(action: Action) { 82 Log.info(TAG, `onMenuClicked, action: ${action.actionID}`); 83 switch (action) { 84 case Action.BACK: 85 router.back(); 86 case Action.CANCEL: 87 Log.info(TAG, 'click cancel'); 88 let abilityResult = { 89 'resultCode': 0, 90 'want': { 91 'parameters': { 92 'select-item-list': [] 93 } 94 } 95 }; 96 terminateSelfWithResult(abilityResult) 97 break; 98 case Action.OK: 99 this.setPickResult(); 100 break; 101 case Action.NAVIGATION_ALBUMS: 102 router.push({ 103 uri: 'feature/thirdSelect/view/ThirdSelectAlbumSetPage', 104 params: { 105 isMultiPick: this.isMultiPick, 106 isFromFa: this.isFromFa, 107 isFromFaPhoto: true, 108 } 109 }); 110 break; 111 default: 112 break; 113 } 114 } 115 116 private initGridRowCount(): void { 117 let contentWidth = screenManager.getWinWidth(); 118 let margin = 0; 119 let maxThumbWidth = px2vp(Constants.GRID_IMAGE_SIZE) * Constants.GRID_MAX_SIZE_RATIO; 120 this.gridRowCount = Math.max(Constants.GRID_MIN_COUNT, Math.ceil(((contentWidth - Constants.NUMBER_2 * margin) 121 + Constants.GRID_GUTTER) / (maxThumbWidth + Constants.GRID_GUTTER))); 122 Log.info(TAG, `initGridRowCount contentWidth: ${contentWidth}`); 123 } 124 125 aboutToAppear(): void { 126 let param = router.getParams(); 127 if (param != null) { 128 Log.info(TAG, `itemId: ${param.itemId}`); 129 this.title = param.itemDisplayName; 130 if (param.itemId) { 131 this.groupDataSource.setAlbumId(param.itemId.toString()); 132 this.albumId = param.itemId.toString() 133 } 134 this.bundleName = new String(param.bundleName).valueOf(); 135 this.isMultiPick = new Boolean(param.isMultiPick).valueOf(); 136 this.isFromFa = new Boolean(param.isFromFa).valueOf(); 137 this.isFromFaPhoto = new Boolean(param.isFromFaPhoto).valueOf(); 138 if (!!param.maxSelectCount && param.maxSelectCount > 0) { 139 this.maxSelectCount = new Number(param.maxSelectCount).valueOf() || 0 140 } 141 if (param.filterMediaType) { 142 this.filterMediaType = new Number(param.filterMediaType).valueOf(); 143 Log.info(TAG, `filterMediaType: ${this.filterMediaType}`) 144 } 145 } 146 if (this.isFromFa || this.isFromFaPhoto) { 147 this.filterMediaType = MediaConstants.SELECT_TYPE_IMAGE; 148 AppStorage.SetOrCreate(Constants.FORM_ITEM_NAME, param.itemName); 149 AppStorage.SetOrCreate(Constants.FORM_ITEM_ALBUM_ID, param.itemId); 150 AppStorage.SetOrCreate(Constants.FORM_ITEM_DISPLAY_NAME, param.itemDisplayName); 151 } 152 if(this.maxSelectCount) { 153 this.filterMediaType = MediaConstants.SELECT_TYPE_IMAGE; 154 } 155 this.groupDataSource.setSelectType(this.filterMediaType); 156 Log.info(TAG, `ThirdSelectPhotoGridPage isMultiPick: ${this.isMultiPick},\ 157 isFromWallpaper: ${param.isFromWallpaper}, maxSelectCount: ${this.maxSelectCount}, filterMediaType: ${this.filterMediaType}`); 158 this.groupDataSource.reloadGroupItemData(true).then((isEmpty: boolean) => { 159 this.isEmpty = isEmpty; 160 this.selectedCount = this.groupDataSource.getSelectedCount(); 161 this.groupDataSource.notifyDataReload(); 162 this.isHideScrollBar = (this.groupDataSource.totalCount() <= Constants.GRID_SCROLL_BAR_VISIBLE_THRESHOLD) 163 }) 164 this.initGridRowCount(); 165 166 this.onMenuClicked = this.onMenuClicked.bind(this); 167 this.broadCast.on(BroadcastConstants.SELECT, (index: number) => this.onSelect(index)); 168 this.broadCast.on(BroadcastConstants.JUMP_THIRD_PHOTO_BROWSER, (name: string, item: MediaDataItem) => { 169 this.jumpToThirdPhotoBrowser(name, item); 170 }) 171 this.broadCast.on(Constants.ON_LOADING_FINISHED, 172 (size: number) => { 173 Log.info(TAG, `ON_LOADING_FINISHED size: ${size}`); 174 this.isEmpty = size == 0; 175 Log.info(TAG, `isEmpty: ${this.isEmpty}`) 176 }); 177 this.isActive = true; 178 179 this.updateActionBar(); 180 } 181 182 onPageShow() { 183 this.appBroadcast.emit(BroadcastConstants.THIRD_ROUTE_PAGE, []); 184 this.isShow = true; 185 this.onActive(); 186 } 187 188 onPageHide() { 189 this.isShow = false; 190 this.onInActive(); 191 } 192 193 private onActive() { 194 if (!this.isActive) { 195 Log.info(TAG, 'onActive'); 196 this.isActive = true; 197 } 198 } 199 200 private onInActive() { 201 if (this.isActive) { 202 Log.info(TAG, 'onInActive'); 203 this.isActive = false; 204 } 205 } 206 207 private async onSelect(index: number) { 208 Log.info(TAG, "onSelect"); 209 let lastSelectedCount = this.selectedCount; 210 this.selectedCount = this.groupDataSource.getSelectedCount(); 211 if (lastSelectedCount == this.selectedCount && this.selectedCount >= this.maxSelectCount) { 212 let toastMsg = await getResourceString($r('app.string.up_to_limit_tips')); 213 showToast(toastMsg); 214 return; 215 } 216 this.isSelectUpperLimited = this.selectedCount >= this.maxSelectCount; 217 this.groupDataSource.onDataUpdate(index); 218 } 219 220 private jumpToThirdPhotoBrowser(name: string, item: MediaDataItem) { 221 let children: MediaDataItem[] = this.groupDataSource.getItems(); 222 let targetIndex = children.indexOf(item); 223 if (targetIndex == Constants.NOT_FOUND) { 224 Log.warn(TAG, 'targetIndex is not found'); 225 return; 226 } 227 AppStorage.SetOrCreate(Constants.APP_KEY_PHOTO_BROWSER, children); 228 router.push({ 229 uri: 'feature/thirdSelect/view/ThirdSelectPhotoBrowser', 230 params: { 231 position: targetIndex, 232 bundleName: this.bundleName, 233 transition: name, 234 isFromFa: this.isFromFa, 235 albumId: this.albumId, 236 isMultiPick: this.isMultiPick, 237 isSelectUpperLimited: this.isSelectUpperLimited 238 } 239 }) 240 } 241 242 aboutToDisappear(): void { 243 this.broadCast.off(null, null); 244 } 245 246 build() { 247 Column() { 248 ActionBar({ 249 actionBarProp: $actionBarProp, 250 onMenuClicked: this.onMenuClicked 251 }) 252 if (this.isEmpty && this.isFromFa) { 253 NoPhotoComponent({ title: $r('app.string.no_distributed_photo_head_title_album') }) 254 } 255 Grid(this.scroller) { 256 if (!this.isFromFa) { 257 GridItem() { 258 CameraGridItemComponent({ 259 bundleName: this.bundleName, 260 filterMediaType: this.filterMediaType 261 }) 262 } 263 .aspectRatio(1) 264 } 265 LazyForEach(this.groupDataSource, (item: LazyItem<MediaDataItem>) => { 266 GridItem() { 267 ImageGridItemComponent({ 268 lazyItem: item, 269 mediaItem: item.get(), 270 pageName: Constants.PHOTO_TRANSITION_ALBUM, 271 isThird: true, 272 isSelectUpperLimited: $isSelectUpperLimited 273 }) 274 } 275 .aspectRatio(1) 276 }, (item: LazyItem<MediaDataItem>) => item == null && item.get() ? JSON.stringify(item) : item.getHashCode()) 277 } 278 .columnsTemplate('1fr '.repeat(this.gridRowCount)) 279 .columnsGap(Constants.GRID_GUTTER) 280 .rowsGap(Constants.GRID_GUTTER) 281 .cachedCount(Constants.GRID_CACHE_ROW_COUNT) 282 .layoutWeight(1) 283 284 if (this.isMultiPick) { 285 Column() { 286 ThirdSelectedPanel({ 287 onMenuClicked: this.onMenuClicked, 288 groupDataSource: this.groupDataSource 289 }) 290 } 291 .width("100%") 292 .height($r('app.float.third_selected_panel_height')) 293 } 294 295 GridScrollBar({ scroller: this.scroller, isHideScrollBar: $isHideScrollBar}); 296 } 297 .backgroundColor($r('app.color.default_background_color')) 298 .padding({ 299 top: px2vp(this.leftBlank[1]), 300 bottom: px2vp(this.leftBlank[3]) 301 }) 302 } 303 304 private setPickResult(): void { 305 let uriArray = this.groupDataSource.getSelectedUris() 306 let abilityResult = { 307 'resultCode': 0, 308 'want': { 309 'parameters': { 310 'select-item-list': uriArray, 311 'isOriginal': this.isOriginalChecked 312 } 313 } 314 }; 315 Log.info(TAG, `uri: ${uriArray}`) 316 let self = this; 317 if (uriArray == null && uriArray == undefined) { 318 globalThis.appContext.terminateSelfWithResult(abilityResult).then((result) => { 319 Log.info(TAG, `terminateSelfWithResult result: ${result}`); 320 }); 321 } else { 322 SelectUtil.grantPermissionForUris(uriArray, self.bundleName); 323 try { 324 Log.info(TAG, `grant permission success.`); 325 globalThis.appContext.terminateSelfWithResult(abilityResult).then((result) => { 326 Log.info(TAG, `terminateSelfWithResult result: ${result}`); 327 }); 328 } catch (err) { 329 Log.info(TAG, `grant permission error: ${JSON.stringify(err)}`); 330 } 331 } 332 } 333} 334