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