1bea4f105Sopenharmony_ci/* 2bea4f105Sopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3bea4f105Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4bea4f105Sopenharmony_ci * you may not use this file except in compliance with the License. 5bea4f105Sopenharmony_ci * You may obtain a copy of the License at 6bea4f105Sopenharmony_ci * 7bea4f105Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8bea4f105Sopenharmony_ci * 9bea4f105Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10bea4f105Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11bea4f105Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12bea4f105Sopenharmony_ci * See the License for the specific language governing permissions and 13bea4f105Sopenharmony_ci * limitations under the License. 14bea4f105Sopenharmony_ci */ 15bea4f105Sopenharmony_ci 16bea4f105Sopenharmony_ciimport { FilesData } from '../../databases/model/FileData'; 17bea4f105Sopenharmony_ciimport { on } from '../../base/utils/EventBus'; 18bea4f105Sopenharmony_ciimport FileAccessExec from '../../base/utils/FileAccessExec'; 19bea4f105Sopenharmony_ciimport { TREE_LAYER } from '../../base/constants/UiConstant'; 20bea4f105Sopenharmony_ciimport { FOLDER_LEVEL } from '../../base/constants/Constant'; 21bea4f105Sopenharmony_ciimport { FileUtil } from '../../base/utils/FileUtil'; 22bea4f105Sopenharmony_ciimport { ArrayUtil } from '../../base/utils/ArrayUtil'; 23bea4f105Sopenharmony_ciimport { FileBase } from '../../databases/model/base/FileBase'; 24bea4f105Sopenharmony_ciimport Logger from '../../base/log/Logger'; 25bea4f105Sopenharmony_ciimport fileAccess from '@ohos.file.fileAccess'; 26bea4f105Sopenharmony_ciimport ObjectUtil from '../../base/utils/ObjectUtil'; 27bea4f105Sopenharmony_ci 28bea4f105Sopenharmony_ci@Styles 29bea4f105Sopenharmony_cifunction pressedStyles() { 30bea4f105Sopenharmony_ci .backgroundColor($r('app.color.hicloud_hmos_bg')) 31bea4f105Sopenharmony_ci} 32bea4f105Sopenharmony_ci 33bea4f105Sopenharmony_ciconst TAG = 'TreeItem'; 34bea4f105Sopenharmony_ci 35bea4f105Sopenharmony_ci@Component 36bea4f105Sopenharmony_ciexport struct TreeItem { 37bea4f105Sopenharmony_ci fileItem: FilesData = new FilesData({}); 38bea4f105Sopenharmony_ci loadPath?: string = ''; 39bea4f105Sopenharmony_ci isNeedExpand: boolean = false; 40bea4f105Sopenharmony_ci @State iconRotate: boolean = false; 41bea4f105Sopenharmony_ci @State subFolderList: FilesData[] = []; 42bea4f105Sopenharmony_ci @Link chooseItem: FilesData; 43bea4f105Sopenharmony_ci @Link selectUri: string; 44bea4f105Sopenharmony_ci @Link selectName: string; 45bea4f105Sopenharmony_ci @Link fileList: FilesData[]; 46bea4f105Sopenharmony_ci @Link folderList: FilesData[]; 47bea4f105Sopenharmony_ci @State isShowArrow: boolean = true; 48bea4f105Sopenharmony_ci @Prop layer: number; 49bea4f105Sopenharmony_ci @State isLoading: boolean = false; 50bea4f105Sopenharmony_ci @Link @Watch('clickExpandChange') isClickExpand: boolean; 51bea4f105Sopenharmony_ci 52bea4f105Sopenharmony_ci private changeSelectItem(selectedItem: FilesData, autoShow: boolean) { 53bea4f105Sopenharmony_ci if (selectedItem) { 54bea4f105Sopenharmony_ci selectedItem.autoShow = autoShow; 55bea4f105Sopenharmony_ci this.chooseItem = selectedItem; 56bea4f105Sopenharmony_ci this.selectUri = this.chooseItem.uri; 57bea4f105Sopenharmony_ci this.selectName = this.chooseItem.fileName; 58bea4f105Sopenharmony_ci } 59bea4f105Sopenharmony_ci } 60bea4f105Sopenharmony_ci 61bea4f105Sopenharmony_ci private async executeQuery(dirUri: string, defaultExpandPath: string, call: Function) { 62bea4f105Sopenharmony_ci this.isLoading = true; 63bea4f105Sopenharmony_ci if (!this.isNeedExpand || (this.isNeedExpand && !this.isClickExpand)) { 64bea4f105Sopenharmony_ci this.changeSelectItem(this.fileItem, false); 65bea4f105Sopenharmony_ci } 66bea4f105Sopenharmony_ci 67bea4f105Sopenharmony_ci let queryRes = await this.getPickPathListFiles(dirUri, defaultExpandPath, this.fileItem.layer); 68bea4f105Sopenharmony_ci this.isLoading = false; 69bea4f105Sopenharmony_ci let subList: FilesData[] = this.fileBaseToFileData(queryRes); 70bea4f105Sopenharmony_ci let { folderList, fileList } = this.transfer(subList); 71bea4f105Sopenharmony_ci this.fileList = fileList 72bea4f105Sopenharmony_ci call(folderList); 73bea4f105Sopenharmony_ci } 74bea4f105Sopenharmony_ci 75bea4f105Sopenharmony_ci private async getPickPathListFiles(dirUri: string, expandPath: string, level: number): Promise<FileBase[]> { 76bea4f105Sopenharmony_ci let fileHelper = await FileUtil.getFileAccessHelperAsync(getContext()); 77bea4f105Sopenharmony_ci let fileInfo: fileAccess.FileInfo = await FileUtil.getFileInfoByUri(dirUri, fileHelper); 78bea4f105Sopenharmony_ci if (ObjectUtil.isNullOrUndefined(fileInfo) || !FileUtil.isFolder(fileInfo.mode)) { 79bea4f105Sopenharmony_ci Logger.e(TAG, 'uri is not folder'); 80bea4f105Sopenharmony_ci return; 81bea4f105Sopenharmony_ci } 82bea4f105Sopenharmony_ci let queryRes = FileAccessExec.getPathPickSubFiles(fileInfo, expandPath, level); 83bea4f105Sopenharmony_ci if (ObjectUtil.isNull(queryRes)) { 84bea4f105Sopenharmony_ci Logger.e(TAG, 'files is null'); 85bea4f105Sopenharmony_ci return; 86bea4f105Sopenharmony_ci } 87bea4f105Sopenharmony_ci return queryRes; 88bea4f105Sopenharmony_ci } 89bea4f105Sopenharmony_ci 90bea4f105Sopenharmony_ci transfer(list: FilesData[]) { 91bea4f105Sopenharmony_ci let folderList: FilesData[] = []; 92bea4f105Sopenharmony_ci let fileList: FilesData[] = []; 93bea4f105Sopenharmony_ci if (ArrayUtil.isEmpty(list)) { 94bea4f105Sopenharmony_ci return { folderList, fileList }; 95bea4f105Sopenharmony_ci } 96bea4f105Sopenharmony_ci for (let i = 0; i < list.length; i++) { 97bea4f105Sopenharmony_ci let fileData = list[i]; 98bea4f105Sopenharmony_ci if (fileData.isFolder) { 99bea4f105Sopenharmony_ci folderList.push(fileData); 100bea4f105Sopenharmony_ci } else { 101bea4f105Sopenharmony_ci fileList.push(fileData); 102bea4f105Sopenharmony_ci } 103bea4f105Sopenharmony_ci } 104bea4f105Sopenharmony_ci return { folderList, fileList }; 105bea4f105Sopenharmony_ci } 106bea4f105Sopenharmony_ci 107bea4f105Sopenharmony_ci fileBaseToFileData(list: FileBase[]): FilesData[] { 108bea4f105Sopenharmony_ci let fileArray: FilesData[] = []; 109bea4f105Sopenharmony_ci if (ArrayUtil.isEmpty(list)) { 110bea4f105Sopenharmony_ci return fileArray; 111bea4f105Sopenharmony_ci } 112bea4f105Sopenharmony_ci for (let i = 0; i < list.length; i++) { 113bea4f105Sopenharmony_ci let data = list[i]; 114bea4f105Sopenharmony_ci let fileData = new FilesData([]); 115bea4f105Sopenharmony_ci fileData.uri = data.uri; 116bea4f105Sopenharmony_ci fileData.fileName = data.fileName; 117bea4f105Sopenharmony_ci fileData.isFolder = data.isFolder; 118bea4f105Sopenharmony_ci fileData.size = data.fileSize; 119bea4f105Sopenharmony_ci fileData.mtime = data.modifyTime; 120bea4f105Sopenharmony_ci fileData.path = data.relativePath; 121bea4f105Sopenharmony_ci fileData.currentDir = data.currentDir; 122bea4f105Sopenharmony_ci if (data.isFolder) { 123bea4f105Sopenharmony_ci if (!ArrayUtil.isEmpty(data.subList)) { 124bea4f105Sopenharmony_ci fileData.setSubList(this.fileBaseToFileData(data.subList)); 125bea4f105Sopenharmony_ci } 126bea4f105Sopenharmony_ci } 127bea4f105Sopenharmony_ci fileArray.push(fileData); 128bea4f105Sopenharmony_ci } 129bea4f105Sopenharmony_ci return fileArray; 130bea4f105Sopenharmony_ci } 131bea4f105Sopenharmony_ci 132bea4f105Sopenharmony_ci /** 133bea4f105Sopenharmony_ci * 是否需要展开目录,如果最近保存的目录不为空,需要展开到最近保存的目录 134bea4f105Sopenharmony_ci * 135bea4f105Sopenharmony_ci * @returns true:需要展开目录 136bea4f105Sopenharmony_ci */ 137bea4f105Sopenharmony_ci needExpandPath(): boolean { 138bea4f105Sopenharmony_ci if (!this.canExpandPath() || this.isClickExpand) { 139bea4f105Sopenharmony_ci return false; 140bea4f105Sopenharmony_ci } 141bea4f105Sopenharmony_ci return FileUtil.hasSubFolder(this.loadPath, this.fileItem.currentDir); 142bea4f105Sopenharmony_ci } 143bea4f105Sopenharmony_ci 144bea4f105Sopenharmony_ci clickExpandChange() { 145bea4f105Sopenharmony_ci this.isNeedExpand = false; 146bea4f105Sopenharmony_ci this.loadPath = ''; 147bea4f105Sopenharmony_ci } 148bea4f105Sopenharmony_ci 149bea4f105Sopenharmony_ci canExpandPath(): boolean { 150bea4f105Sopenharmony_ci return this.layer <= FOLDER_LEVEL.MAX_LEVEL; 151bea4f105Sopenharmony_ci } 152bea4f105Sopenharmony_ci 153bea4f105Sopenharmony_ci loadSubFolder(subFolderList: FilesData[]) { 154bea4f105Sopenharmony_ci this.subFolderList = subFolderList; 155bea4f105Sopenharmony_ci this.folderList = this.subFolderList; 156bea4f105Sopenharmony_ci this.fileItem.setSubFolderList(subFolderList); 157bea4f105Sopenharmony_ci Logger.i(TAG, 'loadSubFolder:selectUri = ' + this.selectUri + 158bea4f105Sopenharmony_ci ' ; subFolderListSize = ' + this.subFolderList.length + 159bea4f105Sopenharmony_ci ' ; iconRotate = ' + this.iconRotate); 160bea4f105Sopenharmony_ci } 161bea4f105Sopenharmony_ci 162bea4f105Sopenharmony_ci aboutToAppear() { 163bea4f105Sopenharmony_ci on('fileMkdir', async (e) => { 164bea4f105Sopenharmony_ci if (this.selectUri === this.fileItem.uri) { 165bea4f105Sopenharmony_ci // 获取当前选中文件夹下的所有子文件 166bea4f105Sopenharmony_ci let queryArray = await this.getPickPathListFiles(this.fileItem.uri, '', this.fileItem.layer); 167bea4f105Sopenharmony_ci let subList: FilesData[] = this.fileBaseToFileData(queryArray); 168bea4f105Sopenharmony_ci let { folderList, fileList } = this.transfer(subList); 169bea4f105Sopenharmony_ci this.fileList = fileList; 170bea4f105Sopenharmony_ci // 获取当前选中文件夹下的所有子文件 171bea4f105Sopenharmony_ci this.subFolderList = folderList; 172bea4f105Sopenharmony_ci this.expandSubFolderCall(folderList); 173bea4f105Sopenharmony_ci // 查找刚刚新建的文件夹index 174bea4f105Sopenharmony_ci const index = this.subFolderList.findIndex(item => item.fileName === e.mkdirName); 175bea4f105Sopenharmony_ci if (index !== -1 && this.canExpandPath()) { 176bea4f105Sopenharmony_ci // 默认选中刚刚新建的文件夹 177bea4f105Sopenharmony_ci this.changeSelectItem(this.subFolderList[index], true); 178bea4f105Sopenharmony_ci this.iconRotate = true; 179bea4f105Sopenharmony_ci this.fileList = []; 180bea4f105Sopenharmony_ci this.folderList = []; 181bea4f105Sopenharmony_ci } 182bea4f105Sopenharmony_ci } 183bea4f105Sopenharmony_ci }) 184bea4f105Sopenharmony_ci 185bea4f105Sopenharmony_ci this.fileItem.setLayer(this.layer); 186bea4f105Sopenharmony_ci this.isNeedExpand = this.needExpandPath(); 187bea4f105Sopenharmony_ci if (this.isNeedExpand) { 188bea4f105Sopenharmony_ci Logger.i(TAG, 'NeedExpand:loadPath = ' + this.loadPath + 189bea4f105Sopenharmony_ci ' ; path = ' + this.fileItem.currentDir); 190bea4f105Sopenharmony_ci this.clickExpand(false); 191bea4f105Sopenharmony_ci } 192bea4f105Sopenharmony_ci } 193bea4f105Sopenharmony_ci 194bea4f105Sopenharmony_ci clickExpand(forceLoading: boolean) { 195bea4f105Sopenharmony_ci if (!this.isLoading) { 196bea4f105Sopenharmony_ci if (this.iconRotate) { 197bea4f105Sopenharmony_ci this.iconRotate = !this.iconRotate; 198bea4f105Sopenharmony_ci this.changeSelectItem(this.fileItem, false); 199bea4f105Sopenharmony_ci this.fileItem.subFileList = null; 200bea4f105Sopenharmony_ci this.folderList = this.fileItem.subFolderList; 201bea4f105Sopenharmony_ci } else { 202bea4f105Sopenharmony_ci if (this.canExpandPath()) { 203bea4f105Sopenharmony_ci if (this.fileItem.hasSubFolderList() && !forceLoading) { 204bea4f105Sopenharmony_ci this.changeSelectItem(this.fileItem, false); 205bea4f105Sopenharmony_ci this.fileList = this.fileItem.subFileList; 206bea4f105Sopenharmony_ci this.expandSubFolderCall(this.fileItem.getSubFolderList()); 207bea4f105Sopenharmony_ci } else { 208bea4f105Sopenharmony_ci this.executeQuery(this.fileItem.uri, this.loadPath, this.expandSubFolderCall.bind(this)); 209bea4f105Sopenharmony_ci } 210bea4f105Sopenharmony_ci } 211bea4f105Sopenharmony_ci } 212bea4f105Sopenharmony_ci } 213bea4f105Sopenharmony_ci } 214bea4f105Sopenharmony_ci 215bea4f105Sopenharmony_ci private expandSubFolderCall(subFolderList: FilesData[]) { 216bea4f105Sopenharmony_ci this.iconRotate = !this.iconRotate; 217bea4f105Sopenharmony_ci this.loadSubFolder(subFolderList); 218bea4f105Sopenharmony_ci this.isShowArrow = this.subFolderList.length !== 0; 219bea4f105Sopenharmony_ci } 220bea4f105Sopenharmony_ci 221bea4f105Sopenharmony_ci build() { 222bea4f105Sopenharmony_ci Column() { 223bea4f105Sopenharmony_ci Row() { 224bea4f105Sopenharmony_ci Image($r('app.media.hidisk_ic_list_empty_folder')) 225bea4f105Sopenharmony_ci .objectFit(ImageFit.Contain) 226bea4f105Sopenharmony_ci .renderMode(ImageRenderMode.Original) 227bea4f105Sopenharmony_ci .aspectRatio(1) 228bea4f105Sopenharmony_ci .width($r('app.float.common_size24')) 229bea4f105Sopenharmony_ci .alignSelf(ItemAlign.Center) 230bea4f105Sopenharmony_ci .margin({ right: $r('app.float.common_margin16') }) 231bea4f105Sopenharmony_ci Text(this.fileItem.fileName) 232bea4f105Sopenharmony_ci .fontSize($r('app.float.common_font_size16')) 233bea4f105Sopenharmony_ci .layoutWeight(1) 234bea4f105Sopenharmony_ci .maxLines(1) 235bea4f105Sopenharmony_ci .textOverflow({ overflow: TextOverflow.Ellipsis }) 236bea4f105Sopenharmony_ci if (this.isLoading) { 237bea4f105Sopenharmony_ci LoadingProgress() 238bea4f105Sopenharmony_ci .width($r('app.float.common_size24')) 239bea4f105Sopenharmony_ci .height($r('app.float.common_size24')) 240bea4f105Sopenharmony_ci .color($r('sys.color.ohos_id_color_text_secondary')) 241bea4f105Sopenharmony_ci } else { 242bea4f105Sopenharmony_ci Image($r('app.media.ic_arrow_right')) 243bea4f105Sopenharmony_ci .objectFit(ImageFit.Contain) 244bea4f105Sopenharmony_ci .autoResize(true) 245bea4f105Sopenharmony_ci .height($r('app.float.common_size12')) 246bea4f105Sopenharmony_ci .width($r('app.float.common_size12')) 247bea4f105Sopenharmony_ci .interpolation(ImageInterpolation.Medium) 248bea4f105Sopenharmony_ci .rotate({ z: 90, angle: this.iconRotate ? 90 : 0 }) 249bea4f105Sopenharmony_ci .visibility(this.isShowArrow ? Visibility.Visible : Visibility.None) 250bea4f105Sopenharmony_ci } 251bea4f105Sopenharmony_ci } 252bea4f105Sopenharmony_ci .width('100%') 253bea4f105Sopenharmony_ci .padding({ 254bea4f105Sopenharmony_ci top: $r('app.float.common_padding16'), 255bea4f105Sopenharmony_ci bottom: $r('app.float.common_padding16'), 256bea4f105Sopenharmony_ci right: $r('app.float.common_padding24'), 257bea4f105Sopenharmony_ci left: this.layer * TREE_LAYER + 'vp' 258bea4f105Sopenharmony_ci }) 259bea4f105Sopenharmony_ci .backgroundColor(this.selectUri === this.fileItem.uri ? $r('app.color.move_dialog_background') : '') 260bea4f105Sopenharmony_ci .stateStyles({ 261bea4f105Sopenharmony_ci pressed: pressedStyles 262bea4f105Sopenharmony_ci }) 263bea4f105Sopenharmony_ci .onClick(() => { 264bea4f105Sopenharmony_ci this.isClickExpand = true; 265bea4f105Sopenharmony_ci this.clickExpand(true); 266bea4f105Sopenharmony_ci }) 267bea4f105Sopenharmony_ci 268bea4f105Sopenharmony_ci if (this.subFolderList.length && this.iconRotate) { 269bea4f105Sopenharmony_ci ForEach(this.subFolderList, (item) => { 270bea4f105Sopenharmony_ci TreeItem({ 271bea4f105Sopenharmony_ci fileItem: item, 272bea4f105Sopenharmony_ci loadPath: this.loadPath, 273bea4f105Sopenharmony_ci chooseItem: $chooseItem, 274bea4f105Sopenharmony_ci selectUri: $selectUri, 275bea4f105Sopenharmony_ci selectName: $selectName, 276bea4f105Sopenharmony_ci layer: this.layer + 1, 277bea4f105Sopenharmony_ci folderList: $folderList, 278bea4f105Sopenharmony_ci fileList: $fileList, 279bea4f105Sopenharmony_ci isClickExpand: $isClickExpand 280bea4f105Sopenharmony_ci }) 281bea4f105Sopenharmony_ci }) 282bea4f105Sopenharmony_ci } 283bea4f105Sopenharmony_ci } 284bea4f105Sopenharmony_ci } 285bea4f105Sopenharmony_ci}