1/* 2 * Copyright (c) 2022-2024 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 prompt from '@ohos.promptAction'; 17import router from '@ohos.router'; 18import mediaQuery from '@ohos.mediaquery'; 19import photoAccessHelper from '@ohos.file.photoAccessHelper'; 20import dataSharePredicates from '@ohos.data.dataSharePredicates'; 21import Logger from '../data/Logger'; 22 23const TAG: string = 'ChoicePhoto'; 24 25interface ChiceBuilderParam { 26 backGround: string, 27 showNumber: number 28}; 29 30@Entry 31@Component 32export struct ChoicePhotos { 33 @State whichShow: Array<boolean> = [true, false]; 34 @State medias: Array<photoAccessHelper.PhotoAsset> = []; 35 @State choiceShow: Array<Resource> = [$r('app.string.choice_photo'), $r('app.string.choice_video')]; 36 @State taskShow: Array<Resource> = [$r('app.media.photo'), $r('app.media.video')]; 37 @State textShow: Array<Resource> = [$r('app.string.photograph'), $r('app.string.take_video')]; 38 @State isShowChoices: Array<boolean> = new Array(this.medias.length).fill(false); 39 @State @Watch('choiceChange') choiceMedias: Array<photoAccessHelper.PhotoAsset> = []; 40 @State mediaUris: Array<string> = []; 41 @State isChoice: boolean = false; 42 @State nextText: string = ''; 43 @State isLand: boolean = false; 44 private listener = mediaQuery.matchMediaSync('screen and (min-aspect-ratio: 1.5) or (orientation: landscape)'); 45 onLand = (mediaQueryResult: mediaQuery.MediaQueryResult) => { 46 if (mediaQueryResult.matches) { 47 this.isLand = true 48 } else { 49 this.isLand = false 50 } 51 }; 52 53 choiceChange() { 54 if (this.choiceMedias.length > 0) { 55 this.isChoice = true 56 } else { 57 this.isChoice = false 58 } 59 } 60 61 @Builder showChoiceBuild($$: ChiceBuilderParam) { 62 Column() { 63 Text($$.showNumber === 0 ? '' : `${$$.showNumber}`) 64 .id(`select${$$.showNumber}`) 65 .fontSize(14) 66 .fontColor(Color.White) 67 .height(20) 68 .margin({ top: 2 }) 69 } 70 .width(24) 71 .height(24) 72 .margin({ top: 6, right: 6 }) 73 .borderRadius(15) 74 .border({ width: 1, style: BorderStyle.Solid, color: Color.White }) 75 .backgroundColor($$.backGround) 76 } 77 78 async getFileAssetsFromType(mediaType: photoAccessHelper.PhotoType) { 79 Logger.info(TAG, `getFileAssetsFromType`); 80 let context = getContext(this); 81 let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context); 82 let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates(); 83 predicates.equalTo('media_type', mediaType); 84 let fetchOptions: photoAccessHelper.FetchOptions = { 85 fetchColumns: ['date_added', 'duration'], 86 predicates: predicates 87 }; 88 89 try { 90 let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = 91 await phAccessHelper.getAssets(fetchOptions); 92 Logger.info(TAG, 'fetchResult success'); 93 if (fetchResult !== undefined) { 94 Logger.info(TAG, `fetchFileResult = ${JSON.stringify(fetchResult)}, ${fetchResult.getCount()}`); 95 if (fetchResult.getCount() > 0) { 96 this.medias = await fetchResult.getAllObjects(); 97 Logger.info(TAG, `this.medias = ${JSON.stringify(this.medias)}`); 98 } 99 } 100 } catch (err) { 101 Logger.error(TAG, 'getAssets failed, message = ' + JSON.stringify(err)); 102 } 103 } 104 105 async convertResourceToString(resource: Resource) { 106 Logger.info(TAG, `convertResourceToString result = ${getContext(this).resourceManager.getStringSync(resource)}`); 107 return getContext(this).resourceManager.getStringSync(resource); 108 } 109 110 getMaxHeight(): ConstraintSizeOptions { 111 if (!this.isLand && this.isChoice) { 112 return { maxHeight: '64%' }; 113 } else if (!this.isLand && !this.isChoice) { 114 return { maxHeight: '75.5%' }; 115 } else if (this.isLand && this.isChoice) { 116 return { maxHeight: '60%' }; 117 } else if (this.isLand && !this.isChoice) { 118 return { maxHeight: '71%' }; 119 }else { 120 return {}; 121 } 122 } 123 124 async aboutToAppear() { 125 Logger.info(TAG, `aboutToAppear`); 126 this.listener.on('change', this.onLand); 127 this.nextText = await this.convertResourceToString($r('app.string.next')); 128 this.getFileAssetsFromType(photoAccessHelper.PhotoType.IMAGE); 129 } 130 131 build() { 132 Column() { 133 Row() { 134 Image($r('app.media.back')) 135 .width(44) 136 .height(24) 137 .objectFit(ImageFit.Contain) 138 .onClick(() => { 139 router.back() 140 }) 141 142 Text($r('app.string.recently_added')) 143 .fontColor(Color.Black) 144 .fontSize(22) 145 .margin({ left: 120 }) 146 .textAlign(TextAlign.Center) 147 148 Image($r('app.media.drop_down')) 149 .width(30) 150 .height(32) 151 .objectFit(ImageFit.Contain) 152 153 Blank() 154 155 Button(`${this.nextText} ${this.isChoice ? `(${this.choiceMedias.length})` : ''}`) 156 .id('nextStep') 157 .fontSize(20) 158 .height(32) 159 .backgroundColor(this.isChoice === true ? '#E92F4F' : '#fffa8e8e') 160 .margin({ right: 10 }) 161 .borderRadius(20) 162 .onClick(() => { 163 if (this.isChoice === false) { 164 return 165 } 166 this.mediaUris = this.choiceMedias.map((item) => { 167 return item.uri 168 }) 169 router.pushUrl({ 170 url: 'pages/Index', 171 params: { mediaUris: this.mediaUris, isShowCamera: true } 172 173 }) 174 }) 175 } 176 .width('100%') 177 .height(35) 178 .padding({ left: 14 }) 179 .margin({ top: 20 }) 180 181 Column() { 182 Row() { 183 ForEach(this.choiceShow, (item: Resource, index) => { 184 Column() { 185 Text(item) 186 .fontSize(20) 187 .fontWeight(500) 188 .fontColor(this.whichShow[index] === true ? '#0000000' : '#99182431') 189 .onClick(() => { 190 this.whichShow.fill(false) 191 this.whichShow[index] = true 192 this.medias = [] 193 if (index == 0) { 194 this.getFileAssetsFromType(photoAccessHelper.PhotoType.IMAGE); 195 } else { 196 prompt.showDialog({ message: $r('app.string.user_tip') }); 197 this.choiceMedias = []; 198 this.isShowChoices = new Array(this.medias.length).fill(false); 199 this.getFileAssetsFromType(photoAccessHelper.PhotoType.VIDEO); 200 } 201 }) 202 if (this.whichShow[index]) { 203 Divider() 204 .vertical(false) 205 .strokeWidth(3) 206 .color('#ffff0000') 207 .lineCap(LineCapStyle.Round) 208 .width('40%') 209 .margin({ top: 4 }) 210 } 211 } 212 .width('30%') 213 .id(`type${index}`) 214 }) 215 } 216 .margin({ top: 20 }) 217 } 218 219 Scroll() { 220 Column() { 221 Grid() { 222 ForEach(this.medias, (item: photoAccessHelper.PhotoAsset, index) => { 223 GridItem() { 224 Stack({ alignContent: Alignment.TopEnd }) { 225 Image(item.uri) 226 .id(`image${index + 1}`) 227 .width('100%') 228 .height('100%') 229 .borderRadius(10) 230 .objectFit(ImageFit.Fill) 231 if (this.isShowChoices[index]) { 232 this.showChoiceBuild({ backGround: '#fffc0303', showNumber: this.choiceMedias.indexOf(item) + 1 }); 233 } else { 234 this.showChoiceBuild({ backGround:'#ffb7b4b4', showNumber: 0 }); 235 } 236 } 237 .width('100%') 238 .height('100%') 239 .onClick(() => { 240 this.isShowChoices[index] = !this.isShowChoices[index] 241 if (this.isShowChoices[index]) { 242 if (this.choiceMedias.length > 5) { 243 prompt.showDialog({ message: $r('app.string.choice_number') }) 244 this.isShowChoices[index] = !this.isShowChoices[index] 245 return 246 } 247 this.choiceMedias.push(item) 248 } else { 249 if (this.choiceMedias.indexOf(item) != -1) { 250 this.choiceMedias.splice(this.choiceMedias.indexOf(item), 1) 251 } 252 } 253 }) 254 } 255 .aspectRatio(1) 256 }) 257 } 258 .columnsTemplate('1fr 1fr 1fr 1fr') 259 .columnsGap(8) 260 .rowsGap(8) 261 } 262 .height('100%') 263 .width('95%') 264 .margin({ top: 8 }) 265 } 266 .margin({ top: 20 }) 267 .width('100%') 268 .constraintSize(this.getMaxHeight()) 269 .backgroundColor('#fff5f3f3') 270 271 if (this.isChoice) { 272 Grid() { 273 ForEach(this.choiceMedias, (item: photoAccessHelper.PhotoAsset, index) => { 274 GridItem() { 275 Stack({ alignContent: Alignment.TopEnd }) { 276 Image(item.uri) 277 .id(`selected${index + 1}`) 278 .width('100%') 279 .height(70) 280 .borderRadius(10) 281 Image($r('app.media.delete')) 282 .id(`deleteImage${index + 1}`) 283 .width(20) 284 .height(20) 285 .margin({ top: 5, right: 5 }) 286 .onClick(() => { 287 for (let i = 0;i < this.medias.length; i++) { 288 if (this.medias[i] === this.choiceMedias[index]) { 289 this.isShowChoices[i] = false 290 } 291 } 292 this.choiceMedias.splice(index, 1) 293 }) 294 } 295 .width('100%') 296 } 297 }, (item: photoAccessHelper.PhotoAsset) => item.uri ) 298 } 299 .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr') 300 .columnsGap(8) 301 .rowsGap(8) 302 .margin({ top: 8 }) 303 .width('95%') 304 .height(70) 305 306 Divider() 307 .vertical(false) 308 .strokeWidth(1) 309 .color('#ffd9d5d6') 310 .lineCap(LineCapStyle.Round) 311 .width('100%') 312 .margin({ top: 8 }) 313 } 314 315 Row() { 316 ForEach(this.taskShow, (item: Resource, index) => { 317 Column() { 318 Image(item) 319 .width(30) 320 .height(30) 321 322 Text(this.textShow[index]) 323 .fontSize(14) 324 .fontColor('#99182431') 325 .margin({ top: 2 }) 326 } 327 .width('50%') 328 }) 329 } 330 .margin({ top: 8 }) 331 } 332 } 333} 334