• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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