• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 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 worker from '@ohos.worker'
17import { FirstLevelByType } from './FirstLevelByType'
18import { SecondLevelByFold } from './SecondLevelByFold'
19import { ThirdLevelHasDetail } from '../pages/ThirdLevelHasDetail'
20import { ThirdLevelHasPic } from '../pages/ThirdLevelHasPic'
21import {
22  MenuLevel,
23  TerminateReason,
24  MediaType,
25  MediaName
26} from '../../../../../../common/src/main/ets/components/Data/Constants'
27import { FileInfo } from '../../../../../../common/src/main/ets/components/Data/FileInfo'
28import { TopPathInfo } from '../../../../../../common/src/main/ets/components/Data/TopPathInfo'
29import { terminateSelfWithResult } from '../../../../../../common/src/main/ets/components/Utils/AbilityUtils'
30import { getFirstMenu } from '../../../../../../common/src/main/ets/components/Utils/FileManagerServiceUtils'
31import { logInfo, logDebug, logError } from '../../../../../../common/src/main/ets/components/Utils/LogUtils'
32import { changeStringToType, updateTopPathInfo } from '../../../../../../common/src/main/ets/components/Utils/Utils'
33import { WarningDialog } from '../../../../../../common/src/main/ets/components/View/WarningDialog'
34
35@Entry
36@Component
37struct allIndex {
38  private TAG: string = 'Main'
39
40  build() {
41    Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.End, justifyContent: FlexAlign.SpaceBetween }) {
42      Stack({ alignContent: Alignment.Bottom }) {
43        Column() {
44        }
45        .onClick(() => {
46          globalThis.context.terminateSelf((err, data) => {
47            logInfo(this.TAG, 'terminateSelf success')
48          })
49        })
50        .width('100%')
51        .height('100%')
52
53        Index()
54      }
55      .width('100%')
56      .height('100%')
57    }
58    .backgroundColor('rgba(0,0,0,0.1)')
59    .position({ x: 0, y: 0 })
60    .width('100%')
61    .height('100%')
62  }
63}
64
65@Component
66struct Index {
67  private TAG: string = 'Main'
68  private mWorker
69  private customDialogController: CustomDialogController = new CustomDialogController({
70    builder: WarningDialog({ code: $code })
71  })
72  @State mFirstMenuData: FileInfo[] = []
73  @State mSecondMenuData: FileInfo[] = []
74  @State mThirdMenuPicData: FileInfo[] = []
75  @State mThirdMenuDetailData: FileInfo[] = []
76  @State mType: string = ''
77  @State mMenuLevel: number = MenuLevel.MENU_FIRST_LEVEL_BY_TYPE
78  @State mCurrentPath: string = ''
79  @State code: number = 2;
80  @StorageLink('startMode') mCurrentMode: string = 'choose'
81  @StorageLink('topPathInfo') topPathInfo: Array<TopPathInfo> = updateTopPathInfo([], '文件类型', '')
82  scroller: Scroller = new Scroller()
83
84  aboutToAppear() {
85    if (globalThis.debugMode) {
86      this.mFirstMenuData = getFirstMenu('')
87      logDebug(this.TAG, 'mFirstMenuData length = ' + this.mFirstMenuData.length)
88    } else {
89      logInfo(this.TAG, 'aboutToAppear')
90      this.initWork()
91      logInfo(this.TAG, 'send message to worker')
92      this.mWorker.postMessage({
93        request_data: 'getRoot',
94        device_name: 'local',
95        menu_level: this.mMenuLevel,
96        MediaType: this.mType,
97        path: this.mCurrentPath,
98        context: globalThis.context,
99      })
100    }
101  }
102
103  private initWork() {
104    if (this.mWorker == undefined) {
105      logInfo(this.TAG, 'initWorker')
106      this.mWorker = new worker.Worker('RK/ets/workers/DataWorker.js', { type: 'classic', name: 'filePicker' })
107      this.mWorker.onerror = this.onError.bind(this)
108      this.mWorker.onmessageerror = this.onMessageError.bind(this)
109      this.mWorker.onexit = this.onExit.bind(this)
110      this.mWorker.onmessage = this.onMessage.bind(this)
111    }
112  }
113
114  private onError(e): void{
115    logError(this.TAG, 'onError = ' + JSON.stringify(e))
116  }
117
118  private onMessageError(e): void{
119    logError(this.TAG, 'onMessageError = ' + JSON.stringify(e))
120  }
121
122  private onExit(): void{
123    logInfo(this.TAG, 'onExit')
124    this.mWorker = undefined
125  }
126
127  private onMessage(result) {
128    logInfo(this.TAG, 'main thread onMessage');
129    var params = result.data.params;
130    if (params.save_name && params.retCode == -17) {
131      logInfo(this.TAG, 'main thread onMessage pop-up window');
132      AlertDialog.show(
133        {
134          title: '文件已存在',
135          message: '是否覆盖原文件?',
136          primaryButton: {
137            value: '取消',
138            action: () => {
139            }
140          },
141          secondaryButton: {
142            value: '确定',
143            action: () => {
144              logInfo(this.TAG, 'main thread onMessage confirm and conver file');
145              this.mWorker.postMessage({
146                request_data: 'coverFile',
147                device_name: 'local',
148                MediaType: this.mType,
149                path: this.mCurrentPath,
150                cover_name: params.save_name,
151                context: globalThis.context,
152              })
153            }
154          },
155          cancel: () => {
156          }
157        }
158      )
159      return
160    }
161    var file = JSON.parse(String.fromCharCode.apply(null, new Uint16Array(result.data.data)));
162    if (params.request_data == 'createFile' || params.request_data == 'coverFile') {
163      if (file.code == undefined) {
164        terminateSelfWithResult(TerminateReason.SUCCESS, file)
165      } else {
166        if (params.path == 'datashare:///media/root') {
167          this.code = 2;
168          this.customDialogController.open()
169        } else {
170          this.code = file.code
171          this.customDialogController.open()
172        }
173      }
174      return
175    }
176    if (Array.isArray(file)) {
177      let listData: Array<FileInfo> = []
178      for (var index = 0;index < file.length; index++) {
179        var info = file[index]
180        let item = new FileInfo(info.name)
181        item.path = info.path
182        item.type = info.type
183        item.size = info.size
184        item.addedTime = info.added_time
185        item.modifiedTime = info.modified_time
186        if (params.menu_level == MenuLevel.MENU_FIRST_LEVEL_BY_TYPE) {
187          if (item.name == 'MEDIA_TYPE_IMAGE') {
188            item.name = '图片'
189            item.mediaType = 'image'
190            item.thumbnail = $r("app.media.ic_type_image")
191          } else if (item.name == 'MEDIA_TYPE_VIDEO') {
192            item.name = '视频'
193            item.mediaType = 'video'
194            item.thumbnail = $r("app.media.ic_type_video")
195          } else if (item.name == 'MEDIA_TYPE_AUDIO') {
196            item.name = '音乐'
197            item.mediaType = 'audio'
198            item.thumbnail = $r("app.media.ic_type_audio")
199          } else if (item.name == 'MEDIA_TYPE_FILE') {
200            item.name = '文档'
201            item.mediaType = 'file'
202            item.thumbnail = $r("app.media.ic_type_file")
203          }
204        }
205
206        if (params.menu_level == MenuLevel.MENU_THIRD_LEVEL_HAS_DETAIL) {
207          if (this.mCurrentMode == 'save' && item.type != MediaType.MEDIA_TYPE_ALBUM) {
208            break
209          }
210        }
211        listData.push(item)
212      }
213      logInfo(this.TAG, 'onMessage menu_level = ' + params.menu_level + ' request_data = ' + params.request_data)
214      if (params.menu_level == MenuLevel.MENU_FIRST_LEVEL_BY_TYPE && params.request_data == 'getRoot') {
215        logInfo(this.TAG, 'mFirstMenuData length = ' + listData.length)
216        this.mFirstMenuData = listData
217      } else if (params.menu_level == MenuLevel.MENU_SECOND_LEVEL_BY_FOLD) {
218        logInfo(this.TAG, 'mSecondMenuData length = ' + listData.length)
219        this.mSecondMenuData = listData
220      } else if (params.menu_level == MenuLevel.MENU_THIRD_LEVEL_HAS_PIC) {
221        logInfo(this.TAG, 'mThirdMenuPicData length = ' + listData.length)
222        this.mThirdMenuPicData = listData
223      } else if (params.menu_level == MenuLevel.MENU_THIRD_LEVEL_HAS_DETAIL) {
224        logInfo(this.TAG, 'mThirdMenuDetailData length = ' + listData.length)
225        if (listData.length > 0) {
226          this.mThirdMenuDetailData = listData
227        } else {
228          this.mThirdMenuDetailData = []
229        }
230      }
231    }
232  }
233
234  build() {
235    Column() {
236      TopBarArea()
237
238      Column() {
239        Column() {
240          Row() {
241            List() {
242              ForEach(this.topPathInfo, (item: TopPathInfo) => {
243                ListItem() {
244                  Row() {
245                    if (item.name != '文件类型') {
246                      Image($r("app.media.ic_public_right"))
247                        .width(12 * 1.3)
248                        .height(24 * 1.3)
249                        .margin({
250                          left: 4 * 1.3,
251                          right: 4 * 1.3
252                        })
253                    }
254
255                    Text(item.name)
256                      .height(24 * 1.3)
257                      .fontColor('#000000')
258                      .fontSize(16 * 1.3)
259                      .fontWeight(FontWeight.Medium)
260                      .opacity(item.opacity)
261                      .onClick(() => {
262                        logInfo(this.TAG, item.name + ' onClick')
263                        if (item.name == '文件类型') {
264                          updateTopPathInfo([], '文件类型', '')
265                          this.mMenuLevel = MenuLevel.MENU_FIRST_LEVEL_BY_TYPE
266                          this.mType = ''
267                        } else if (this.mMenuLevel == MenuLevel.MENU_THIRD_LEVEL_HAS_PIC || (this.mMenuLevel == MenuLevel.MENU_THIRD_LEVEL_HAS_DETAIL)) {
268                          this.topPathInfo.pop()
269                          this.topPathInfo[this.topPathInfo.length - 1].opacity = 1
270                          if (this.topPathInfo.length > 1) {
271                            var index = this.topPathInfo.length - 1
272                            this.mCurrentPath = this.topPathInfo[index].path
273                            this.mMenuLevel = MenuLevel.MENU_SECOND_LEVEL_BY_FOLD
274                          } else {
275                            this.mMenuLevel = MenuLevel.MENU_FIRST_LEVEL_BY_TYPE
276                            this.mType = ''
277                          }
278                        }
279                      })
280                  }
281                }
282              }, item => item.name.toString())
283            }
284            .padding({ right: 24 * 1.3 })
285            .listDirection(Axis.Horizontal)
286          }
287          .alignItems(VerticalAlign.Center)
288          .width('100%')
289          .height(48 * 1.3)
290          .margin({ left: 12 * 1.3, top: 4 * 1.3 })
291          .padding({ top: 13 * 1.3, bottom: 13 * 1.3 })
292
293          Scroll(this.scroller) {
294            Column() {
295              if (this.mMenuLevel == MenuLevel.MENU_FIRST_LEVEL_BY_TYPE) {
296                FirstLevelByType({
297                  mFileList: this.mFirstMenuData,
298                  mType: $mType,
299                  mMenuLevel: $mMenuLevel,
300                  mCurrentPath: $mCurrentPath,
301                  mWorker: this.mWorker,
302                })
303              } else if (this.mMenuLevel == MenuLevel.MENU_SECOND_LEVEL_BY_FOLD) {
304                SecondLevelByFold({
305                  mType: $mType,
306                  mMenuLevel: $mMenuLevel,
307                  mCurrentPath: $mCurrentPath,
308                  mWorker: this.mWorker,
309                  mFileList: $mSecondMenuData
310                })
311              } else if (this.mMenuLevel == MenuLevel.MENU_THIRD_LEVEL_HAS_PIC) {
312                ThirdLevelHasPic({
313                  mType: $mType,
314                  mMenuLevel: $mMenuLevel,
315                  mCurrentPath: $mCurrentPath,
316                  mWorker: this.mWorker,
317                  mFileList: $mThirdMenuPicData
318                })
319              } else if (this.mMenuLevel == MenuLevel.MENU_THIRD_LEVEL_HAS_DETAIL) {
320                ThirdLevelHasDetail({
321                  mType: $mType,
322                  mMenuLevel: $mMenuLevel,
323                  mCurrentPath: $mCurrentPath,
324                  mWorker: this.mWorker,
325                  mFileInfo: $mThirdMenuDetailData
326                })
327              }
328              Row() {
329              }.width('100%').height(53 * 1.3)
330            }
331            .alignItems(HorizontalAlign.Start)
332          }
333          .scrollBar(BarState.Off)
334          .scrollable(ScrollDirection.Vertical)
335        }
336        .alignItems(HorizontalAlign.Start)
337      }
338      .alignItems(HorizontalAlign.Start)
339      .height(globalThis.mainDialogHeight - 140 * 1.3)
340
341      BottomBar({
342        mCurrentPath: $mCurrentPath,
343        mMenuLevel: $mMenuLevel,
344        mType: $mType,
345        mWorker: this.mWorker
346      })
347    }
348    .padding({ left: 12 * 1.3, right: 12 * 1.3 })
349    .width('100%')
350    .height(globalThis.mainDialogHeight)
351    .border({ radius: 24 })
352    .backgroundColor('#F1F3F5')
353  }
354}
355
356@Component
357struct TopBarArea {
358  build() {
359    Row() {
360      Text('文件类型')
361        .width(98 * 1.3)
362        .height(33 * 1.3)
363        .fontSize(24 * 1.3)
364        .fontColor('#182431')
365        .fontWeight(FontWeight.Medium)
366        .margin({ left: 12 * 1.3 })
367    }
368    .height(64 * 1.3)
369    .width('100%')
370    .border({ radius: 24 })
371    .padding({ top: 8 * 1.3 })
372  }
373}
374
375@Component
376struct BottomBar {
377  private TAG: string = 'BottomBar'
378  private mWorker
379  @State currentChoseFiles: Array<string> = []
380  @Link mType: string
381  @Link mMenuLevel: number
382  @Link mCurrentPath: string
383  @StorageLink('choseFiles') @Watch('choseFileChange') choseFiles: Array<FileInfo> = []
384
385  aboutToAppear() {
386    logInfo(this.TAG, 'current choose file number = ' + this.currentChoseFiles.length)
387  }
388
389  private choseFileChange() {
390    this.currentChoseFiles = []
391    let files: Array<FileInfo> = AppStorage.Get('choseFiles')
392    files.forEach((item: FileInfo) => {
393      this.currentChoseFiles.push(item.name)
394    })
395    logInfo(this.TAG, 'current choose file number = ' + this.currentChoseFiles.length)
396  }
397
398  build() {
399    Row() {
400      Button() {
401        Text('取消')
402          .width(110 * 1.3)
403          .height(22 * 1.3)
404          .fontSize(16 * 1.3)
405          .fontWeight(FontWeight.Medium)
406          .fontColor('#007DFF')
407          .textAlign(TextAlign.Center)
408      }
409      .width(150 * 1.3)
410      .height(40 * 1.3)
411      .margin({ left: 12 * 1.3, top: 12 * 1.3, bottom: 24 * 1.3 })
412      .backgroundColor('#E5E8EA')
413      .onClick((event: ClickEvent) => {
414        terminateSelfWithResult(TerminateReason.NO_ACTION, '')
415        AppStorage.Set('choseFiles', [])
416      })
417
418      if (globalThis.startMode == 'save') {
419        Button() {
420          Text($r("app.string.btn_save"))
421            .width(110 * 1.3)
422            .height(22 * 1.3)
423            .fontSize(16 * 1.3)
424            .fontWeight(FontWeight.Medium)
425            .fontColor('#007DFF')
426            .textAlign(TextAlign.Center)
427            .opacity(this.mMenuLevel != MenuLevel.MENU_FIRST_LEVEL_BY_TYPE ? 1 : 0.4)
428        }
429        .backgroundColor(this.mMenuLevel != MenuLevel.MENU_FIRST_LEVEL_BY_TYPE ? '#E5E8EA' : '#ECEEF0')
430        .margin({
431          left: 12 * 1.3,
432          top: 12 * 1.3,
433          bottom: 24 * 1.3
434        })
435        .height(40 * 1.3)
436        .width(150 * 1.3)
437        .stateEffect(this.mMenuLevel == MenuLevel.MENU_FIRST_LEVEL_BY_TYPE ? false : true)
438        .onClick((event: ClickEvent) => {
439          this.mWorker.postMessage({
440            request_data: 'createFile',
441            device_name: 'local',
442            menu_level: this.mMenuLevel,
443            MediaType: this.mType,
444            path: this.mCurrentPath,
445            save_name: globalThis.saveFile,
446            context: globalThis.context,
447          })
448        })
449      } else {
450        Button() {
451          Text($r("app.string.btn_upload"))
452            .width(110 * 1.3)
453            .height(22 * 1.3)
454            .fontSize(16 * 1.3)
455            .fontWeight(FontWeight.Medium)
456            .fontColor('#007DFF')
457            .textAlign(TextAlign.Center)
458            .opacity(this.choseFiles.length != 0 ? 1 : 0.4)
459        }
460        .backgroundColor(this.choseFiles.length != 0 ? '#E5E8EA' : '#ECEEF0')
461        .stateEffect(this.choseFiles.length != 0)
462        .margin({
463          left: 12 * 1.3,
464          top: 12 * 1.3,
465          bottom: 24 * 1.3
466        })
467        .height(40 * 1.3)
468        .width(150 * 1.3)
469        .onClick(() => {
470          let result: string = ''
471          this.choseFiles.forEach((item: FileInfo) => {
472            result += item.path + ';'
473          })
474          terminateSelfWithResult(TerminateReason.SUCCESS, result)
475          AppStorage.Set('choseFiles', [])
476        })
477      }
478    }
479    .height(76 * 1.3)
480    .width('100%')
481    .backgroundColor('#F1F3F5')
482  }
483}