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